Ejemplo n.º 1
0
  def export(self,exportables):
    for exportable in exportables:
      # Get node to export
      node = slicer.mrmlScene.GetNodeByID(exportable.nodeID)
      if node.GetAssociatedNode() == None or not node.GetAssociatedNode().IsA('vtkMRMLScalarVolumeNode'):
        error = "Series '" + node.GetNameWithoutPostfix() + "' cannot be exported!"
        print(error)
        return error

      # Get output directory and create a subdirectory. This is necessary
      # to avoid overwriting the files in case of multiple exportables, as
      # naming of the DICOM files is static
      directoryDir = qt.QDir(exportable.directory)
      directoryDir.mkdir(exportable.nodeID)
      directoryDir.cd(exportable.nodeID)
      directory = directoryDir.absolutePath()
      print("Export scalar volume '" + node.GetAssociatedNode().GetName() + "' to directory " + directory)

      # Get study and patient nodes
      studyNode = node.GetParentNode()
      if studyNode == None:
        error = "Unable to get study node for series '" + node.GetAssociatedNode().GetName() + "'"
        print(error)
        return error
      patientNode = studyNode.GetParentNode()
      if patientNode == None:
        error = "Unable to get patient node for series '" + node.GetAssociatedNode().GetName() + "'"
        print(error)
        return error

      # Assemble tags dictionary for volume export
      from vtkSlicerSubjectHierarchyModuleMRMLPython import vtkMRMLSubjectHierarchyConstants
      tags = {}
      tags['Patient Name'] = exportable.tag(vtkMRMLSubjectHierarchyConstants.GetDICOMPatientNameTagName())
      tags['Patient ID'] = exportable.tag(vtkMRMLSubjectHierarchyConstants.GetDICOMPatientIDTagName())
      tags['Patient Comments'] = exportable.tag(vtkMRMLSubjectHierarchyConstants.GetDICOMPatientCommentsTagName())
      tags['Study ID'] = self.defaultStudyID
      tags['Study Date'] = exportable.tag(vtkMRMLSubjectHierarchyConstants.GetDICOMStudyDateTagName())
      tags['Study Description'] = exportable.tag(vtkMRMLSubjectHierarchyConstants.GetDICOMStudyDescriptionTagName())
      tags['Modality'] = exportable.tag('Modality')
      tags['Manufacturer'] = exportable.tag('Manufacturer')
      tags['Model'] = exportable.tag('Model')
      tags['Series Description'] = exportable.tag('SeriesDescription')
      tags['Series Number'] = exportable.tag('SeriesNumber')

      # Validate tags
      if tags['Modality'] == "":
        error = "Empty modality for series '" + node.GetAssociatedNode().GetName() + "'"
        print(error)
        return error
      #TODO: more tag checks

      # Perform export
      exporter = DICOMExportScalarVolume(tags['Study ID'], node.GetAssociatedNode(), tags, directory)
      exporter.export()

    # Success
    return ""
  def export(self,exportables):
    for exportable in exportables:
      # Get node to export
      node = slicer.mrmlScene.GetNodeByID(exportable.nodeID)
      if node.GetAssociatedNode() is None or not node.GetAssociatedNode().IsA('vtkMRMLScalarVolumeNode'):
        error = "Series '" + node.GetNameWithoutPostfix() + "' cannot be exported!"
        logging.error(error)
        return error

      # Get output directory and create a subdirectory. This is necessary
      # to avoid overwriting the files in case of multiple exportables, as
      # naming of the DICOM files is static
      directoryDir = qt.QDir(exportable.directory)
      directoryDir.mkdir(exportable.nodeID)
      directoryDir.cd(exportable.nodeID)
      directory = directoryDir.absolutePath()
      logging.info("Export scalar volume '" + node.GetAssociatedNode().GetName() + "' to directory " + directory)

      # Get study and patient nodes
      studyNode = node.GetParentNode()
      if studyNode is None:
        error = "Unable to get study node for series '" + node.GetAssociatedNode().GetName() + "'"
        logging.error(error)
        return error
      patientNode = studyNode.GetParentNode()
      if patientNode is None:
        error = "Unable to get patient node for series '" + node.GetAssociatedNode().GetName() + "'"
        logging.error(error)
        return error

      # Assemble tags dictionary for volume export
      tags = {}
      tags['Patient Name'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMPatientNameTagName())
      tags['Patient ID'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMPatientIDTagName())
      tags['Patient Comments'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMPatientCommentsTagName())
      tags['Study ID'] = self.defaultStudyID
      tags['Study Date'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyDateTagName())
      tags['Study Description'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyDescriptionTagName())
      tags['Modality'] = exportable.tag('Modality')
      tags['Manufacturer'] = exportable.tag('Manufacturer')
      tags['Model'] = exportable.tag('Model')
      tags['Series Description'] = exportable.tag('SeriesDescription')
      tags['Series Number'] = exportable.tag('SeriesNumber')

      # Validate tags
      if tags['Modality'] == "":
        error = "Empty modality for series '" + node.GetAssociatedNode().GetName() + "'"
        logging.error(error)
        return error
      #TODO: more tag checks

      # Perform export
      exporter = DICOMExportScalarVolume(tags['Study ID'], node.GetAssociatedNode(), tags, directory)
      exporter.export()

    # Success
    return ""
