def convertData(self, plugin, loadable): node = plugin.load(loadable) dcmFile = loadable.files[0] seriesNumber = self.dicomDatabase.fileValue(dcmFile, "0020,0011") patientID = self.dicomDatabase.fileValue(dcmFile, "0010,0020") studyDate = self.dicomDatabase.fileValue(dcmFile, "0008,0020") studyTime = self.dicomDatabase.fileValue(dcmFile, "0008,0030")[0:4] if node: storageNode = node.CreateDefaultStorageNode() studyID = '{}_{}_{}'.format(patientID, studyDate, studyTime) dirName = os.path.join(self.outputDir, studyID, "RESOURCES", seriesNumber, "Reconstructions") xmlName = os.path.join(dirName, seriesNumber + '.xml') try: os.makedirs(dirName) except: pass DICOMLib.DICOMCommand("dcm2xml", [dcmFile, xmlName]).start() nrrdName = os.path.join(dirName, seriesNumber + ".nrrd") # print(nrrdName) storageNode.SetFileName(nrrdName) storageNode.WriteData(node) if self.copyDICOM: fileCount = 0 dirName = os.path.join(self.outputDir, studyID, "RESOURCES", seriesNumber, "DICOM") try: os.makedirs(dirName) except: pass for dcm in loadable.files: shutil.copy(dcm, os.path.join(dirName, "%06d.dcm" % fileCount)) fileCount = fileCount + 1 else: print('No node!')
def createDICOMFileForScene(self): """ Export the scene data: - first to a directory using the utility in the mrmlScene - create a zip file using the application logic - create secondary capture based on the sample dataset - add the zip file as a private creator tag TODO: confirm that resulting file is valid - may need to change the CLI to include more parameters or do a new implementation ctk/DCMTK See: http://sourceforge.net/apps/mediawiki/gdcm/index.php?title=Writing_DICOM """ # set up temp directories and files self.dicomDirectory = tempfile.mkdtemp('', 'dicomExport', slicer.app.temporaryPath) self.sceneDirectory = os.path.join(self.dicomDirectory,'scene') os.mkdir(self.sceneDirectory) # known to be unique self.imageFile = os.path.join(self.dicomDirectory, "scene.jpg") self.zipFile = os.path.join(self.dicomDirectory, "scene.zip") self.dumpFile = os.path.join(self.dicomDirectory, "dicom.dump") self.sdbFile = os.path.join(self.dicomDirectory, "SlicerDataBundle.dcm") # Clean up paths on Windows (some commands and operations are not performed properly with mixed slash and backslash) self.dicomDirectory = self.dicomDirectory.replace('\\','/') self.sceneDirectory = self.sceneDirectory.replace('\\','/') # otherwise invalid zip file is created on Windows (with the same size strangely) self.imageFile = self.imageFile.replace('\\','/') self.zipFile = self.zipFile.replace('\\','/') self.dumpFile = self.dumpFile.replace('\\','/') self.sdbFile = self.sdbFile.replace('\\','/') # get the screen image self.progress('Saving Image...') image = ctk.ctkWidgetsUtils.grabWidget(slicer.util.mainWindow()) image.save(self.imageFile) imageReader = vtk.vtkJPEGReader() imageReader.SetFileName(self.imageFile) imageReader.Update() #add storage node for each storable node in the scene, add file name if file name doesn't exist # TODO: this could be moved to appLogic.SaveSceneToSlicerDataBundleDirectory lnodes = slicer.mrmlScene.GetNodesByClass("vtkMRMLLinearTransformNode") lnodes.UnRegister(slicer.mrmlScene) lnum = lnodes.GetNumberOfItems() for itemNum in range(lnum): print(itemNum) node = lnodes.GetItemAsObject(itemNum) snode = node.GetStorageNode() if snode is None: print("something is none") snode = node.CreateDefaultStorageNode() slicer.mrmlScene.AddNode(snode) node.SetAndObserveStorageNodeID(snode.GetID()) if snode.GetFileName() is None: snode.SetFileName(node.GetID()+".h5") # save the scene to the temp dir self.progress('Saving Scene...') appLogic = slicer.app.applicationLogic() appLogic.SaveSceneToSlicerDataBundleDirectory(self.sceneDirectory, imageReader.GetOutput()) # make the zip file self.progress('Making zip...') appLogic.Zip(self.zipFile, self.sceneDirectory) zipSize = os.path.getsize(self.zipFile) # now create the dicom file # - create the dump (capture stdout) # cmd = "dcmdump --print-all --write-pixel %s %s" % (self.dicomDirectory, self.referenceFile) self.progress('Making dicom reference file...') if not self.referenceFile: # set reference file the first file found in the DICOM database self.getFirstFileInDatabase() # if there is still no reference file, then there are no files in the database, cannot continue if not self.referenceFile: logging.error('No reference file! DICOM database is empty') return False args = ['--print-all', '--write-pixel', self.dicomDirectory, self.referenceFile] dump = DICOMLib.DICOMCommand('dcmdump', args).start() # append this to the dumped output and save the result as self.dicomDirectory/dcm.dump # with %s as self.zipFile and %d being its size in bytes zipSizeString = "%d" % zipSize # hack: encode the file zip file size as part of the creator string # because none of the normal types (UL, DS, LO) seem to survive # the dump2dcm step (possibly due to the Unknown nature of the private tag) creatorString = "3D Slicer %s" % zipSizeString candygram = """(cadb,0010) LO [%s] # %d, 1 PrivateCreator (cadb,1008) LO [%s] # 4, 1 Unknown Tag & Data (cadb,1010) OB =%s # %d, 1 Unknown Tag & Data """ % (creatorString, len(creatorString), zipSizeString, self.zipFile, zipSize) dump = str(dump) + candygram logging.debug('dumping to: %s/dump.dcm' % self.dicomDirectory, 'w') fp = open('%s/dump.dcm' % self.dicomDirectory, 'w') fp.write(dump) fp.close() self.progress('Encapsulating Scene in DICOM Dump...') args = [ '%s/dump.dcm' % self.dicomDirectory, '%s/template.dcm' % self.dicomDirectory, '--generate-new-uids', '--overwrite-uids', '--ignore-errors'] DICOMLib.DICOMCommand('dump2dcm', args).start() # now create the Secondary Capture data set # cmd = "img2dcm -k 'InstanceNumber=1' -k 'SeriesDescription=Slicer Data Bundle' -df %s/template.dcm %s %s" % (self.dicomDirectory, self.imageFile, self.sdbFile) args = [ '-k', 'InstanceNumber=1', '-k', 'StudyDescription=Slicer Scene Export', '-k', 'SeriesDescription=Slicer Data Bundle', '--dataset-from', '%s/template.dcm' % self.dicomDirectory, self.imageFile, self.sdbFile] self.progress('Creating DICOM Binary File...') DICOMLib.DICOMCommand('img2dcm', args).start() self.progress('Done') return True
def createDICOMFileForScene(self, parameters): """ Export the scene data: - first to a directory using the utility in the mrmlScene - create a zip file using the application logic - create secondary capture based on the sample dataset - add the zip file as a private creator tag TODO: confirm that resulting file is valid - may need to change the CLI to include more parameters or do a new implementation ctk/DCMTK See: http://sourceforge.net/apps/mediawiki/gdcm/index.php?title=Writing_DICOM """ # set up temp directories and files self.dicomDirectory = tempfile.mkdtemp('', 'dicomExport', slicer.app.temporaryPath) self.sceneDirectory = os.path.join(self.dicomDirectory, 'scene') os.mkdir(self.sceneDirectory) # known to be unique self.imageFile = os.path.join(self.dicomDirectory, "scene.jpg") self.zipFile = os.path.join(self.dicomDirectory, "scene.zip") self.dumpFile = os.path.join(self.dicomDirectory, "dicom.dump") self.sdbFile = os.path.join(self.dicomDirectory, "SlicerDataBundle.dcm") # get the screen image self.progress('Saving Image...') pixmap = qt.QPixmap.grabWidget(slicer.util.mainWindow()) pixmap.save(self.imageFile) imageReader = vtk.vtkJPEGReader() imageReader.SetFileName(self.imageFile) imageReader.Update() # save the scene to the temp dir self.progress('Saving Scene...') appLogic = slicer.app.applicationLogic() appLogic.SaveSceneToSlicerDataBundleDirectory(self.sceneDirectory, imageReader.GetOutput()) # make the zip file self.progress('Making zip...') appLogic.Zip(self.zipFile, self.sceneDirectory) zipSize = os.path.getsize(self.zipFile) # now create the dicom file # - create the dump (capture stdout) # cmd = "dcmdump --print-all --write-pixel %s %s" % (self.dicomDirectory, self.referenceFile) self.progress('Making dicom reference file...') if not self.referenceFile: self.parametersFromStudy() args = [ '--print-all', '--write-pixel', self.dicomDirectory, self.referenceFile ] dump = DICOMLib.DICOMCommand('dcmdump', args).start() # append this to the dumped output and save the result as self.dicomDirectory/dcm.dump # with %s as self.zipFile and %d being its size in bytes zipSizeString = "%d" % zipSize candygram = """(cadb,0010) LO [3D Slicer Lollipop] # %d, 1 PrivateCreator (cadb,1008) UL [%s] # 4, 1 Unknown Tag & Data (cadb,1010) OB =%s # %d, 1 Unknown Tag & Data """ % (len('3D Slicer Lollipop'), zipSizeString, self.zipFile, zipSize) dump = dump + candygram fp = open('%s/dump.dcm' % self.dicomDirectory, 'w') fp.write(dump) fp.close() self.progress('Encapsulating Scene in DICOM Dump...') args = [ '%s/dump.dcm' % self.dicomDirectory, '%s/template.dcm' % self.dicomDirectory, '--generate-new-uids', '--overwrite-uids', '--ignore-errors' ] DICOMLib.DICOMCommand('dump2dcm', args).start() # now create the Secondary Capture data set # cmd = "img2dcm -k 'InstanceNumber=1' -k 'SeriesDescription=Slicer Data Bundle' -df %s/template.dcm %s %s" % (self.dicomDirectory, self.imageFile, self.sdbFile) args = [ '-k', 'InstanceNumber=1', '-k', 'StudyDescription=Slicer Scene Export', '-k', 'SeriesDescription=Slicer Data Bundle', '--dataset-from', '%s/template.dcm' % self.dicomDirectory, self.imageFile, self.sdbFile ] self.progress('Creating DICOM Binary File...') DICOMLib.DICOMCommand('img2dcm', args).start() self.progress('Done') return True
import DICOMLib, sys, slicer, os dcmfile = sys.argv[1] dcmdump = DICOMLib.DICOMCommand('dcmdump', [dcmfile]) dump = str(dcmdump.start()).replace("\\r", "\r").replace("\\n", "\n").splitlines() found_private_tag = False for line in dump: line = line.split(' ') if line[0] == '(2001,1003)': if line[-1] == "DiffusionBFactor": found_private_tag = True break if not found_private_tag: raise Exception("Could not find 'DiffusionBFactor' " "private tag reading file '%s' using 'dcmdump' !" % dcmfile)
def createDICOMFileForScene(self): """ Export the scene data: - first to a directory using the utility in the mrmlScene - create a zip file using the application logic - create secondary capture based on the sample dataset - add the zip file as a private creator tag TODO: confirm that resulting file is valid - may need to change the CLI to include more parameters or do a new implementation ctk/DCMTK See: http://sourceforge.net/apps/mediawiki/gdcm/index.php?title=Writing_DICOM """ # set up temp directories and files if self.saveDirectoryPath is None: self.saveDirectoryPath = tempfile.mkdtemp('', 'dicomExport', slicer.app.temporaryPath) self.zipFile = os.path.join(self.saveDirectoryPath, "scene.zip") self.dumpFile = os.path.join(self.saveDirectoryPath, "dump.dcm") self.templateFile = os.path.join(self.saveDirectoryPath, "template.dcm") self.sdbFile = os.path.join(self.saveDirectoryPath, "SlicerDataBundle.dcm") if self.studyDescription is None: self.studyDescription = 'Slicer Scene Export' if self.seriesDescription is None: self.seriesDescription = 'Slicer Data Bundle' # get the screen image if not specified if self.imageFile is None: self.progress('Saving Image...') self.imageFile = os.path.join(self.saveDirectoryPath, "scene.jpg") image = ctk.ctkWidgetsUtils.grabWidget(slicer.util.mainWindow()) image.save(self.imageFile) imageReader = vtk.vtkJPEGReader() imageReader.SetFileName(self.imageFile) imageReader.Update() # Clean up paths on Windows (some commands and operations are not performed properly with mixed slash and backslash) self.saveDirectoryPath = self.saveDirectoryPath.replace('\\', '/') self.imageFile = self.imageFile.replace('\\', '/') self.zipFile = self.zipFile.replace('\\', '/') self.dumpFile = self.dumpFile.replace('\\', '/') self.templateFile = self.templateFile.replace('\\', '/') self.sdbFile = self.sdbFile.replace('\\', '/') # save the scene to the temp dir self.progress('Saving scene into MRB...') if not slicer.mrmlScene.WriteToMRB(self.zipFile, imageReader.GetOutput()): logging.error('Failed to save scene into MRB file: ' + self.zipFile) return False zipSize = os.path.getsize(self.zipFile) # now create the dicom file # - create the dump (capture stdout) # cmd = "dcmdump --print-all --write-pixel %s %s" % (self.saveDirectoryPath, self.referenceFile) self.progress('Making dicom reference file...') logging.info('Using reference file ' + str(self.referenceFile)) args = [ '--print-all', '--write-pixel', self.saveDirectoryPath, self.referenceFile ] dumpByteArray = DICOMLib.DICOMCommand('dcmdump', args).start() dump = str(dumpByteArray.data(), encoding='utf-8') # append this to the dumped output and save the result as self.saveDirectoryPath/dcm.dump # with %s as self.zipFile and %d being its size in bytes zipSizeString = "%d" % zipSize # hack: encode the file zip file size as part of the creator string # because none of the normal types (UL, DS, LO) seem to survive # the dump2dcm step (possibly due to the Unknown nature of the private tag) creatorString = "3D Slicer %s" % zipSizeString candygram = """(cadb,0010) LO [%s] # %d, 1 PrivateCreator (cadb,1008) LO [%s] # 4, 1 Unknown Tag & Data (cadb,1010) OB =%s # %d, 1 Unknown Tag & Data """ % (creatorString, len(creatorString), zipSizeString, self.zipFile, zipSize) dump = dump + candygram logging.debug('dumping to: %s' % self.dumpFile) fp = open(self.dumpFile, 'w') fp.write(dump) fp.close() self.progress('Encapsulating scene in DICOM dump...') args = [ self.dumpFile, self.templateFile, '--generate-new-uids', '--overwrite-uids', '--ignore-errors' ] DICOMLib.DICOMCommand('dump2dcm', args).start() # now create the Secondary Capture data set # cmd = "img2dcm -k 'InstanceNumber=1' -k 'SeriesDescription=Slicer Data Bundle' -df %s/template.dcm %s %s" % (self.saveDirectoryPath, self.imageFile, self.sdbFile) args = [ '-k', 'InstanceNumber=1', '-k', 'StudyDescription=%s' % str(self.studyDescription), '-k', 'SeriesDescription=%s' % str(self.seriesDescription), '--dataset-from', self.templateFile, self.imageFile, self.sdbFile ] argIndex = 6 for key, value in self.optionalTags.items(): args.insert(argIndex, '-k') tagNameValue = f'{str(key)}={str(value)}' args.insert(argIndex + 1, tagNameValue) argIndex += 2 self.progress('Creating DICOM binary file...') DICOMLib.DICOMCommand('img2dcm', args).start() self.progress('Deleting temporary files...') os.remove(self.zipFile) os.remove(self.dumpFile) os.remove(self.templateFile) self.progress('Done') return True
def createDICOMFileForScene(self, parameters): """ Export the scene data: - first to a directory using the utility in the mrmlScene - create a zip file using python utility - create secondary capture based on the sample dataset - add the zip file as a private creator tag TODO: confirm that resulting file is valid - may need to change the CLI to include more parameters or do a new implementation ctk/DCMTK See: http://sourceforge.net/apps/mediawiki/gdcm/index.php?title=Writing_DICOM """ # set up temp directories and files self.dicomDirectory = tempfile.mkdtemp('', 'dicomExport', slicer.app.temporaryPath) self.sceneDirectory = os.path.join(self.dicomDirectory,'scene') os.mkdir(self.sceneDirectory) # known to be unique self.imageFile = os.path.join(self.dicomDirectory, "scene.jpg") self.zipFile = os.path.join(self.dicomDirectory, "scene.zip") self.dumpFile = os.path.join(self.dicomDirectory, "dicom.dump") self.sdbFile = os.path.join(self.dicomDirectory, "SlicerDataBundle.dcm") # get the screen image pixmap = qt.QPixmap.grabWidget(slicer.util.mainWindow()) pixmap.save(self.imageFile) imageReader = vtk.vtkJPEGReader() imageReader.SetFileName(self.imageFile) imageReader.Update() # save the scene to the temp dir appLogic = slicer.app.applicationLogic() appLogic.SaveSceneToSlicerDataBundleDirectory(self.sceneDirectory, imageReader.GetOutput()) # make the zip file zip = zipfile.ZipFile( self.zipFile, "w", zipfile.ZIP_DEFLATED ) start = len(self.sceneDirectory) + 1 for root, subdirs, files in os.walk(self.sceneDirectory): for f in files: filePath = os.path.join(root,f) archiveName = filePath[start:] zip.write(filePath, archiveName) zip.close() zipSize = os.path.getsize(self.zipFile) # now create the dicom file # - create the dump (capture stdout) # cmd = "dcmdump --print-all --write-pixel %s %s" % (self.dicomDirectory, self.referenceFile) if not self.referenceFile: self.parametersFromStudy() args = ['--print-all', '--write-pixel', self.dicomDirectory, self.referenceFile] dump = DICOMLib.DICOMCommand('dcmdump', args).start() # append this to the dumped output and save the result as self.dicomDirectory/dcm.dump #with %s as self.zipFile and %d being its size in bytes candygram = """(cadb,0010) LO [3D Slicer Candygram] # 20, 1 PrivateCreator (cadb,1008) OB =%s # %d, 1 Unknown Tag & Data """ % (self.zipFile, zipSize) dump = dump + candygram fp = open('%s/dump.dcm' % self.dicomDirectory, 'w') fp.write(dump) fp.close() # cmd = "dump2dcm %s/dump.dcm %s/template.dcm" % (self.dicomDirectory, self.dicomDirectory) args = ['%s/dump.dcm' % self.dicomDirectory, '%s/template.dcm' % self.dicomDirectory] DICOMLib.DICOMCommand('dump2dcm', args).start() # now create the SC data set # cmd = "img2dcm -k 'InstanceNumber=1' -k 'SeriesDescription=Slicer Data Bundle' -df %s/template.dcm %s %s" % (self.dicomDirectory, self.imageFile, self.sdbFile) args = ['-k', 'InstanceNumber=1', '-k', 'SeriesDescription=Slicer Data Bundle', '-df', '%s/template.dcm' % self.dicomDirectory, self.imageFile, self.sdbFile] DICOMLib.DICOMCommand('img2dcm', args).start()