Esempio n. 1
0
  def mapSOPClassUIDToDICOMQuantityAndUnits(self, classUID):

    MRname2UID = {
        "MR Image Storage": "1.2.840.10008.5.1.4.1.1.4",
        "Enhanced MR Image Storage": "1.2.840.10008.5.1.4.1.1.4.1",
        "Legacy Converted Enhanced MR Image Storage": "1.2.840.10008.5.1.4.1.1.4.4"
        }

    CTname2UID = {
        "CT Image Storage": "1.2.840.10008.5.1.4.1.1.2",
        "Enhanced CT Image Storage": "1.2.840.10008.5.1.4.1.1.2.1",
        "Legacy Converted Enhanced CT Image Storage": "1.2.840.10008.5.1.4.1.1.2.2"
        }

    quantity = None
    units = None

    # Note more specialized definitions can be specified for MR by more
    # specialized plugins, see codes 110800 and on in
    # http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_D.html
    if classUID in MRname2UID.values():
      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning("110852", "DCM", "MR signal intensity")
      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning("1", "UCUM", "no units")

    if classUID in CTname2UID.values():
      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning("112031", "DCM", "Attenuation Coefficient")
      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning("[hnsf'U]", "UCUM", "Hounsfield unit")

    return (quantity, units)
 def _downloadTestData(self):
   """ download DICOM PET scan and add to DICOM database
   """ 
   import urllib
   quantity = slicer.vtkCodedEntry()
   quantity.SetFromString('CodeValue:126400|CodingSchemeDesignator:DCM|CodeMeaning:Standardized Uptake Value')
   units = slicer.vtkCodedEntry()
   units.SetFromString('CodeValue:{SUVbw}g/ml|CodingSchemeDesignator:UCUM|CodeMeaning:Standardized Uptake Value body weight')      
   url = 'http://slicer.kitware.com/midas3/download/item/257234/QIN-HEADNECK-01-0139-PET.zip'
   zipFile = 'QIN-HEADNECK-01-0139-PET.zip'
   suvNormalizationFactor = 0.00040166400000000007
   destinationDirectory = self.tempDicomDatabase
   filePath = os.path.join(destinationDirectory, zipFile)
   # download dataset if necessary
   if not len(slicer.dicomDatabase.filesForSeries(self.UID)):
     filePath = os.path.join(destinationDirectory, zipFile)
     if not os.path.exists(os.path.dirname(filePath)):
       os.makedirs(os.path.dirname(filePath))
     logging.debug('Saving download %s to %s ' % (url, filePath))
     if not os.path.exists(filePath) or os.stat(filePath).st_size == 0:
       slicer.util.delayDisplay('Requesting download of %s...\n' % url, 1000)
       urllib.urlretrieve(url, filePath)
     if os.path.exists(filePath) and os.path.splitext(filePath)[1]=='.zip':
       success = slicer.app.applicationLogic().Unzip(filePath, destinationDirectory)
       if not success:
         logging.error("Archive %s was NOT unzipped successfully." %  filePath)
     indexer = ctk.ctkDICOMIndexer()
     indexer.addDirectory(slicer.dicomDatabase, destinationDirectory, None)
     indexer.waitForImportFinished()
  def mapSOPClassUIDToDICOMQuantityAndUnits(self, classUID):

    MRname2UID = {
        "MR Image Storage": "1.2.840.10008.5.1.4.1.1.4",
        "Enhanced MR Image Storage": "1.2.840.10008.5.1.4.1.1.4.1",
        "Legacy Converted Enhanced MR Image Storage": "1.2.840.10008.5.1.4.1.1.4.4"
        }

    CTname2UID = {
        "CT Image Storage": "1.2.840.10008.5.1.4.1.1.2",
        "Enhanced CT Image Storage": "1.2.840.10008.5.1.4.1.1.2.1",
        "Legacy Converted Enhanced CT Image Storage": "1.2.840.10008.5.1.4.1.1.2.2"
        }

    quantity = None
    units = None

    # Note more specialized definitions can be specified for MR by more
    # specialized plugins, see codes 110800 and on in
    # http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_D.html
    if classUID in MRname2UID.values():
      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning("110852", "DCM", "MR signal intensity")
      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning("1", "UCUM", "no units")

    if classUID in CTname2UID.values():
      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning("112031", "DCM", "Attenuation Coefficient")
      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning("[hnsf'U]", "UCUM", "Hounsfield unit")

    return (quantity, units)