Ejemplo n.º 3
0
    def export(self, exportables):
        for exportable in exportables:
            # Get volume node to export
            shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(
                slicer.mrmlScene)
            if shNode is None:
                error = "Invalid subject hierarchy"
                logging.error(error)
                return error
            volumeNode = shNode.GetItemDataNode(
                exportable.subjectHierarchyItemID)
            if volumeNode is None or not volumeNode.IsA(
                    'vtkMRMLScalarVolumeNode'):
                error = "Series '" + shNode.GetItemName(
                    exportable.subjectHierarchyItemID
                ) + "' cannot be exported  as volume sequence"
                logging.error(error)
                return error

            sequenceBrowserNode = self.getSequenceBrowserNodeForMasterOutputNode(
                volumeNode)
            if not sequenceBrowserNode:
                error = "Series '" + shNode.GetItemName(
                    exportable.subjectHierarchyItemID
                ) + "' cannot be exported as volume sequence"
                logging.error(error)
                return error

            volumeSequenceNode = sequenceBrowserNode.GetSequenceNode(
                volumeNode)
            if not volumeSequenceNode:
                error = "Series '" + shNode.GetItemName(
                    exportable.subjectHierarchyItemID
                ) + "' cannot be exported as volume sequence"
                logging.error(error)
                return error

            # Get study and patient items
            studyItemID = shNode.GetItemParent(
                exportable.subjectHierarchyItemID)
            if not studyItemID:
                error = "Unable to get study for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error
            patientItemID = shNode.GetItemParent(studyItemID)
            if not patientItemID:
                error = "Unable to get patient for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error

            # Assemble tags dictionary for volume export

            tags = {}
            tags['Patient Name'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientNameTagName())
            tags['Patient ID'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientIDTagName())
            tags['Patient Comments'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientCommentsTagName())
            if slicer.app.majorVersion >= 5 or (slicer.app.majorVersion == 4
                                                and
                                                slicer.app.minorVersion >= 11):
                tags['Study Instance UID'] = pydicom.uid.generate_uid()
            else:
                tags['Study Instance UID'] = dicom.UID.generate_uid()
            tags['Study ID'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyIDTagName(
                ))
            tags['Study Date'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyDateTagName())
            tags['Study Time'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyTimeTagName())
            tags['Study Description'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyDescriptionTagName())
            tags['Modality'] = exportable.tag('Modality')
            tags['Manufacturer'] = exportable.tag('Manufacturer')
            tags['Model'] = exportable.tag('Model')
            tags['Series Description'] = exportable.tag('SeriesDescription')
            tags['Series Number'] = exportable.tag('SeriesNumber')
            tags['Series Date'] = exportable.tag("SeriesDate")
            tags['Series Time'] = exportable.tag("SeriesTime")
            if slicer.app.majorVersion >= 5 or (slicer.app.majorVersion == 4
                                                and
                                                slicer.app.minorVersion >= 11):
                tags['Series Instance UID'] = pydicom.uid.generate_uid()
                tags[
                    'Frame of Reference Instance UID'] = pydicom.uid.generate_uid(
                    )
            else:
                tags['Series Instance UID'] = dicom.UID.generate_uid()
                tags[
                    'Frame of Reference Instance UID'] = dicom.UID.generate_uid(
                    )

            # Validate tags
            if tags['Modality'] == "":
                error = "Empty modality for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error
            #TODO: more tag checks

            sequenceItemCount = sequenceBrowserNode.GetMasterSequenceNode(
            ).GetNumberOfDataNodes()
            originalSelectedSequenceItemNumber = sequenceBrowserNode.GetSelectedItemNumber(
            )
            masterVolumeNode = sequenceBrowserNode.GetMasterSequenceNode()

            # initialize content datetime from series datetime
            contentStartDate = exportable.tag("SeriesDate")
            contentStartTime = exportable.tag("SeriesTime")
            import datetime
            datetimeNow = datetime.datetime.now()
            if not contentStartDate:
                contentStartDate = datetimeNow.strftime("%Y%m%d")
            if not contentStartTime:
                contentStartTime = datetimeNow.strftime("%H%M%S.%f")
            contentStartDatetime = self.datetimeFromDicom(
                contentStartDate, contentStartTime)

            # Get output directory and create a subdirectory. This is necessary
            # to avoid overwriting the files in case of multiple exportables, as
            # naming of the DICOM files is static
            directoryName = 'VolumeSequence_' + str(
                exportable.subjectHierarchyItemID)
            directoryDir = qt.QDir(exportable.directory)
            directoryDir.mkdir(directoryName)
            directoryDir.cd(directoryName)
            directory = directoryDir.absolutePath()
            logging.info("Export scalar volume '" + volumeNode.GetName() +
                         "' to directory " + directory)

            for sequenceItemIndex in range(sequenceItemCount):

                # Switch to next item in the series
                sequenceBrowserNode.SetSelectedItemNumber(sequenceItemIndex)
                slicer.app.processEvents()
                # Compute content date&time
                # TODO: verify that unit in sequence node is "second" (and convert to seconds if not)
                timeOffsetSec = float(
                    masterVolumeNode.GetNthIndexValue(sequenceItemIndex)
                ) - float(masterVolumeNode.GetNthIndexValue(0))
                contentDatetime = contentStartDatetime + datetime.timedelta(
                    seconds=timeOffsetSec)
                tags['Content Date'] = contentDatetime.strftime("%Y%m%d")
                tags['Content Time'] = contentDatetime.strftime("%H%M%S.%f")
                # Perform export
                filenamePrefix = f"IMG_{sequenceItemIndex:04d}_"
                exporter = DICOMExportScalarVolume(tags['Study ID'],
                                                   volumeNode, tags, directory,
                                                   filenamePrefix)
                exporter.export()

        # Success
        return ""
