PantelisGeorgiadis / dcmjs-dimse

DICOM DIMSE implementation for Node.js using the dcmjs library
MIT License
74 stars 14 forks source link

How to create .dcm file and save locally #65

Closed ctTushar closed 3 weeks ago

ctTushar commented 1 month ago

`const fs = require('fs') const crypto = require('crypto') const path = require('path') const rnBridge = require('rn-bridge') const dcmjs = require('dcmjs')

const mapExamToDataset = require('../functions/mapExamToDataset') const datasetToFile = require('../functions/datasetToFile') const sendDicom = require('../functions/sendDicom') const { DIST_PATH } = require('../constants/paths')

module.exports = class UploadExamCommand { constructor(exam, serialNumber, appVersion, image, options) { this.exam = exam this.serialNumber = serialNumber this.appVersion = appVersion this.image = image this.options = options }

execute() { const { isMultiframe } = this.options

const fileName = UploadExamCommand.generateFileName()
const filePath = path.join(DIST_PATH, fileName)

if (!fs.existsSync(DIST_PATH)) {
  fs.mkdirSync(DIST_PATH)
}

if (fs.existsSync(path.join(DIST_PATH, fileName))) {
  fs.unlinkSync(path.join(DIST_PATH, fileName))
}
const dataset = mapExamToDataset(this.image, this.probeSerialNumber, this.appVersion, this.exam, {
  isMultiframe,
})

if (saveLocally) { // assume it is true for now

  const dicomData = dcmjs.data.DicomMessage.write(dataset)
  try {
    fs.writeFileSync(filePath, Buffer.from(dicomData))
  } catch (error) {
    console.error('Error writing DICOM file:', error)
  }
}

sendDicom(dataset, this.options)

}

static generateFileName() { return ${crypto.randomBytes(20).toString('hex')}.dcm } } below is the data set JSON { "transferSyntaxUid": "1.2.840.10008.1.2.1", "elements": { "PatientID": "2.16.840.1.114556.79494184422528272155.20241021131306.3.568743.1", "PatientName": "Unknown", "PatientBirthDate": "unknown", "PatientSex": "O", "ReferringPhysicianName": "unknown", "AccessionNumber": "unknown", "StudyDescription": "", "PerformingPhysicianName": "unknown", "StudyInstanceUID": "2.16.840.1.114556.79494184422528272155.20241021131306.3.568743.1", "StudyDate": "20241021", "StudyTime": "131306.6000", "StudyID": "f6012e30-5f0d-43bd-885c-eebeed7dea5f", "Modality": "US", "SeriesInstanceUID": "2.16.840.1.114556.1.1.1.20241021T07431.48fc8941a16aa4c3fe7de495d23062a8", "SeriesNumber": "1", "SeriesDate": "20241021", "SeriesTime": "131306", "Laterality": "", "Manufacturer": "COMPANY Inc", "ManufacturerModelName": "COMPANY Device", "InstitutionName": "COMPANYINC", "SoftwareVersions": "4.2.3.13", "DeviceSerialNumber": "0116-2318-0134-67C8C9", "StationName": "COMPANY", "InstanceNumber": "1", "PatientOrientation": "", "ContentDate": "20241021", "ContentTime": "131306", "ImageType": "ORIGINAL\PRIMARY", "AcquisitionDate": "20241021", "AcquisitionTime": "131306", "AcquisitionDateTime": "20241021131306", "PlanarConfiguration": 0, "UltrasoundColorDataPresent": 1, "SamplesPerPixel": 3, "PhotometricInterpretation": "RGB", "PixelRepresentation": 0, "Rows": 2051, "Columns": 1080, "BitsAllocated": 8, "BitsStored": 8, "HighBit": 7, "PixelAspectRatio": "1\1", "LossyImageCompression": "00", "FocusDepth": "2", "SOPInstanceUID": "2.16.840.1.114556.1.1.1.20241025T07532.f0e005e185fc532e5634febaa4cf9303", "SOPClassUID": "1.2.840.10008.5.1.4.1.1.6.1", "MediaStorageSOPClassUID": "1.2.840.10008.5.1.4.1.1.6.1", "MediaStorageSOPInstanceUID": "2.16.840.1.114556.1.1.1.20241025T07532.f0e005e185fc532e5634febaa4cf9303", "SequenceOfUltrasoundRegions": [ { "RegionSpatialFormat": 1, "RegionDataType": 1, "RegionFlags": 3, "RegionLocationMinX0": 0, "RegionLocationMinY0": 0, "RegionLocationMaxX1": 1080, "RegionLocationMaxY1": 2051, "ReferencePixelX0": 540, "ReferencePixelY0": 0, "PhysicalUnitsXDirection": 3, "PhysicalUnitsYDirection": 3, "ReferencePixelPhysicalValueX": 0, "ReferencePixelPhysicalValueY": 0, "PhysicalDeltaX": 0.0076103500761035, "PhysicalDeltaY": 0 } ], "OperatorsName": "COMPANY", "SpecificCharacterSet": "ISO_IR 100", "PixelSpacing": "0.183406\0.183406", "PrivateCreator": "ABC_PRIVATE", "PixelData": [{}], "defaultOptions": { "TransferSyntaxUid": "1.2.840.10008.1.2.1", "isMultiframe": false, "PhotometricInterpretation": "RGB", "SamplesPerPixel": 3, "BitsAllocated": 8, "BitsStored": 8, "HighBit": 7 } } } `

