dcmjs-org / dcmjs

Javascript implementation of DICOM manipulation
https://dcmjs.netlify.com/
MIT License
287 stars 108 forks source link

Order of tags gets messed up when edition DICOM SEG #365

Open emelalkim opened 10 months ago

emelalkim commented 10 months ago
          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 commented 10 months ago

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 commented 10 months ago

@pieper any ideas?

pieper commented 9 months ago

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.

emelalkim commented 9 months ago

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?

pieper commented 9 months ago

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.