def getLoadablesFromRWVMFile(self, file):
        rwvLoadable = DICOMLib.DICOMLoadable()
        rwvLoadable.files.append(file)
        rwvLoadable.patientName = self.__getSeriesInformation(
            rwvLoadable.files, self.tags['patientName'])
        rwvLoadable.patientID = self.__getSeriesInformation(
            rwvLoadable.files, self.tags['patientID'])
        rwvLoadable.studyDate = self.__getSeriesInformation(
            rwvLoadable.files, self.tags['studyDate'])
        dicomFile = dicom.read_file(file)
        rwvmSeq = dicomFile.ReferencedImageRealWorldValueMappingSequence[
            0].RealWorldValueMappingSequence
        unitsSeq = rwvmSeq[0].MeasurementUnitsCodeSequence
        rwvLoadable.name = rwvLoadable.patientName + ' ' + self.convertStudyDate(
            rwvLoadable.studyDate) + ' ' + unitsSeq[0].CodeMeaning
        rwvLoadable.unitName = unitsSeq[0].CodeMeaning

        (quantity, units) = self.getQuantityAndUnitsFromDICOM(dicomFile)

        rwvLoadable.quantity = quantity
        rwvLoadable.units = units

        rwvLoadable.tooltip = rwvLoadable.name
        rwvLoadable.selected = True
        rwvLoadable.confidence = 0.90
        return [rwvLoadable]
Example #2
0
    def examineFilesMultiseries(self, files):
        """
    This strategy is similar to examineFiles(), but
    does not separate the files by individual series before
    parsing multivolumes out.
    """

        if self.detailedLogging:
            logging.debug('MultiVolumeImporterPlugin: examineMultiseries')

        loadables = []

        mvNodes = self.initMultiVolumes(files,
                                        prescribedTags=[
                                            'SeriesTime', 'AcquisitionTime',
                                            'FlipAngle', 'CardiacCycle'
                                        ])

        if self.detailedLogging:
            logging.debug(
                'MultiVolumeImporterPlugin: found {} multivolumes!'.format(
                    len(mvNodes)))

        for mvNode in mvNodes:
            tagName = mvNode.GetAttribute(
                'MultiVolume.FrameIdentifyingDICOMTagName')
            nFrames = mvNode.GetNumberOfFrames()
            orderedFiles = mvNode.GetAttribute(
                'MultiVolume.FrameFileList').split(',')

            desc = slicer.dicomDatabase.fileValue(
                orderedFiles[0],
                self.tags['studyDescription'])  # SeriesDescription
            num = slicer.dicomDatabase.fileValue(orderedFiles[0],
                                                 self.tags['seriesNumber'])
            if num != "":
                name = num + ": " + desc
            else:
                name = desc

            if self.isFrameOriginConsistent(orderedFiles, mvNode) == False:
                continue

            loadable = DICOMLib.DICOMLoadable()
            loadable.files = orderedFiles
            loadable.tooltip = name + ' - ' + str(
                nFrames) + ' frames MultiVolume by ' + tagName
            loadable.name = name
            loadable.selected = True
            loadable.multivolume = mvNode
            if tagName == 'TemporalPositionIdentifier':
                loadable.confidence = 0.9
            else:
                loadable.confidence = 1.
            loadables.append(loadable)

        return loadables
Example #3
0
    def examineFilesMultiseries(self, files):

        print('MultiVolumeImportPlugin:examineMultiseries')
        loadables = []

        mvNodes = self.initMultiVolumes(
            files,
            prescribedTags=['SeriesTime', 'AcquisitionTime', 'FlipAngle'])

        print('DICOMMultiVolumePlugin found ' + str(len(mvNodes)) +
              ' multivolumes!')

        for mvNode in mvNodes:
            tagName = mvNode.GetAttribute(
                'MultiVolume.FrameIdentifyingDICOMTagName')
            nFrames = mvNode.GetNumberOfFrames()
            orderedFiles = string.split(
                mvNode.GetAttribute('MultiVolume.FrameFileList'), ',')

            desc = slicer.dicomDatabase.fileValue(
                orderedFiles[0],
                self.tags['studyDescription'])  # SeriesDescription
            num = slicer.dicomDatabase.fileValue(orderedFiles[0],
                                                 self.tags['seriesNumber'])
            if num != "":
                name = num + ": " + desc
            else:
                name = desc

            if self.isFrameOriginConsistent(orderedFiles, mvNode) == False:
                continue

            loadable = DICOMLib.DICOMLoadable()
            loadable.files = orderedFiles
            loadable.tooltip = name + ' - ' + str(
                nFrames) + ' frames MultiVolume by ' + tagName
            loadable.name = name
            loadable.selected = True
            loadable.multivolume = mvNode
            loadable.confidence = 0.9
            loadables.append(loadable)

        return loadables