Esempio n. 4
0
    def loadTestData(self):
        #download data and add to dicom database
        zipFileUrl = 'http://slicer.kitware.com/midas3/download/item/257234/QIN-HEADNECK-01-0139-PET.zip'
        zipFilePath = self.tempDataDir + '/dicom.zip'
        zipFileData = self.tempDataDir + '/dicom'
        expectedNumOfFiles = 545
        if not os.access(self.tempDataDir, os.F_OK):
            os.mkdir(self.tempDataDir)
        if not os.access(zipFileData, os.F_OK):
            os.mkdir(zipFileData)

        dicomWidget = slicer.modules.dicom.widgetRepresentation().self()
        dicomPluginCheckbox = dicomWidget.detailsPopup.pluginSelector.checkBoxByPlugin
        dicomPluginStates = {(key, value.checked)
                             for key, value in dicomPluginCheckbox.iteritems()}
        for cb in dicomPluginCheckbox.itervalues():
            cb.checked = False
        dicomPluginCheckbox['DICOMScalarVolumePlugin'].checked = True

        # Download, unzip, import, and load data. Verify loaded nodes.
        loadedNodes = {'vtkMRMLScalarVolumeNode': 1}
        with DICOMUtils.LoadDICOMFilesToDatabase(zipFileUrl, zipFilePath,
                                                 zipFileData,
                                                 expectedNumOfFiles, {},
                                                 loadedNodes) as success:
            self.assertTrue(success)
            print('loading returned true')

        self.assertEqual(
            len(slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*')), 1)
        imageNode = slicer.mrmlScene.GetFirstNodeByClass(
            'vtkMRMLScalarVolumeNode')

        for key, value in dicomPluginStates:
            dicomPluginCheckbox[key].checked = value

        # apply the SUVbw conversion factor and set units and quantity
        suvNormalizationFactor = 0.00040166400000000007
        quantity = slicer.vtkCodedEntry()
        quantity.SetFromString(
            'CodeValue:126400|CodingSchemeDesignator:DCM|CodeMeaning:Standardized Uptake Value'
        )
        units = slicer.vtkCodedEntry()
        units.SetFromString(
            'CodeValue:{SUVbw}g/ml|CodingSchemeDesignator:UCUM|CodeMeaning:Standardized Uptake Value body weight'
        )
        multiplier = vtk.vtkImageMathematics()
        multiplier.SetOperationToMultiplyByK()
        multiplier.SetConstantK(suvNormalizationFactor)
        multiplier.SetInput1Data(imageNode.GetImageData())
        multiplier.Update()
        imageNode.GetImageData().DeepCopy(multiplier.GetOutput())
        imageNode.GetVolumeDisplayNode().SetWindowLevel(6, 3)
        imageNode.GetVolumeDisplayNode().SetAndObserveColorNodeID(
            'vtkMRMLColorTableNodeInvertedGrey')
        imageNode.SetVoxelValueQuantity(quantity)
        imageNode.SetVoxelValueUnits(units)

        return imageNode
Esempio n. 5
0
    def loadTestData(self):
        #download data and add to dicom database
        zipFileUrl = 'http://slicer.kitware.com/midas3/download/item/257234/QIN-HEADNECK-01-0139-PET.zip'
        zipFilePath = self.tempDataDir + '/dicom.zip'
        zipFileData = self.tempDataDir + '/dicom'
        expectedNumOfFiles = 545
        if not os.access(self.tempDataDir, os.F_OK):
            os.mkdir(self.tempDataDir)
        if not os.access(zipFileData, os.F_OK):
            os.mkdir(zipFileData)
            slicer.util.downloadAndExtractArchive(zipFileUrl, zipFilePath,
                                                  zipFileData,
                                                  expectedNumOfFiles)
        DICOMUtils.importDicom(zipFileData)

        # load dataset
        dicomFiles = slicer.util.getFilesInDirectory(zipFileData)
        loadablesByPlugin, loadEnabled = DICOMUtils.getLoadablesFromFileLists(
            [dicomFiles], ['DICOMScalarVolumePlugin'])
        loadedNodeIDs = DICOMUtils.loadLoadables(loadablesByPlugin)
        imageNode = slicer.mrmlScene.GetNodeByID(loadedNodeIDs[0])
        imageNode.SetSpacing(
            3.3940266832237, 3.3940266832237, 2.02490234375
        )  # mimic spacing as produced by Slicer 4.10 for which the test was originally developed
        imageNode.SetOrigin(
            285.367523193359375, 494.58682250976556816, -1873.3819580078125
        )  # mimic origin as produced by Slicer 4.10 for which the test was originally developed

        # apply the SUVbw conversion factor and set units and quantity
        suvNormalizationFactor = 0.00040166400000000007
        quantity = slicer.vtkCodedEntry()
        quantity.SetFromString(
            'CodeValue:126400|CodingSchemeDesignator:DCM|CodeMeaning:Standardized Uptake Value'
        )
        units = slicer.vtkCodedEntry()
        units.SetFromString(
            'CodeValue:{SUVbw}g/ml|CodingSchemeDesignator:UCUM|CodeMeaning:Standardized Uptake Value body weight'
        )
        multiplier = vtk.vtkImageMathematics()
        multiplier.SetOperationToMultiplyByK()
        multiplier.SetConstantK(suvNormalizationFactor)
        multiplier.SetInput1Data(imageNode.GetImageData())
        multiplier.Update()
        imageNode.GetImageData().DeepCopy(multiplier.GetOutput())
        imageNode.GetVolumeDisplayNode().SetWindowLevel(6, 3)
        imageNode.GetVolumeDisplayNode().SetAndObserveColorNodeID(
            'vtkMRMLColorTableNodeInvertedGrey')
        imageNode.SetVoxelValueQuantity(quantity)
        imageNode.SetVoxelValueUnits(units)

        return imageNode
  def loadTestData(self):
    self.patienName = 'QIN-HEADNECK-01-0139'
    #download data and add to dicom database
    zipFileUrl = 'http://slicer.kitware.com/midas3/download/item/257234/QIN-HEADNECK-01-0139-PET.zip'
    zipFilePath = self.tempDataDir+'/dicom.zip'
    zipFileData = self.tempDataDir+'/dicom'
    expectedNumOfFiles = 545
    if not os.access(self.tempDataDir, os.F_OK):
      os.mkdir(self.tempDataDir)
    if not os.access(zipFileData, os.F_OK):
      os.mkdir(zipFileData)

    dicomWidget = slicer.modules.dicom.widgetRepresentation().self()
    dicomPluginCheckbox =  dicomWidget.detailsPopup.pluginSelector.checkBoxByPlugin
    dicomPluginStates = {(key,value.checked) for key,value in dicomPluginCheckbox.iteritems()}
    for cb in dicomPluginCheckbox.itervalues(): cb.checked=False
    dicomPluginCheckbox['DICOMScalarVolumePlugin'].checked = True

    # Download, unzip, import, and load data. Verify loaded nodes.
    loadedNodes = {'vtkMRMLScalarVolumeNode':1}
    with DICOMUtils.LoadDICOMFilesToDatabase(zipFileUrl, zipFilePath, zipFileData, expectedNumOfFiles, {}, loadedNodes) as success:
      self.assertTrue(success)
      print ('loading returned true')

    self.assertEqual( len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ), 1 )
    imageNode = slicer.mrmlScene.GetFirstNodeByClass('vtkMRMLScalarVolumeNode')

    for key,value in dicomPluginStates:
      dicomPluginCheckbox[key].checked=value

    # apply the SUVbw conversion factor and set units and quantity
    suvNormalizationFactor = 0.00040166400000000007
    quantity = slicer.vtkCodedEntry()
    quantity.SetFromString('CodeValue:126400|CodingSchemeDesignator:DCM|CodeMeaning:Standardized Uptake Value')
    units = slicer.vtkCodedEntry()
    units.SetFromString('CodeValue:{SUVbw}g/ml|CodingSchemeDesignator:UCUM|CodeMeaning:Standardized Uptake Value body weight')
    multiplier = vtk.vtkImageMathematics()
    multiplier.SetOperationToMultiplyByK()
    multiplier.SetConstantK(suvNormalizationFactor)
    multiplier.SetInput1Data(imageNode.GetImageData())
    multiplier.Update()
    imageNode.GetImageData().DeepCopy(multiplier.GetOutput())
    imageNode.GetVolumeDisplayNode().SetWindowLevel(6,3)
    imageNode.GetVolumeDisplayNode().SetAndObserveColorNodeID('vtkMRMLColorTableNodeInvertedGrey')
    imageNode.SetVoxelValueQuantity(quantity)
    imageNode.SetVoxelValueUnits(units)

    return imageNode
Esempio n. 7
0
    def loadTestData(self):
        self.patienName = 'UNIFORMITY^Bio-mCT'

        #download data and add to dicom database
        zipFileUrl = 'https://github.com/QIICR/SlicerPETPhantomAnalysis/releases/download/test-data/PETCylinderPhantom.zip'
        zipFilePath = self.tempDataDir + '/dicom.zip'
        zipFileData = self.tempDataDir + '/dicom'
        expectedNumOfFiles = 171
        if not os.access(self.tempDataDir, os.F_OK):
            os.mkdir(self.tempDataDir)
        if not os.access(zipFileData, os.F_OK):  # download DICOM test dataset
            os.mkdir(zipFileData)
            slicer.util.downloadAndExtractArchive(zipFileUrl, zipFilePath,
                                                  zipFileData,
                                                  expectedNumOfFiles)
        DICOMUtils.importDicom(zipFileData)

        # load dataset
        dicomFiles = slicer.util.getFilesInDirectory(zipFileData)
        loadablesByPlugin, loadEnabled = DICOMUtils.getLoadablesFromFileLists(
            [dicomFiles], ['DICOMScalarVolumePlugin'])
        loadedNodeIDs = DICOMUtils.loadLoadables(loadablesByPlugin)
        imageNode = slicer.mrmlScene.GetNodeByID(loadedNodeIDs[0])

        # apply the SUVbw conversion factor and set units and quantity
        suvNormalizationFactor = 0.00012595161151
        quantity = slicer.vtkCodedEntry()
        quantity.SetFromString(
            'CodeValue:126400|CodingSchemeDesignator:DCM|CodeMeaning:Standardized Uptake Value'
        )
        units = slicer.vtkCodedEntry()
        units.SetFromString(
            'CodeValue:{SUVbw}g/ml|CodingSchemeDesignator:UCUM|CodeMeaning:Standardized Uptake Value body weight'
        )
        multiplier = vtk.vtkImageMathematics()
        multiplier.SetOperationToMultiplyByK()
        multiplier.SetConstantK(suvNormalizationFactor)
        multiplier.SetInput1Data(imageNode.GetImageData())
        multiplier.Update()
        imageNode.GetImageData().DeepCopy(multiplier.GetOutput())
        imageNode.GetVolumeDisplayNode().SetWindowLevel(6, 3)
        imageNode.GetVolumeDisplayNode().SetAndObserveColorNodeID(
            'vtkMRMLColorTableNodeInvertedGrey')
        imageNode.SetVoxelValueQuantity(quantity)
        imageNode.SetVoxelValueUnits(units)

        return imageNode
Esempio n. 8
0
 def createCodedEntry(codeValue,
                      codingScheme,
                      codeMeaning,
                      returnAsString=False):
     """Create a coded entry and return as string or vtkCodedEntry"""
     entry = slicer.vtkCodedEntry()
     entry.SetValueSchemeMeaning(codeValue, codingScheme, codeMeaning)
     return entry if not returnAsString else entry.GetAsString()
Esempio n. 9
0
  def mapSOPClassUIDToDICOMQuantityAndUnits(self, sopClassUID):

    quantity = None
    units = None

    modality = self.mapSOPClassUIDToModality(sopClassUID)
    if modality == "MR":
      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning("110852", "DCM", "MR signal intensity")
      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning("1", "UCUM", "no units")
    elif modality == "CT":
      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning("112031", "DCM", "Attenuation Coefficient")
      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning("[hnsf'U]", "UCUM", "Hounsfield unit")

    return (quantity, units)
 def getHeaderNames(self, nonEmptyKeysOnly=True):
     # Derive column header names based on: (a) DICOM information if present,
     # (b) measurement info name if present (c) measurement key as fallback.
     # Duplicate names get a postfix [1][2]... to make them unique
     # Initial and unique column header names are returned
     keys = self.getNonEmptyKeys() if nonEmptyKeysOnly else self.keys
     statistics = self.getStatistics()
     headerNames = []
     for key in keys:
         name = key
         info = statistics['MeasurementInfo'][key] if key in statistics[
             'MeasurementInfo'] else {}
         entry = slicer.vtkCodedEntry()
         dicomBasedName = False
         if info:
             if 'DICOM.DerivationCode' in info and info[
                     'DICOM.DerivationCode']:
                 entry.SetFromString(info['DICOM.DerivationCode'])
                 name = entry.GetCodeMeaning()
                 dicomBasedName = True
             elif 'DICOM.QuantityCode' in info and info[
                     'DICOM.QuantityCode']:
                 entry.SetFromString(info['DICOM.QuantityCode'])
                 name = entry.GetCodeMeaning()
                 dicomBasedName = True
             elif 'name' in info and info['name']:
                 name = info['name']
             if dicomBasedName and 'DICOM.UnitsCode' in info and info[
                     'DICOM.UnitsCode']:
                 entry.SetFromString(info['DICOM.UnitsCode'])
                 units = entry.GetCodeValue()
                 if len(units) > 0 and units[0] == '[' and units[-1] == ']':
                     units = units[1:-1]
                 if len(units) > 0: name += ' [' + units + ']'
             elif 'units' in info and info['units'] and len(
                     info['units']) > 0:
                 units = info['units']
                 name += ' [' + units + ']'
         headerNames.append(name)
     uniqueHeaderNames = list(headerNames)
     for name in set(name for name in uniqueHeaderNames
                     if uniqueHeaderNames.count(name) > 1):
         j = 1
         for i in range(len(uniqueHeaderNames)):
             if uniqueHeaderNames[i] == name:
                 uniqueHeaderNames[i] = name + ' (' + str(j) + ')'
                 j += 1
     headerNames = dict((keys[i], headerNames[i]) for i in range(len(keys)))
     uniqueHeaderNames = dict(
         (keys[i], uniqueHeaderNames[i]) for i in range(len(keys)))
     return headerNames, uniqueHeaderNames
Esempio n. 11
0
 def getHeaderNames(self, nonEmptyKeysOnly = True):
   # Derive column header names based on: (a) DICOM information if present,
   # (b) measurement info name if present (c) measurement key as fallback.
   # Duplicate names get a postfix [1][2]... to make them unique
   # Initial and unique column header names are returned
   keys = self.getNonEmptyKeys() if nonEmptyKeysOnly else self.keys
   statistics = self.getStatistics()
   headerNames = []
   for key in keys:
     name = key
     info = statistics['MeasurementInfo'][key] if key in statistics['MeasurementInfo'] else {}
     entry = slicer.vtkCodedEntry()
     dicomBasedName = False
     if info:
       if 'DICOM.DerivationCode' in info and info['DICOM.DerivationCode']:
        entry.SetFromString(info['DICOM.DerivationCode'])
        name = entry.GetCodeMeaning()
        dicomBasedName = True
       elif 'DICOM.QuantityCode' in info and info['DICOM.QuantityCode']:
         entry.SetFromString(info['DICOM.QuantityCode'])
         name = entry.GetCodeMeaning()
         dicomBasedName = True
       elif 'name' in info and info['name']:
         name = info['name']
       if dicomBasedName and 'DICOM.UnitsCode' in info and info['DICOM.UnitsCode']:
         entry.SetFromString(info['DICOM.UnitsCode'])
         units = entry.GetCodeValue()
         if len(units)>0 and units[0]=='[' and units[-1]==']': units = units[1:-1]
         if len(units)>0: name += ' ['+units+']'
       elif 'units' in info and info['units'] and len(info['units'])>0:
         name += ' ['+units+']'
     headerNames.append(name)
   uniqueHeaderNames = list(headerNames)
   for name in set(name for name in uniqueHeaderNames if uniqueHeaderNames.count(name)>1):
     j = 1
     for i in range(len(uniqueHeaderNames)):
       if uniqueHeaderNames[i]==name:
         uniqueHeaderNames[i] = name+' ('+str(j)+')'
         j += 1
   headerNames = dict((keys[i], headerNames[i]) for i in range(len(keys)))
   uniqueHeaderNames = dict((keys[i], uniqueHeaderNames[i]) for i in range(len(keys)))
   return headerNames, uniqueHeaderNames
Esempio n. 12
0
 def createCodedEntry(codeValue, codingScheme, codeMeaning, returnAsString=False):
   """Create a coded entry and return as string or vtkCodedEntry"""
   entry = slicer.vtkCodedEntry()
   entry.SetValueSchemeMeaning(codeValue, codingScheme, codeMeaning)
   return entry if not returnAsString else entry.GetAsString()
Esempio n. 13
0
    def load(self, loadable):
        """ Load the DICOM PM object
    """
        logging.debug('DICOM PM load()')
        try:
            uid = loadable.uid
            logging.debug(f'in load(): uid = {uid}')
        except AttributeError:
            return False

        self.tempDir = os.path.join(slicer.app.temporaryPath, "QIICR", "PM",
                                    self.currentDateTime, loadable.uid)
        try:
            os.makedirs(self.tempDir)
        except OSError:
            pass

        pmFileName = slicer.dicomDatabase.fileForInstance(uid)
        if pmFileName is None:
            logging.debug(
                f'Failed to get the filename from the DICOM database for {uid}'
            )
            self.cleanup()
            return False

        parameters = {
            "inputFileName": pmFileName,
            "outputDirName": self.tempDir,
        }
        try:
            pm2nrrd = slicer.modules.paramap2itkimage
        except AttributeError:
            logging.debug(
                'Unable to find CLI module paramap2itkimage, unable to load DICOM ParametricMap object'
            )
            self.cleanup()
            return False

        cliNode = None
        cliNode = slicer.cli.run(pm2nrrd,
                                 cliNode,
                                 parameters,
                                 wait_for_completion=True)
        if cliNode.GetStatusString() != 'Completed':
            logging.debug(
                'PM converter did not complete successfully, unable to load DICOM ParametricMap'
            )
            self.cleanup()
            return False

        pmNode = slicer.util.loadVolume(os.path.join(self.tempDir,
                                                     "pmap.nrrd"))

        # load the metadata JSON to retrieve volume semantics (quantity stored and units)
        with open(os.path.join(self.tempDir, "meta.json")) as metafile:
            meta = json.load(metafile)
            qJson = meta["QuantityValueCode"]
            uJson = meta["MeasurementUnitsCode"]

            quantity = slicer.vtkCodedEntry()
            quantity.SetValueSchemeMeaning(qJson["CodeValue"],
                                           qJson["CodingSchemeDesignator"],
                                           qJson["CodeMeaning"])

            units = slicer.vtkCodedEntry()
            units.SetValueSchemeMeaning(uJson["CodeValue"],
                                        uJson["CodingSchemeDesignator"],
                                        uJson["CodeMeaning"])

            pmNode.SetVoxelValueQuantity(quantity)
            pmNode.SetVoxelValueUnits(units)

            pmNode.SetAttribute("DICOM.instanceUIDs", uid)

        # create Subject hierarchy nodes for the loaded series
        self.addSeriesInSubjectHierarchy(loadable, pmNode)

        self.cleanup()
        return True
Esempio n. 14
0
  def load(self,loadable):
    """ Load the DICOM PM object
    """
    logging.debug('DICOM PM load()')
    try:
      uid = loadable.uid
      logging.debug('in load(): uid = ', uid)
    except AttributeError:
      return False

    self.tempDir = os.path.join(slicer.app.temporaryPath, "QIICR", "PM", self.currentDateTime, loadable.uid)
    try:
      os.makedirs(self.tempDir)
    except OSError:
      pass

    pmFileName = slicer.dicomDatabase.fileForInstance(uid)
    if pmFileName is None:
      logging.debug('Failed to get the filename from the DICOM database for ', uid)
      self.cleanup()
      return False

    parameters = {
      "inputFileName": pmFileName,
      "outputDirName": self.tempDir,
      }
    try:
      pm2nrrd = slicer.modules.paramap2itkimage
    except AttributeError:
      logging.debug('Unable to find CLI module paramap2itkimage, unable to load DICOM ParametricMap object')
      self.cleanup()
      return False

    cliNode = None
    cliNode = slicer.cli.run(pm2nrrd, cliNode, parameters, wait_for_completion=True)
    if cliNode.GetStatusString() != 'Completed':
      logging.debug('PM converter did not complete successfully, unable to load DICOM ParametricMap')
      self.cleanup()
      return False

    (_,pmNode) = slicer.util.loadVolume(os.path.join(self.tempDir,"pmap.nrrd"), returnNode=True)

    # load the metadata JSON to retrieve volume semantics (quantity stored and units)
    with open(os.path.join(self.tempDir,"meta.json")) as metafile:
      meta = json.load(metafile)
      qJson = meta["QuantityValueCode"]
      uJson = meta["MeasurementUnitsCode"]

      quantity = slicer.vtkCodedEntry()
      quantity.SetValueSchemeMeaning(qJson["CodeValue"], qJson["CodingSchemeDesignator"], qJson["CodeMeaning"])

      units = slicer.vtkCodedEntry()
      units.SetValueSchemeMeaning(uJson["CodeValue"], uJson["CodingSchemeDesignator"], uJson["CodeMeaning"])

      pmNode.SetVoxelValueQuantity(quantity)
      pmNode.SetVoxelValueUnits(units)

      pmNode.SetAttribute("DICOM.instanceUIDs", uid)

    # create Subject hierarchy nodes for the loaded series
    self.addSeriesInSubjectHierarchy(loadable, pmNode)

    self.cleanup()
    return True