Exemple #1
0
    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!')
Exemple #2
0
  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
Exemple #3
0
    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)
Exemple #5
0
    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
Exemple #6
0
  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()