Example #4
0
    def examine(self, fileLists):
        """ Returns a list of DICOMLoadable instances
    corresponding to ways of interpreting the
    fileLists parameter.

    Top-level examine() calls various individual strategies implemented in examineFiles*().
    """
        loadables = []
        allfiles = []
        for files in fileLists:
            loadables += self.examineFiles(files)

            # this strategy sorts the files into groups
            loadables += self.examineFilesIPPAcqTime(files)

            allfiles += files

        # here all files are lumped into one list for the situations when
        # individual frames should be parsed from series
        loadables += self.examineFilesMultiseries(allfiles)
        if len(allfiles) > len(files):
            # only examineFilesIPPAcqTime again if there are multiple file groups
            loadables += self.examineFilesIPPAcqTime(allfiles)

        # this strategy sorts the files into groups
        loadables += self.examineFilesIPPInstanceNumber(allfiles)

        # If Sequences module is available then duplicate all the loadables
        # for loading them as volume sequence.
        # A slightly higher confidence value is set for volume sequence loadables,
        # therefore by default data will be loaded as volume sequence.

        if hasattr(slicer.modules, 'sequences'):

            seqLoadables = []
            for loadable in loadables:
                seqLoadable = DICOMLib.DICOMLoadable()
                seqLoadable.files = loadable.files
                seqLoadable.tooltip = loadable.tooltip.replace(
                    ' frames MultiVolume by ', ' frames Volume Sequence by ')
                seqLoadable.name = loadable.name.replace(
                    ' frames MultiVolume by ', ' frames Volume Sequence by ')
                seqLoadable.multivolume = loadable.multivolume
                seqLoadable.selected = loadable.selected

                seqLoadable.confidence = loadable.confidence

                seqLoadable.loadAsVolumeSequence = True
                seqLoadables.append(seqLoadable)

            # Among all selected loadables, the ones that are listed first will be selected by default,
            # therefore we need to prepend loadables if sequence format is preferred.
            # Determine from settings loading into sequence node should have higher confidence (selected by default).
            settings = qt.QSettings()
            sequenceFormatPreferred = (settings.value(
                "DICOM/PreferredMultiVolumeImportFormat",
                "default") == "sequence")
            if sequenceFormatPreferred:
                # prepend
                loadables[0:0] = seqLoadables
            else:
                # append
                loadables += seqLoadables

        return loadables
Example #5
0
    def examineFiles(self, files):
        """
    This is the main strategy that assumes all files (instances) belong
    to the same series, and all instances within the same frame have the same value for one of the attributes defined in self.multiVolumeTags
    """

        logging.debug("MultiVolumeImportPlugin::examine")
        """ Returns a list of DICOMLoadable instances
    corresponding to ways of interpreting the
    files parameter.
    """
        loadables = []

        # Look for series with several values in either of the volume-identifying
        #  tags in files

        # first separate individual series, then try to find multivolume in each
        # of the series (code from DICOMScalarVolumePlugin)
        subseriesLists = {}
        subseriesDescriptions = {}

        for file in files:

            value = slicer.dicomDatabase.fileValue(
                file, self.tags['seriesInstanceUID'])  # SeriesInstanceUID
            desc = slicer.dicomDatabase.fileValue(
                file, self.tags['seriesDescription'])  # SeriesDescription

            if value == "":
                value = "Unknown"

            if desc == "":
                desc = "Unknown"

            if not subseriesLists.has_key(value):
                subseriesLists[value] = []
            subseriesLists[value].append(file)
            subseriesDescriptions[value] = desc

        # now iterate over all subseries file lists and try to parse the
        # multivolumes

        for key in subseriesLists.keys():

            mvNodes = self.initMultiVolumes(subseriesLists[key])

            logging.debug('DICOMMultiVolumePlugin found ' + str(len(mvNodes)) +
                          ' multivolumes!')

            for mvNode in mvNodes:
                tagName = mvNode.GetAttribute(
                    'MultiVolume.FrameIdentifyingDICOMTagName')
                nFrames = mvNode.GetNumberOfFrames()
                orderedFiles = string.split(
                    mvNode.GetAttribute('MultiVolume.FrameFileList'), ',')

                if self.isFrameOriginConsistent(orderedFiles, mvNode) == False:
                    continue

                loadable = DICOMLib.DICOMLoadable()
                loadable.files = files
                loadable.name = subseriesDescriptions[key] + ' - as a ' + str(
                    nFrames) + ' frames MultiVolume by ' + tagName
                mvNode.SetName(subseriesDescriptions[key])
                loadable.tooltip = loadable.name
                loadable.selected = True
                loadable.multivolume = mvNode
                loadables.append(loadable)

        return loadables
