Which DICOM UIDs should be replaced while overwriting pixel data in DICOM? - uuid

I am trying to create a new DICOM file (instance) from an existing one, where I change the pixel data.
I know that I need to change some of the UIDs while replacing pixel data. Currently I am generating SOPInstanceUID, MediaStorageSOPInstanceUID and ReferencedSOPInstanceUID wherever applicable.
Are there some other UIDs that needs to be changed to get a valid DICOM file? It will be helpful if you can point me where to look for this in the standard.

Following is a quote from specifications discussing about uniqueness of UIDs:
Unique Identifiers (UIDs) provide the capability to uniquely identify a wide variety of items. They guarantee uniqueness across multiple countries, sites, vendors and equipment. Different classes of objects, instance of objects and information entities can be distinguished from one another across the DICOM universe of discourse irrespective of any semantic context.
PS 3.5 2017a - Data Structures and Encoding - 9 Unique Identifiers (UIDs)
If you are changing pixel data (changing compression (transfer syntax) to lossy or overwriting all together), you must change SOP Instance UID (0008,0018).
About Media Storage SOP Instance UID (0002,0003), as you notice, it belongs to group 2 i.e. File Meta Information header. These tags only present when you serialize the instance to hard disk. This should have same value as that of SOP Instance UID (0008,0018). So, if you change one, you should also change other. Please refer to this answer and following part in specifications:
C.12.1.1.1 SOP Class UID, SOP Instance UID
The SOP Class UID and SOP Instance UID Attributes are defined for all DICOM IODs. However, they are only encoded in Composite IODs with the Type equal to 1. See Section C.1.2.3. When encoded they shall be equal to their respective Attributes in the DIMSE Services and the File Meta Information header (see PS3.10 Media Storage).
PS3.3 2021a - Information Object Definitions - C.12.1.1.1
The Referenced SOP Instance UID (0008,1155) is reference to other instance. It depends whether you need to change this or not based on your case; generally should not be needed. Please refer to this answer for more details about Referenced SOP Instance UID.
The Transfer Syntax UID (0002,0010) needs to be changed according to the new Transfer Syntax you applied. While overwriting the pixel data, if you are changing it, change the UID accordingly.
The SOP Class UID (0008,0016) and Media Storage SOP Class UID (0002,0002) define your SOP Class. By just changing pixel data, you are not changing it. So you do not need to change this UID.
The Implementation Class UID (0002,0012) is associated with creator. No need to change.
Decision about Study Instance UID (0020,000D) and Series Instance UID (0020,000E) depends on your use case. It depends on how you want user to handle your newly created instance. Say, while creating report for Study, many implementations do not change Study IUID but do create new Series (i.e. new Series IUID).
Please refer to following answers for more details:
https://stackoverflow.com/a/46316162/5779732
https://stackoverflow.com/a/53775161/5779732

Related

How to provide visibility to users based on field criteria?