Ejemplo n.º 4
0
    def export(self, exportables):
        for exportable in exportables:
            # Get volume node to export
            shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(
                slicer.mrmlScene)
            if shNode is None:
                error = "Invalid subject hierarchy"
                logging.error(error)
                return error
            volumeNode = shNode.GetItemDataNode(
                exportable.subjectHierarchyItemID)
            if volumeNode is None or not volumeNode.IsA(
                    'vtkMRMLScalarVolumeNode'):
                error = "Series '" + shNode.GetItemName(
                    exportable.subjectHierarchyItemID) + "' cannot be exported"
                logging.error(error)
                return error

            # Get output directory and create a subdirectory. This is necessary
            # to avoid overwriting the files in case of multiple exportables, as
            # naming of the DICOM files is static
            directoryName = 'ScalarVolume_' + str(
                exportable.subjectHierarchyItemID)
            directoryDir = qt.QDir(exportable.directory)
            directoryDir.mkdir(directoryName)
            directoryDir.cd(directoryName)
            directory = directoryDir.absolutePath()
            logging.info("Export scalar volume '" + volumeNode.GetName() +
                         "' to directory " + directory)

            # Get study and patient items
            studyItemID = shNode.GetItemParent(
                exportable.subjectHierarchyItemID)
            if not studyItemID:
                error = "Unable to get study for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error
            patientItemID = shNode.GetItemParent(studyItemID)
            if not patientItemID:
                error = "Unable to get patient for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error

            # Assemble tags dictionary for volume export
            tags = {}
            tags['Patient Name'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientNameTagName())
            tags['Patient ID'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientIDTagName())
            tags['Patient Comments'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientCommentsTagName())
            tags['Study ID'] = self.defaultStudyID
            tags['Study Date'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyDateTagName())
            tags['Study Time'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyTimeTagName())
            tags['Study Description'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyDescriptionTagName())
            tags['Modality'] = exportable.tag('Modality')
            tags['Manufacturer'] = exportable.tag('Manufacturer')
            tags['Model'] = exportable.tag('Model')
            tags['Series Description'] = exportable.tag('SeriesDescription')
            tags['Series Number'] = exportable.tag('SeriesNumber')
            tags['Series Date'] = exportable.tag('SeriesDate')
            tags['Series Time'] = exportable.tag('SeriesTime')
            tags['Content Date'] = exportable.tag('ContentDate')
            tags['Content Time'] = exportable.tag('ContentTime')

            tags['Study Instance UID'] = exportable.tag('StudyInstanceUID')
            tags['Series Instance UID'] = exportable.tag('SeriesInstanceUID')
            tags['Frame of Reference Instance UID'] = exportable.tag(
                'FrameOfReferenceInstanceUID')

            # Validate tags
            if tags['Modality'] == "":
                error = "Empty modality for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error
            #TODO: more tag checks

            # Perform export
            exporter = DICOMExportScalarVolume(tags['Study ID'], volumeNode,
                                               tags, directory)
            exporter.export()

        # Success
        return ""