Example #6
0
    def examineFilesIPPAcqTime(self, files):
        """
    This strategy first orders files into lists, where each list is
    indexed by ImagePositionPatient (IPP). Next, files within each
    list are ordered by AcquisitionTime attribute. Finally, loadable
    frames are indexed by AcquisitionTime, and files within each
    frame are ordered by IPP.
    This strategy was required to handle DSC MRI data collected on
    Siemens, tested with a DSC sequence obtained using software
    version "syngo MR B15"
    """

        loadables = []
        subseriesLists = {}
        orderedFiles = []

        desc = slicer.dicomDatabase.fileValue(
            files[0], self.tags['seriesDescription'])  # SeriesDescription

        minTime = self.tm2ms(
            slicer.dicomDatabase.fileValue(files[0],
                                           self.tags['AcquisitionTime']))
        for file in files:
            ipp = slicer.dicomDatabase.fileValue(file, self.tags['position'])
            time = self.tm2ms(
                slicer.dicomDatabase.fileValue(file,
                                               self.tags['AcquisitionTime']))
            if time < minTime:
                minTime = time
            if not subseriesLists.has_key(ipp):
                subseriesLists[ipp] = {}
            subseriesLists[ipp][time] = file

        nSlicesEqual = True
        allIPPs = subseriesLists.keys()
        for ipp in subseriesLists.keys():
            if len(subseriesLists[allIPPs[0]].keys()) != len(
                    subseriesLists[ipp].keys()):
                nSlicesEqual = False
                break

        if len(subseriesLists[allIPPs[0]].keys()) < 2 or not nSlicesEqual:
            return []

        if nSlicesEqual:
            nFrames = len(subseriesLists[allIPPs[0]].keys())
            nSlices = len(allIPPs)

            orderedFiles = [0] * nFrames * nSlices

            frameLabelsStr = ""
            frameFileListStr = ""
            frameLabelsArray = vtk.vtkDoubleArray()

            ippPositionCnt = 0
            for ipp in subseriesLists.keys():
                timesSorted = subseriesLists[ipp].keys()
                timesSorted.sort()
                timeCnt = 0
                for time in timesSorted:
                    orderedFiles[timeCnt * nSlices +
                                 ippPositionCnt] = subseriesLists[ipp][time]
                    timeCnt = timeCnt + 1
                    if ippPositionCnt == 0:
                        frameLabelsStr = frameLabelsStr + str(time -
                                                              minTime) + ','
                        frameLabelsArray.InsertNextValue(time - minTime)
                ippPositionCnt = ippPositionCnt + 1

            scalarVolumePlugin = slicer.modules.dicomPlugins[
                'DICOMScalarVolumePlugin']()
            firstFrameTime = 0
            for f in range(nFrames):
                frameFileList = orderedFiles[f * nSlices:(f + 1) * nSlices]
                svs = scalarVolumePlugin.examine([frameFileList])
                if len(svs) == 0:
                    print(
                        'Failed to parse one of the multivolume frames as scalar volume!'
                    )
                    break
                time = self.tm2ms(
                    slicer.dicomDatabase.fileValue(
                        svs[0].files[0], self.tags['AcquisitionTime']))
                if f == 0:
                    frameLabelsStr = '0,'
                    frameLabelsArray.InsertNextValue(0)
                    firstFrameTime = time
                else:
                    frameLabelsStr = frameLabelsStr + str(time -
                                                          firstFrameTime) + ','
                    frameLabelsArray.InsertNextValue(time)

            for file in orderedFiles:
                frameFileListStr = frameFileListStr + str(file) + ','

            frameLabelsStr = frameLabelsStr[:-1]
            frameFileListStr = frameFileListStr[:-1]

            mvNode = slicer.mrmlScene.CreateNodeByClass(
                'vtkMRMLMultiVolumeNode')
            mvNode.SetReferenceCount(mvNode.GetReferenceCount() - 1)
            mvNode.SetScene(slicer.mrmlScene)
            mvNode.SetAttribute("MultiVolume.FrameLabels", frameLabelsStr)
            mvNode.SetAttribute("MultiVolume.FrameIdentifyingDICOMTagName",
                                "AcquisitionTime")
            mvNode.SetAttribute("MultiVolume.ParseStrategy",
                                "AcquisitionTime+ImagePositionPatient")
            mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(nFrames))
            mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits',
                                "ms")
            # keep the files in the order by the detected tag
            # files are not ordered within the individual frames -- this will be
            # done by ScalarVolumePlugin later
            mvNode.SetAttribute('MultiVolume.FrameFileList', frameFileListStr)

            self.addAcquisitionAttributes(mvNode, frameFileList)

            mvNode.SetNumberOfFrames(nFrames)
            mvNode.SetLabelName("AcquisitionTime")
            mvNode.SetLabelArray(frameLabelsArray)

            loadable = DICOMLib.DICOMLoadable()
            loadable.files = orderedFiles
            loadable.name = desc + ' - as a ' + str(
                nFrames
            ) + ' frames MultiVolume by ImagePositionPatient+AcquisitionTime'
            mvNode.SetName(desc)
            loadable.tooltip = loadable.name
            loadable.selected = True
            loadable.multivolume = mvNode
            loadable.confidence = 1.
            loadables.append(loadable)

        return loadables
 def getLoadablePetSeriesFromRWVMFile(self, file):
   """ Returns DICOMLoadable instances associated with an RWVM object."""
   
   newLoadables = []
   dicomFile = dicom.read_file(file)
   if dicomFile.Modality == "RWV":
     refRWVMSeq = dicomFile.ReferencedImageRealWorldValueMappingSequence
     refSeriesSeq = dicomFile.ReferencedSeriesSequence
     if refRWVMSeq:
       # May have more than one RWVM value, create loadables for each
       for item in refRWVMSeq:
         rwvLoadable = DICOMLib.DICOMLoadable()
         # Get the referenced files from the database
         refImageSeq = item.ReferencedImageSequence
         instanceFiles = []
         for instance in refImageSeq:
           uid = instance.ReferencedSOPInstanceUID
           if uid:
             instanceFiles += [slicer.dicomDatabase.fileForInstance(uid)]
         # Get the Real World Values
         rwvLoadable.files = instanceFiles
         rwvLoadable.rwvFile = file
         rwvLoadable.patientName = self.__getSeriesInformation(rwvLoadable.files, self.tags['patientName'])
         rwvLoadable.patientID = self.__getSeriesInformation(rwvLoadable.files, self.tags['patientID'])
         rwvLoadable.studyDate = self.__getSeriesInformation(rwvLoadable.files, self.tags['studyDate'])
         rwvmSeq = item.RealWorldValueMappingSequence
         unitsSeq = rwvmSeq[0].MeasurementUnitsCodeSequence
         rwvLoadable.name = rwvLoadable.patientName + ' ' + self.convertStudyDate(rwvLoadable.studyDate) + ' ' + unitsSeq[0].CodeMeaning
         rwvLoadable.tooltip = rwvLoadable.name
         
         rwvLoadable.unitName = unitsSeq[0].CodeMeaning
         rwvLoadable.units = unitsSeq[0].CodeValue
         rwvLoadable.confidence = 0.90
         rwvLoadable.selected = True # added by CB
         rwvLoadable.slope = rwvmSeq[0].RealWorldValueSlope
         rwvLoadable.referencedSeriesInstanceUID = refSeriesSeq[0].SeriesInstanceUID
         
         # determine modality of referenced series
         refSeriesFiles = slicer.dicomDatabase.filesForSeries(refSeriesSeq[0].SeriesInstanceUID)
         refSeriesFile0 = dicom.read_file(refSeriesFiles[0])
         rwvLoadable.referencedModality = refSeriesFile0.Modality
         
         # add radiopharmaceutical info if PET
         if rwvLoadable.referencedModality == 'PT':
           print('Found Referenced PET series')
           ris = refSeriesFile0.RadiopharmaceuticalInformationSequence[0]
           try: # TODO Many DICOM series do not have radiopharmaceutical code sequence!
             rcs = ris.RadiopharmaceuticalCodeSequence
             if len(rcs) > 0:
               rwvLoadable.RadiopharmaceuticalCodeValue = rcs[0].CodeValue
           except AttributeError:
             print('WARNING: series does not have radiopharmaceutical code sequence.')
           try:
             rcs = ris.RadionuclideCodeSequence
             if len(rcs) > 0:
               rwvLoadable.RadionuclideCodeValue = rcs[0].CodeValue
           except AttributeError:
             print('WARNING: Cannot find radionuclide info for PET Series.')
         
         self.sortLoadableSeriesFiles(rwvLoadable)
         newLoadables.append(rwvLoadable)
           
   return newLoadables