How do I provide visibility to records for users based on field criteria?
My demand is: When I have some specific object Files with some specific products the users that contact in this accounts that have this product will see this register of Files. Like:
I create a register on the object File with the field product fill with 'B'';
The account with some specific record type also has the field product filled with 'B' and 'C';
Because of that, the contacts (that are users in the community) present on this account will have access to the object File, because it contains 'B'.
How to reach this solution? I think about a trigger on the object File that will check the accounts that contain the same product, and then, create a sharing rule for that, but I don`t know if is the best option and also, because of the limit of 300. It's that any other way?
Uh, interesting one! You mean real Files (ContentDocument, ContentVersion), not some custom object, right? Files are bit tricky, normally community user would see all files attached to their account + special "Asset" files.
trigger on the object File (...) and then create a sharing rule
Don't think it'll work. Sharing rules are metadata, not data. You'd need a deployment or cheat by making API callout. But also sharing rules don't really work for community, you're supposed to use sharing sets.
You could try making ContentDocumentLinks between the file header (ContentDocument) and Account. And yes, you should be able to do it from trigger. I don't remember if there are limitations like 1 file can be linked at most to X records, this might be tricky. a change of Account's product would potentially mean lots of links to add/remove, maybe move this bit to #future / Queueable.
Alternatively you could just make all files & their folders visible in the community, maybe even for guest user (look into Asset files?). And just show / hide links to their folders based on what's on the account. Bit "security by obscurity" but well, fairly easy to do, adding/removing products wouldn't mean lots of operations. Depends if these files are somewhat sensitive or it's more about guiding the user to what they're interested in.
Ask on https://salesforce.stackexchange.com/ too, somebody can have even better ideas.

Adding additional data fields to account information in Substrate

Very new to Substrate and Rust. My understanding of the ChainState is that it acts sort of like a database which holds account numbers (in this case public keys) and their associated balances. When making a transaction, Substrate basically checks to see that you have a sufficient balance, and if so, the transaction succeeds. (This is different from the UTXO method used in Bitcoin.)
First of all, if I am wrong on the above, please correct me.
If I am correct (or at least close) I would like to find a method for associating other data with each account. I've noticed that in the demos, accounts are also associated with names, like Alice, Bob, etc. Is this kept in the ChainState, or is this something which would only be stored on one's own node?
I am trying to determine a way to associate additional data with accounts in the ChainState. For example, how could I store a name (like Alice, Bob, etc.) in the ChainState (assuming that they are only stored locally) or even other information, such as the birthday of the account owner, or their favorite author, or whatever arbitrary information?
The Chain State is just the state of everything, not necessarily connected to Account IDs. It does, among other things, store balances and such, yes, but also many other things that the chain stored one way or another.
To add custom data, you would create a new structure (map) and then map account IDs to whatever data you want. As an example:
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
/// The storage item for our proofs.
/// It maps a proof to the user who made the claim and when they made it.
Proofs: map hasher(blake2_128_concat) Vec<u8> => (T::AccountId, T::BlockNumber);
}
}
The above declares a storage map which will associate a hash with a tuple of Account and Block Number. That way, querying the hash will return those two values. You could also do the reverse and associate an AccountID with some other value, like a string (Vec<u8>).
I recommend going through this tutorial from which I took the above snippet: it will show you exactly how to add custom information into a chain.
The answer given by #Swader was very good, as it was general in scope. I will be looking into this answer more, as I try to associate more types of information. (I voted it up, but my vote isn't visible because I am relatively new to StackOverflow, at least on this account.)
After a bit more searching I also found this tutorial: Add a Pallet to Your Runtime.
This pallet happens to specifically add the ability to associate a nickname with the account ID, which was the example I gave in my question. #Swader's answer, however, was more general, and therefore both more useful and also more closely answered my question.
By the way, the nicknames are saved as hex encoded, and are returned as hex encoded as well. An easy way to check that the hex encoding is actually equivalent to the nickname which was set is to visit https://convertstring.com/EncodeDecode/HexDecode and paste in the hex string, without the initial 0x.

Should I store uploaded filename in database?

I have a database table with an autoincrement ID as primary key.
For each record of this table, I can have up to 3 files, which can be publicly available so random filename generation is not mandatory, and these files are optional.
I think I have 2 possible solutions:
Store a random generated filename in 3 nullable varchar column and store all the files in the same place:
columns: a | b | c
uploads/f6se54fse654.jpg
Don't store the filenames, but place them in specific folders and name them the same than the primary key value:
uploads/a/1.jpg
uploads/b/1.jpg
uploads/c/1.jpg
With this last solution, I know that uploads/a/1.jpg belongs to record with ID 1, and is a file of type a. But I have to check if the file exists because the files are optional.
Do you think there is a good practice in all that? Or maybe there is a better approach?
If the files you are talking about are intended to be displayed or downloaded by users (whether for visitors or for authenticated users, filtered by roles (ACL) or not), it is important to ensure (IMHO) that the user will not be able to guess other information other than the content of the concerned resource which has been sent to him. There is no perfect solution that can be applied to all cases without exception, so let's take an example to give you more explanations.
In order to enhance the security and total opacity of sensitive data, for example for the specific case of uploads/users/7/invoices/3.pdf, I think it would be wise to ensure that absolutely no one can guess the number of files that are potentially associated with the user or any other entity (because otherwise, in this example, we could imagine that there potentially are other accessible files - 1.pdf and 2.pdf). By design, we generally want to give access to files in a well defined and specific cases and context. However, this may not be the case for an image file which is intended to be seen by everyone (a profile photo, for example). That's why the context matters in some way.
If you choose to keep the auto-incremented identifiers as names to refer to your files, this can also give information about the size of the data stored in your database (/uploads/invoices/128.pdf informs that you may already have 127 invoices on your server) and potentially motivate unscrupulous people to try to reach resources that should never be fetched out of the defined context. This case may be less obvious if you choose to use some kind of unique generated identifiers (GUID).
I recommend that you read this article concerning the generation of (G)/(U)UIDs (a 128-bit hexadecimal numbers) to be stored in your database for each uploaded or created file. If you use MySQL in its latest version it is even possible to host this identifier in a binary (16) type which offers an automatic conversion to UUID, I let you read this interesting topic associated with what I refer about. It will probably output this as /uploads/invoices/b0016303-8e4f-487a-8c30-5dddf1ebf7e9.pdf which is a lot better as long as you ensure that the generated identifier is unique hash.
It does not seem useful to me here to talk about performance issues because today there are many methods for caching files or path and urls, which avoid having to make requests each time in a lot of cases where a resource is called (often ordered by their popularity rank in bigdata cases).
Last, but not least, many web and mobile platform applications (I think of Slack, Discord, Facebook, Twitter...) which store a lot of media files every day which are often associated with accounts users, both public and confidential files and information, generate a unique hash for each of them.
Twitter is using its own unique identifier string (64-bits BIGINT) generator called Twitter Snowflake which you might be interesting to read too. It is based on the UNIX epoch value which is, by definition, unique at each millisecond tick.
There isn't a global and perfect solution which can be applied for everything but I hope that this will help you as you may want to take a deeper look in this and find the "best solution" for each context and entity you'll store and link files.

Referencing previously defined items in JSON-LD

I'm trying to wrap my head around defining JSON-LD correctly for my website. The bit I'm not sure about is how to reference previously defined JSON-LD items without having to copy and paste them.
I know that each item can be given an #id property, but how should I correctly utilize it (if I even can)?
For example, suppose I create an Organization item with an #id of https://example.com/#Organization.
When I need to reference that item again, is it correct to simply specify that #id again, nothing more?
Also am I correct in assuming that I can do this even if the item isn't defined on the page that I'm referencing it?
In the case of the Organization item type, my understanding is that you should only declare it on the home page, rather than every page, so if the user is currently on the product page, and I want to reference the organization, it isn't already defined on the page I'm on, but has been declared elsewhere.
You're correct that using the same #id in different places allows you to make statements about the same thing. In fact, the JSON-LD Flattening algorithm, which is used as part of Framing, consolidates these all together in a single node object.
JSON-LD is a format for Linked Data, and it is reasonable to say that statements made about the same resource on different locations (pages) can be merged together, and if you form a Knowledge Graph from information across multiple locations, this is effectively what you're doing. A Knowledge Graph will typically reduce the JSON-LD (or other equivalent syntactic representation) to RDF Triples/Quads, where each "page" effectively defines a graph, which can be combined to create a larger Dataset. You can then query the dataset in different ways to retrieve that information, which can result in the separate statements being consolidated.
Most applications, however, will likely look for a complete definition of a resource in a single location. But for something like Organization, you could imaging that different Employee resources might be made, where there is a relation such as :Employee :worksFor :Organization, so that the page for an Organization would not expect to also list every employee in that organization, but a more comprehensive Knowledge Graph made from the merge of all of those separate resources could be used to reconstruct it.

How do I create a new customer segment in Websphere Commerce using only DB2 database queries?

How can I add a new customer segment using only the database? I know how to create customer segments in CMC, but I'm looking to automate the process of adding, say, hundreds of user segments by writing a script to do it for me. However, I can't find any information on how to create a new customer segment using only DB2 database queries.
Is there a way to create a new customer segment using nothing but DB2 database queries?
I would not recommend that you use SQL directly to create customer segments, as this makes generation of primary keys and updates of the KEYS table your responsibility. And once you take that on, Murphy's Law states that you'll get something wrong.
Your question asks how to create "hundreds of user segments". However, I'm not sure if that's what you meant, or if you meant that you had hundreds of users to add to existing segments.
If you're talking about loading hundreds of users, then I'd refer you to
this article in the Knowledge Center that explains how you can use the MemberGroupMemberMediator to load segments from e-mail addresses.
If you truly mean to create segments by data load, I'd refer you to this Knowledge Center article that shows how to create member groups. A customer segment is a member group with a particular usage type.
For reference, these are the tables involved:
MBRGRP: The base group (segment) definintion
MBRGRPCOND: This is used to define the condition if it is a rule-based segment (e.g. "all shoppers over the age of 25")
MBRGRPDESC: The NLS description (name, etc) of the segment
MBRGRPMBR: For manually defined segments, this defines the members (relationship to MEMBER table)
MBRGRPTYPE: The type of the member group (e.g. "CustomerGroup")
MBRGRPUSG: The usage code for the member group (e.g. "GeneralPurpose")
What version fixpack / fep are you working with? Have you read http://www-01.ibm.com/support/knowledgecenter/SSZLC2_7.0.0/com.ibm.commerce.management-center.doc/tasks/tsbctsegbatch.htm?lang=en
Technically, changing the DB2 database directly is not officially supported. There are things like stagingprop that depend on certain actions happening in certain ways. For example, primary keys of any rows in any table that is a part of stagingprop cannot be updated. CMC will instead do this for you as a delete and an insert when you make the change through CMC.
That said, I've seen unsupported methods like this used to update/change/create data in WebSphere Commerce databases. I don't have the information specific to how to do this for customer segments. I just caution you that it is dangerous when changing the DB2 database directly, so be sure you have backups and evaluate the impact on other processes like stagingprop or dbclean very carefully.

Resources