Ejemplo n.º 5
0
  def export(self,exportables):
    for exportable in exportables:
      # Get volume node to export
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
      if shNode is None:
        error = "Invalid subject hierarchy"
        logging.error(error)
        return error
      volumeNode = shNode.GetItemDataNode(exportable.subjectHierarchyItemID)
      if volumeNode is None or not volumeNode.IsA('vtkMRMLScalarVolumeNode'):
        error = "Series '" + shNode.GetItemName(exportable.subjectHierarchyItemID) + "' cannot be exported"
        logging.error(error)
        return error

      # Get output directory and create a subdirectory. This is necessary
      # to avoid overwriting the files in case of multiple exportables, as
      # naming of the DICOM files is static
      directoryName = 'ScalarVolume_' + str(exportable.subjectHierarchyItemID)
      directoryDir = qt.QDir(exportable.directory)
      directoryDir.mkdir(directoryName)
      directoryDir.cd(directoryName)
      directory = directoryDir.absolutePath()
      logging.info("Export scalar volume '" + volumeNode.GetName() + "' to directory " + directory)

      # Get study and patient items
      studyItemID = shNode.GetItemParent(exportable.subjectHierarchyItemID)
      if not studyItemID:
        error = "Unable to get study for series '" + volumeNode.GetName() + "'"
        logging.error(error)
        return error
      patientItemID = shNode.GetItemParent(studyItemID)
      if not patientItemID:
        error = "Unable to get patient for series '" + volumeNode.GetName() + "'"
        logging.error(error)
        return error

      # Assemble tags dictionary for volume export
      tags = {}
      tags['Patient Name'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMPatientNameTagName())
      tags['Patient ID'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMPatientIDTagName())
      tags['Patient Comments'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMPatientCommentsTagName())
      tags['Study ID'] = self.defaultStudyID
      tags['Study Date'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyDateTagName())
      tags['Study Time'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyTimeTagName())
      tags['Study Description'] = exportable.tag(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyDescriptionTagName())
      tags['Modality'] = exportable.tag('Modality')
      tags['Manufacturer'] = exportable.tag('Manufacturer')
      tags['Model'] = exportable.tag('Model')
      tags['Series Description'] = exportable.tag('SeriesDescription')
      tags['Series Number'] = exportable.tag('SeriesNumber')
      tags['Series Date'] = exportable.tag('SeriesDate')
      tags['Series Time'] = exportable.tag('SeriesTime')
      tags['Content Date'] = exportable.tag('ContentDate')
      tags['Content Time'] = exportable.tag('ContentTime')

      tags['Study Instance UID'] = exportable.tag('StudyInstanceUID')
      tags['Series Instance UID'] = exportable.tag('SeriesInstanceUID')
      tags['Frame of Reference Instance UID'] = exportable.tag('FrameOfReferenceInstanceUID')

      # Validate tags
      if tags['Modality'] == "":
        error = "Empty modality for series '" + volumeNode.GetName() + "'"
        logging.error(error)
        return error
      #TODO: more tag checks

      # Perform export
      exporter = DICOMExportScalarVolume(tags['Study ID'], volumeNode, tags, directory)
      exporter.export()

    # Success
    return ""