Example #8
0
    def loadMeasurementVolumesEndOf2013(self, measurements, sampleIndex=0):
        """Load the volumes corresponding to the given measurement.
    If there is more than one sample, load the sampleIndex'th data.
    """
        import DICOMScalarVolumePlugin
        import DICOMLib

        results = {}
        m = measurements

        # load the original MR scans
        loader = DICOMScalarVolumePlugin.DICOMScalarVolumePluginClass()
        loadable = DICOMLib.DICOMLoadable()
        loadable.name = m.label
        loadable.files = m.rawFiles[sampleIndex]
        results['MR'] = loader.load(loadable)
        results['MR', "files"] = m.rawFiles[sampleIndex]

        # load the CRO-provided overall label map
        results['classmap'] = slicer.util.loadVolume(
            m.classmapFiles[sampleIndex][0], returnNode=True)[1]
        results['classmap'].SetName(m.label + "-classmap")
        results['classmap', "files"] = m.classmapFiles[sampleIndex]

        # load the semi-automated per-muscle segmentations
        volumesLogic = slicer.modules.volumes.logic()
        labelFile = m.labelFiles[sampleIndex]
        results['muscleLabel'] = volumesLogic.AddArchetypeVolume(
            labelFile, m.label + "-label", 1)
        results['muscleLabel', "files"] = labelFile

        for result in ("MR", "classmap", "muscleLabel"):
            if not results[result]:
                print('Could not load %s' % result)
                print(results[result, "files"])
                return

        # use the same physical mapping for all volumes, since
        # they should all be in the same pixel space
        # but:
        # -- the CRO provided DICOM files have embedded NULL
        #    characters in PixelSpacing so they do not always load correctly
        # -- control points are expressed in muscleIJKToRAS coordinates,
        #    but we want to export them with respect to mrIJKToRAS, so
        #    we keep muscleToMR as a 4x4 matrix to map the control points.
        mrIJKToRAS = vtk.vtkMatrix4x4()
        muscleIJKToRAS = vtk.vtkMatrix4x4()
        results['MR'].GetIJKToRASMatrix(mrIJKToRAS)
        results['muscleLabel'].GetIJKToRASMatrix(muscleIJKToRAS)
        results['classmap'].SetIJKToRASMatrix(mrIJKToRAS)
        results['muscleLabel'].SetIJKToRASMatrix(mrIJKToRAS)

        # in the file we have Pmuscle == points in muscle space
        # we want Mmusle2mr == matrix from muscle to mr space
        # thus:
        #  Pmr = Mmuscle2mr * Pmuscle
        mMuscleToMR = vtk.vtkMatrix4x4()
        # so we first map from Pmuscle to IJK, then IJK to MR
        # or:
        #  Pmr = MmrIJKToRAS * MmuscleIJKToRAS-1 * Pmuscle
        muscleIJKToRAS.Invert()
        vtk.vtkMatrix4x4.Multiply4x4(mrIJKToRAS, muscleIJKToRAS, mMuscleToMR)
        results['mMuscleToMR'] = mMuscleToMR

        # select volumes to display
        appLogic = slicer.app.applicationLogic()
        selNode = appLogic.GetSelectionNode()
        selNode.SetReferenceActiveVolumeID(results['MR'].GetID())
        selNode.SetReferenceSecondaryVolumeID(results['classmap'].GetID())
        selNode.SetReferenceActiveLabelVolumeID(results['muscleLabel'].GetID())
        appLogic.PropagateVolumeSelection()

        # set up the composite nodes and slice nodes
        compositeNodes = slicer.util.getNodes('vtkMRMLSliceCompositeNode*')
        for compositeNode in compositeNodes.values():
            compositeNode.SetForegroundOpacity(0.5)
        sliceNodes = slicer.util.getNodes('vtkMRMLSliceNode*')
        for sliceNode in sliceNodes.values():
            sliceNode.SetUseLabelOutline(True)

        layoutManager = slicer.app.layoutManager()
        layoutManager.layout = 3  # the four-up view

        # let the layout take effect and re-render new data
        slicer.app.processEvents()

        layoutManager.resetSliceViews()
        threeDView = layoutManager.threeDWidget(0).threeDView()
        threeDView.lookFromAxis(ctk.ctkAxesWidget.Anterior)
        threeDView.resetFocalPoint()

        renderer = threeDView.renderWindow().GetRenderers().GetItemAsObject(0)
        camera = renderer.GetActiveCamera()
        camera.SetPosition(-125, 1307.15, 211)
        camera.SetFocalPoint(-125, 21, 211)
        camera.SetClippingRange(934.232, 1849.54)
        camera.SetDistance(1286.15)

        # let the layout take effect and re-render new data
        slicer.app.processEvents()

        return results
    def examine(self, fileLists):
        """ Returns a list of DICOMLoadable instances
    corresponding to ways of interpreting the
    fileLists parameter.
    """
        petCtStudies = self.__scanForValidPETCTStudies(fileLists)

        mainLoadable = DICOMLib.DICOMLoadable()
        mainLoadable.tooltip = "PET/CT Studies for Longitudinal PET/CT Report"

        studyplrlsing = "Studies" if len(petCtStudies) != 1 else "Study"
        mainLoadable.name = str(len(petCtStudies)) + " PET/CT " + studyplrlsing

        mainLoadable.selected = True
        mainLoadable.confidence = 1.0

        petImageSeries = 0
        ctImageSeries = 0

        for fileList in fileLists:

            petSeries = self.__getSeriesInformation(
                fileList, self.tags['seriesModality']) == self.petTerm
            ctSeries = self.__getSeriesInformation(
                fileList, self.tags['seriesModality']) == self.ctTerm
            fromPetCtStudy = self.__getSeriesInformation(
                fileList, self.tags['studyInstanceUID']) in petCtStudies

            if (petSeries | ctSeries) & fromPetCtStudy:

                loadables = self.getCachedLoadables(fileList)

                if not loadables:
                    loadables = self.scalarVolumePlugin.examineFiles(fileList)
                    self.cacheLoadables(fileList, loadables)

                for ldbl in loadables:
                    if ldbl.selected:
                        type = ""
                        if petSeries:
                            petImageSeries += 1
                            type = "PT"
                        elif ctSeries:
                            ctImageSeries += 1
                            type = "CT"

                        mainLoadable.files += ldbl.files

                        ldbl.name = type + "_" + self.__getSeriesInformation(
                            ldbl.files, self.tags['studyDate']
                        ) + "_" + self.__getSeriesInformation(
                            ldbl.files, self.tags['seriesTime'])
                        self.cacheLoadables(ldbl.files, [ldbl])
                        if ldbl.warning:
                            mainLoadable.warning += ldbl.warning + " "

                        break  # break for loop because only one loadable needed

        loadables = []

        if mainLoadable.files:
            mainLoadable.name = mainLoadable.name + " containing " + str(
                petImageSeries) + " PET and " + str(
                    ctImageSeries) + " CT image series"
            loadables = [mainLoadable]

        return loadables