PantelisGeorgiadis commented 1 month ago

Hello @ctTushar, Thank you for your question. If I am not mistaken, the above code snippet doesn't involve the use of dcmjs-dimse. Is that accurate?

ctTushar commented 1 month ago

@PantelisGeorgiadis currently i am trying with dcmjs, do we have same for dcmjs-dimse ? or do you have any documentation/source or link which can guide me. Thanks

PantelisGeorgiadis commented 1 month ago

Hello @ctTushar, Given a collection of elements, as the one you posted above, you can check how dcmjs-dimse is saving them in a DICOM part10 file, by following the Dataset's toFile function: https://github.com/PantelisGeorgiadis/dcmjs-dimse/blob/a98654b05386bb5c2120437969098b09f55cc0a5/src/Dataset.js#L177

ctTushar commented 1 month ago

Working thanks.

dataset.toFile(filePath, (err, data) => { if (err) { console.error('Error saving DICOM file:', err) } else { console.log('DICOM file saved successfully:', filePath, JSON.stringify(data)) } })

ctTushar commented 1 month ago

You can close this ticket. Thanks.

I have 1 more question. It regarding dicom in some PACS server the cine.dcm file are stored with green color overlay. Any idea what could cause the issue.

Below is the output

image

below is the output what is expected

image
PantelisGeorgiadis commented 1 month ago

Thank you @ctTushar! Do you mind anonymizing and sharing the cine.dcm file?

ctTushar commented 1 month ago

Let me anonymize it and give it to, in sometime.

ctTushar commented 1 month ago

@PantelisGeorgiadis here is cine.dcm sample file in zip folder

Cine file.zip

PantelisGeorgiadis commented 1 month ago

Thanks for sending your file @ctTushar. The image is encoded fine, it seems that it is your viewer's fault to present it greenish. Just drag and drop your file here: https://unpkg.com/dcmjs-imaging/build/index.html to verify.

ctTushar commented 1 month ago

On provide link you share it is rendering properly and our own created ORTHANC server too it is working fine. On client server it is creating issue.

ctTushar commented 1 month ago

if i change one tag i.e PhotometricInterpretation: 'RGB', to other value i.e 'Monochrome2' or 'YBR_FULL' on client server it color change to pink. Not sure is it our problem in code or while generating code, or it server configuration issue or what else, we have no idea.

PantelisGeorgiadis commented 1 month ago

It is not a problem of the networking code but rather one in your client's rendering code.

ctTushar commented 1 month ago

Our client has raised a concern regarding the mobile application. When sending DICOM files to PACS using C-Store from an Android device, it works fine. However, when performing the same operation from an iPhone, only a green color appears. This issue occurs specifically with Cine files, while images work fine on both platforms.

I download the file from client server and share it here, once i get it.

ctTushar commented 1 month ago

i upload same cine.dcm file on client server this is the output. Any feedback on this ?. Thanks

image
PantelisGeorgiadis commented 1 month ago

Typically, that's a colorspace conversion problem. Most often you can find this issue in ultrasounds with JPEG Baseline syntax in which, during decompression, the proper YBR to RGB conversion is not performed.

ctTushar commented 3 weeks ago

@PantelisGeorgiadis i was able to fix the colour issue when we upload image from iOS, The issue in iOS was if you notice there in snap provide the top and bottom colour is set to some other i.e white, So we explicitly added background colour to black which resolve the issue. But some how to android device it is automatically picking up black but not for iOS platform.

ctTushar commented 3 weeks ago

you can now close the ticket. Thanks for you help.

PantelisGeorgiadis commented 3 weeks ago

Can't say that I did much for you @ctTushar but it was my pleasure!