Ejemplo n.º 6
0
    def export(self, exportables):
        for exportable in exportables:
            # Get volume node to export
            shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(
                slicer.mrmlScene)
            if shNode is None:
                error = "Invalid subject hierarchy"
                logging.error(error)
                return error
            volumeNode = shNode.GetItemDataNode(
                exportable.subjectHierarchyItemID)
            if volumeNode is None or not volumeNode.IsA(
                    'vtkMRMLScalarVolumeNode'):
                error = "Series '" + shNode.GetItemName(
                    exportable.subjectHierarchyItemID) + "' cannot be exported"
                logging.error(error)
                return error

            # Get output directory and create a subdirectory. This is necessary
            # to avoid overwriting the files in case of multiple exportables, as
            # naming of the DICOM files is static
            directoryName = 'ScalarVolume_' + str(
                exportable.subjectHierarchyItemID)
            directoryDir = qt.QDir(exportable.directory)
            directoryDir.mkpath(directoryName)
            directoryDir.cd(directoryName)
            directory = directoryDir.absolutePath()
            logging.info("Export scalar volume '" + volumeNode.GetName() +
                         "' to directory " + directory)

            # Get study and patient items
            studyItemID = shNode.GetItemParent(
                exportable.subjectHierarchyItemID)
            if not studyItemID:
                error = "Unable to get study for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error
            patientItemID = shNode.GetItemParent(studyItemID)
            if not patientItemID:
                error = "Unable to get patient for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error

            # Assemble tags dictionary for volume export
            tags = {}
            tags['Patient Name'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientNameTagName())
            tags['Patient ID'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientIDTagName())
            tags['Patient Birth Date'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientBirthDateTagName())
            tags['Patient Sex'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientSexTagName())
            tags['Patient Comments'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMPatientCommentsTagName())
            tags['Study ID'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMStudyIDTagName(
                ))
            tags['Study Date'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyDateTagName())
            tags['Study Time'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyTimeTagName())
            tags['Study Description'] = exportable.tag(
                slicer.vtkMRMLSubjectHierarchyConstants.
                GetDICOMStudyDescriptionTagName())
            tags['Modality'] = exportable.tag('Modality')
            tags['Manufacturer'] = exportable.tag('Manufacturer')
            tags['Model'] = exportable.tag('Model')
            tags['Series Description'] = exportable.tag('SeriesDescription')
            tags['Series Number'] = exportable.tag('SeriesNumber')
            tags['Series Date'] = exportable.tag('SeriesDate')
            tags['Series Time'] = exportable.tag('SeriesTime')
            tags['Content Date'] = exportable.tag('ContentDate')
            tags['Content Time'] = exportable.tag('ContentTime')

            tags['Study Instance UID'] = exportable.tag('StudyInstanceUID')
            tags['Series Instance UID'] = exportable.tag('SeriesInstanceUID')
            tags['Frame of Reference UID'] = exportable.tag(
                'FrameOfReferenceUID')

            # Generate any missing but required UIDs
            if not tags['Study Instance UID']:
                import pydicom as dicom
                tags['Study Instance UID'] = dicom.uid.generate_uid()
            if not tags['Series Instance UID']:
                import pydicom as dicom
                tags['Series Instance UID'] = dicom.uid.generate_uid()
            if not tags['Frame of Reference UID']:
                import pydicom as dicom
                tags['Frame of Reference UID'] = dicom.uid.generate_uid()

            # Use the default Study ID if none is specified
            if not tags['Study ID']:
                tags['Study ID'] = self.defaultStudyID

            # Validate tags
            if tags['Modality'] == "":
                error = "Empty modality for series '" + volumeNode.GetName(
                ) + "'"
                logging.error(error)
                return error

            seriesInstanceUID = tags['Series Instance UID']
            if seriesInstanceUID:
                # Make sure we don't use a series instance UID that already exists (it would mix in more slices into an existing series,
                # which is very unlikely that users would want).
                db = slicer.dicomDatabase
                studyInstanceUID = db.studyForSeries(seriesInstanceUID)
                if studyInstanceUID:
                    # This seriesInstanceUID is already found in the database
                    if len(seriesInstanceUID) > 25:
                        seriesInstanceUID = seriesInstanceUID[:20] + "..."
                    error = f"A series already exists in the database by SeriesInstanceUID {seriesInstanceUID}."
                    logging.error(error)
                    return error

            # TODO: more tag checks

            # Perform export
            exporter = DICOMExportScalarVolume(tags['Study ID'], volumeNode,
                                               tags, directory)
            if not exporter.export():
                return "Creating DICOM files from scalar volume failed. See the application log for details."

        # Success
        return ""