Example #10
0
  def getLoadablePetSeriesFromRWVMFile(self, file):
    """ Returns DICOMLoadable instances associated with an RWVM object."""
    
    newLoadables = []
    dicomFile = dicom.read_file(file)
    if dicomFile.Modality == "RWV":
      refRWVMSeq = dicomFile.ReferencedImageRealWorldValueMappingSequence
      refSeriesSeq = dicomFile.ReferencedSeriesSequence
      if refRWVMSeq:
        # May have more than one RWVM value, create loadables for each
        for item in refRWVMSeq:
          rwvLoadable = DICOMLib.DICOMLoadable()
          # Get the referenced files from the database
          refImageSeq = item.ReferencedImageSequence
          instanceFiles = []
          for instance in refImageSeq:
            uid = instance.ReferencedSOPInstanceUID
            if uid:
              instanceFiles += [slicer.dicomDatabase.fileForInstance(uid)]
          # Get the Real World Values
          rwvLoadable.files = instanceFiles
          rwvLoadable.rwvFile = file
          rwvLoadable.patientName = self.__getSeriesInformation(rwvLoadable.files, self.tags['patientName'])
          rwvLoadable.patientID = self.__getSeriesInformation(rwvLoadable.files, self.tags['patientID'])
          rwvLoadable.studyDate = self.__getSeriesInformation(rwvLoadable.files, self.tags['studyDate'])
          rwvmSeq = item.RealWorldValueMappingSequence
          unitsSeq = rwvmSeq[0].MeasurementUnitsCodeSequence
          rwvLoadable.name = rwvLoadable.patientName + ' ' + self.convertStudyDate(rwvLoadable.studyDate) + ' ' + unitsSeq[0].CodeMeaning
          rwvLoadable.tooltip = rwvLoadable.name
          
          import json
          rwvLoadable.unitName = unitsSeq[0].CodeMeaning
          rwvLoadable.units = unitsSeq[0].CodeValue
          unitsCode = CodedValueTuple(unitsSeq[0].CodeValue, unitsSeq[0].CodeMeaning, unitsSeq[0].CodingSchemeDesignator)
          rwvLoadable.unitsCode = json.dumps(unitsCode.getDictionary())

          quantityCode = CodedValueTuple()
          # Slicer is using an older version of pydicom that does not have this
          # item in the dictionary, thus need to access by tag, instead of
          # this:
          # quantitySeq = rwvmSeq[0].QuantityDefinitionSequence
          try:
            quantitySeq = rwvmSeq[0][0x0040,0x9220]
            if quantitySeq:
              for qsItem in quantitySeq:
                if qsItem.ConceptNameCodeSequence[0].CodeMeaning == "Quantity":
                  concept = qsItem.ConceptCodeSequence[0]
                  quantityCode = CodedValueTuple(concept.CodeValue, concept.CodeMeaning, concept.CodingSchemeDesignator)
                  rwvLoadable.quantityCode = json.dumps(quantityCode.getDictionary())
          except:
            # it does not matter what goes wrong
            pass

          rwvLoadable.confidence = 0.90
          rwvLoadable.selected = True # added by CB
          rwvLoadable.slope = rwvmSeq[0].RealWorldValueSlope
          rwvLoadable.referencedSeriesInstanceUID = refSeriesSeq[0].SeriesInstanceUID
          
          # determine modality of referenced series
          refSeriesFiles = slicer.dicomDatabase.filesForSeries(refSeriesSeq[0].SeriesInstanceUID)
          refSeriesFile0 = dicom.read_file(refSeriesFiles[0])
          rwvLoadable.referencedModality = refSeriesFile0.Modality
          
          # add radiopharmaceutical info if PET
          if rwvLoadable.referencedModality == 'PT':
            print('Found Referenced PET series')
            ris = refSeriesFile0.RadiopharmaceuticalInformationSequence[0]
            try: # TODO Many DICOM series do not have radiopharmaceutical code sequence!
              rcs = ris.RadiopharmaceuticalCodeSequence
              if len(rcs) > 0:
                rwvLoadable.RadiopharmaceuticalCodeValue = rcs[0].CodeValue
            except AttributeError:
              print('WARNING: series does not have radiopharmaceutical code sequence.')
            try:
              rcs = ris.RadionuclideCodeSequence
              if len(rcs) > 0:
                rwvLoadable.RadionuclideCodeValue = rcs[0].CodeValue
            except AttributeError:
              print('WARNING: Cannot find radionuclide info for PET Series.')
          
          self.sortLoadableSeriesFiles(rwvLoadable)
          newLoadables.append(rwvLoadable)
            
    return newLoadables