dcmjs icon indicating copy to clipboard operation
dcmjs copied to clipboard

Order of tags gets messed up when edition DICOM SEG

Open emelalkim opened this issue 2 years ago • 7 comments

          I'd suggest something more like this:
const dcmjs = require("dcmjs");
const fs = require("fs");

const filePath = "/Users/pieper/data/public-dicom/MRHead-multiframe+seg/MRHead-multiframe.dcm"

let arrayBuffer = fs.readFileSync(filePath).buffer;

let DicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer);

const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(DicomDict.dict);

dataset.PatientName = "Name^Somebody's"

DicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);

let new_file_WriterBuffer = DicomDict.write();

fs.writeFileSync("/tmp/file.dcm", new Buffer(new_file_WriterBuffer)); 

Originally posted by @pieper in https://github.com/dcmjs-org/dcmjs/issues/64#issuecomment-504509650

Hi, We are using this method to create copies of DICOM objects with different UIDs. The MRIs are OK, but the segmentations throws this when I run dciodvfy Error - Tags out of order - trailing garbage, wrong transfer syntax, or not valid DICOM Error - MediaStorageSOPInstanceUID but missing SOPInstanceUID and not a directory Error - MediaStorageSOPClassUID but missing SOPClassUID and not a directory

I was able to reproduce it locally using this code

const dcmjs = require("dcmjs");
const fs = require("fs");

const filePath = "/Users/ealkim/bra45-4510-413-ser/orj.dcm"

let arrayBuffer = fs.readFileSync(filePath).buffer;

let DicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer);

const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(DicomDict.dict);

dataset.SeriesInstanceUID = '2.25.23542678765445654764635245765';
dataset.SOPInstanceUID = '2.25.23542678765445654764635245769';
dataset.MediaStorageSOPInstanceUID = '2.25.23542678765445654764635245769';

DicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);

let new_file_WriterBuffer = DicomDict.write();

fs.writeFileSync("/Users/ealkim/bra45-4510-413-ser/orj_editedlocal.dcm", Buffer.from(new_file_WriterBuffer)); 

emelalkim avatar Sep 12 '23 18:09 emelalkim

Sample original and edited files orj_editedlocal.dcm is the file created by using the code snippet given above edited_by_epad.dcm is the file created by ePAD using a similar code to the code snippet given above

emelalkim avatar Sep 12 '23 18:09 emelalkim

@pieper any ideas?

emelalkim avatar Sep 12 '23 20:09 emelalkim

Hi @emelalkim thanks for your patience - I think the issue is that MediaStorageSOPInstanceUID is only supposed to be in the part10 (dicom file) metaheader and not in the dataset itself.

In dcmjs that's stored in the _meta field in the the javascript object, like in this code that parses a part10 from an array of bytes. Let me know if that approach solves the issue.

pieper avatar Sep 26 '23 19:09 pieper

Hi @pieper, thank you for the feedback I tried modifying the code as below but it doesn't edit the MediaStorageSOPInstanceUID now

const fs = require("fs");

const filePath = "/Users/ealkim/bra45-4510-413-ser/orj.dcm"

let arrayBuffer = fs.readFileSync(filePath).buffer;

let DicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer);

const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(DicomDict.dict);
dataset._meta = dcmjs.data.DicomMetaDictionary.namifyDataset(DicomDict.meta);
    
dataset.SeriesInstanceUID = '2.25.23542678765445654764635245765';
dataset.SOPInstanceUID = '2.25.23542678765445654764635245769';
dataset._meta.MediaStorageSOPInstanceUID = '2.25.23542678765445654764635245769';

DicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);

let new_file_WriterBuffer = DicomDict.write();

fs.writeFileSync("/Users/ealkim/bra45-4510-413-ser/orj_editedlocal2.dcm", Buffer.from(new_file_WriterBuffer)); 

Am I doing it wrong? And I think it is actually about the data itself. I mean '2.25.23542678765445654764635245769'. There is no issue with ones 1.3... something. I believe it should be valid DICOM UID. What do you think?

emelalkim avatar Sep 26 '23 22:09 emelalkim

Hmm, either 2.25.xxx or 1.3.xxx should be fine. There are rules in the standard about what's allowed in these strings of numbers but software like dcmjs shouldn't care. (We use the 2.25 form since it's considered to be the correct way to prefix a random number, while the 1.xxx forms are related to registered prefixes).

In addition to

DicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);

Maybe you need to add

DicomDict.meta = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset._meta);

?

If it's still a problem the code to write the data shouldn't be too hard to trace through.

pieper avatar Sep 26 '23 22:09 pieper

hi @pieper, It is been quite a while but I was just able to get back to this. Adding DicomDict.meta = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset._meta); doesn't work. I get this error

/Users/ealkim/bra45-4510-413-ser/node_modules/dcmjs/build/dcmjs.js:7545
            this.view = new DataView(this.buffer);
                        ^

TypeError: First argument to DataView constructor must be an ArrayBuffer
    at new DataView (<anonymous>)

I was able to resolve my problem with adding DicomDict.meta['00020003'].Value[0] = dataset._meta.MediaStorageSOPInstanceUID; instead of that. Here is the working code

const dcmjs = require("dcmjs");
const fs = require("fs");

const filePath = "/Users/ealkim/bra45-4510-413-ser/orj.dcm"

let arrayBuffer = fs.readFileSync(filePath).buffer;

let DicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer);

const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(DicomDict.dict);
dataset._meta = dcmjs.data.DicomMetaDictionary.namifyDataset(DicomDict.meta);
    
dataset.SeriesInstanceUID = '2.25.235426787654456547646352457651';
dataset.SOPInstanceUID = '2.25.235426787654456547646352457691898';
dataset._meta.MediaStorageSOPInstanceUID = '2.25.235426787654456547646352457691898';

DicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);
DicomDict.meta['00020003'].Value[0] = dataset._meta.MediaStorageSOPInstanceUID;

let new_file_WriterBuffer = DicomDict.write();

fs.writeFileSync("/Users/ealkim/bra45-4510-413-ser/orj_editedlocal3.dcm", Buffer.from(new_file_WriterBuffer)); 

I don't know which part in the library needs to be fixed if any, and I don't have time to work on it right now but if you give me pointers I will try to work on it later

emelalkim avatar Aug 15 '24 01:08 emelalkim

I'm glad you found a good solution @emelalkim. I agree it's not clear if this requires a change in the library.

pieper avatar Aug 15 '24 15:08 pieper