コード例 #1
0
ファイル: DICOMUtils.py プロジェクト: luckyfish888/Slicer
def importFromDICOMWeb(dicomWebEndpoint, studyInstanceUID, seriesInstanceUID=None, accessToken=None):
  """
  Downloads and imports DICOM series from a DICOMweb instance.
  Example usage:
    from DICOMLib import DICOMUtils

    loadedUIDs = DICOMUtils.importFromDICOMWeb(dicomWebEndpoint="https://yourdicomweburl/dicomWebEndpoint",
                                             studyInstanceUID="2.16.840.1.113669.632.20.1211.10000509338")
                                             accessToken="YOUR_ACCESS_TOKEN")
  :param dicomWebEndpoint: Endpoint URL for retrieving the study/series from DICOMweb
  :param studyInstanceUID: UID for the study to be downloaded
  :param seriesInstanceUID: UID for the series to be downloaded. If not specified, all series will be downloaded from the study
  :param accessToken: Optional access token for the query
  :return: List of imported study UIDs
  """

  from dicomweb_client.api import DICOMwebClient
  import random

  if accessToken is None:
    client = DICOMwebClient(url = dicomWebEndpoint)
  else:
    client = DICOMwebClient(
              url = dicomWebEndpoint,
              headers = { "Authorization": "Bearer {}".format(accessToken) },
              )

  seriesList = client.search_for_series(study_instance_uid=studyInstanceUID)
  seriesInstanceUIDs = []
  if not seriesInstanceUID is None:
    seriesInstanceUIDs = [seriesInstanceUID]
  else:
    for series in seriesList:
      currentSeriesInstanceUID = series['0020000E']['Value'][0]
      seriesInstanceUIDs.append(currentSeriesInstanceUID)

  fileNumber = 0
  for currentSeriesInstanceUID in seriesInstanceUIDs:
    instances = client.retrieve_series(
      study_instance_uid=studyInstanceUID,
      series_instance_uid=currentSeriesInstanceUID)

    outputDirectoryBase = slicer.dicomDatabase.databaseDirectory + "/DICOMweb"
    if not os.access(outputDirectoryBase, os.F_OK):
      os.makedirs(outputDirectoryBase)
    outputDirectoryBase += "/" + qt.QDateTime.currentDateTime().toString("yyyyMMdd-hhmmss")
    outputDirectory = qt.QTemporaryDir(outputDirectoryBase)  # Add unique substring to directory
    outputDirectory.setAutoRemove(False)
    outputDirectoryPath = outputDirectory.path()

    for instance in instances:
      filename = outputDirectoryPath + "/" + str(fileNumber) + ".dcm"
      instance.save_as(filename)
      fileNumber += 1
      slicer.app.processEvents()
    importDicom(outputDirectoryPath)

  return seriesInstanceUIDs
コード例 #2
0
  def onExport(self):

    # set up the threeDWidget at the correct render size
    layoutManager = slicer.app.layoutManager()
    oldLayout = layoutManager.layout
    threeDWidget = layoutManager.threeDWidget(0)
    threeDWidget.setParent(None)
    threeDWidget.show()
    geometry = threeDWidget.geometry
    size =  self.sizes[self.sizeSelector.currentText]
    threeDWidget.threeDController().visible = False
    threeDWidget.setGeometry(geometry.x(), geometry.y(), size["width"], size["height"])

    # set up the animation nodes
    viewNode = threeDWidget.threeDView().mrmlViewNode()
    animationNode = self.animationSelector.currentNode()
    sequenceBrowserNode = slicer.util.getNode(animationNode.GetAttribute('Animator.sequenceBrowserNodeID'))
    sequenceNodes = vtk.vtkCollection()
    sequenceBrowserNode.GetSynchronizedSequenceNodes(sequenceNodes, True) # include master
    sequenceNode = sequenceNodes.GetItemAsObject(0)
    frameCount = sequenceNode.GetNumberOfDataNodes()
    tempDir = qt.QTemporaryDir()
    fileExtension = self.fileFormats[self.fileFormatSelector.currentText]

    # perform the screen capture and video creation
    from ScreenCapture import ScreenCaptureLogic
    logic = ScreenCaptureLogic()
    logic.captureSequence(
            viewNode,
            sequenceBrowserNode,
            0, frameCount-1, frameCount,
            tempDir.path(),
            "Slicer-%04d.png")
    logic.createVideo(
            60,
            "-pix_fmt yuv420p",
            tempDir.path(),
            "Slicer-%04d.png",
            self.outputFileButton.text+fileExtension)

    # reset the view
    threeDWidget.threeDController().visible = True
    layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFinalView) ;# force change
    layoutManager.setLayout(oldLayout)
コード例 #3
0
def importFromDICOMWeb(dicomWebEndpoint,
                       studyInstanceUID,
                       seriesInstanceUID=None,
                       accessToken=None):
    """
    Downloads and imports DICOM series from a DICOMweb instance.
    Progress is displayed and if errors occur then they are displayed in a popup window in the end.
    If all the instances in a series are already imported then the series will not be retrieved and imported again.

    :param dicomWebEndpoint: Endpoint URL for retrieving the study/series from DICOMweb
    :param studyInstanceUID: UID for the study to be downloaded
    :param seriesInstanceUID: UID for the series to be downloaded. If not specified, all series will be downloaded from the study
    :param accessToken: Optional access token for the query
    :return: List of imported study UIDs

    Example: calling from PythonSlicer console

    .. code-block:: python

      from DICOMLib import DICOMUtils
      loadedUIDs = DICOMUtils.importFromDICOMWeb(dicomWebEndpoint="https://yourdicomweburl/dicomWebEndpoint",
                                               studyInstanceUID="2.16.840.1.113669.632.20.1211.10000509338")
                                               accessToken="YOUR_ACCESS_TOKEN")

    """

    from dicomweb_client.api import DICOMwebClient

    seriesImported = []
    errors = []
    clientLogger = logging.getLogger('dicomweb_client')
    originalClientLogLevel = clientLogger.level

    progressDialog = slicer.util.createProgressDialog(
        parent=slicer.util.mainWindow(), value=0, maximum=100)
    try:
        progressDialog.labelText = f'Retrieving series list...'
        slicer.app.processEvents()

        if accessToken is None:
            client = DICOMwebClient(url=dicomWebEndpoint)
        else:
            client = DICOMwebClient(
                url=dicomWebEndpoint,
                headers={"Authorization": f"Bearer {accessToken}"},
            )

        seriesList = client.search_for_series(
            study_instance_uid=studyInstanceUID)
        seriesInstanceUIDs = []
        if seriesInstanceUID is not None:
            seriesInstanceUIDs = [seriesInstanceUID]
        else:
            for series in seriesList:
                currentSeriesInstanceUID = series['0020000E']['Value'][0]
                seriesInstanceUIDs.append(currentSeriesInstanceUID)

        # Turn off detailed logging, because it would slow down the file transfer
        clientLogger.setLevel(logging.WARNING)

        fileNumber = 0
        cancelled = False
        for seriesIndex, currentSeriesInstanceUID in enumerate(
                seriesInstanceUIDs):
            progressDialog.labelText = f'Retrieving series {seriesIndex+1} of {len(seriesInstanceUIDs)}...'
            slicer.app.processEvents()

            try:
                seriesInfo = client.retrieve_series_metadata(
                    study_instance_uid=studyInstanceUID,
                    series_instance_uid=currentSeriesInstanceUID)
                numberOfInstances = len(seriesInfo)

                # Skip retrieve and import of this series if it is already imported
                alreadyImportedInstances = slicer.dicomDatabase.instancesForSeries(
                    currentSeriesInstanceUID)
                seriesAlreadyImported = True
                for serieInfo in seriesInfo:
                    sopInstanceUID = serieInfo['00080018']['Value'][0]
                    if sopInstanceUID not in alreadyImportedInstances:
                        seriesAlreadyImported = False
                        break
                if seriesAlreadyImported:
                    seriesImported.append(currentSeriesInstanceUID)
                    continue

                instances = client.iter_series(
                    study_instance_uid=studyInstanceUID,
                    series_instance_uid=currentSeriesInstanceUID)

                slicer.app.processEvents()
                cancelled = progressDialog.wasCanceled
                if cancelled:
                    break

                outputDirectoryBase = slicer.dicomDatabase.databaseDirectory + "/DICOMweb"
                if not os.access(outputDirectoryBase, os.F_OK):
                    os.makedirs(outputDirectoryBase)
                outputDirectoryBase += "/" + qt.QDateTime.currentDateTime(
                ).toString("yyyyMMdd-hhmmss")
                outputDirectory = qt.QTemporaryDir(
                    outputDirectoryBase)  # Add unique substring to directory
                outputDirectory.setAutoRemove(False)
                outputDirectoryPath = outputDirectory.path()

                for instanceIndex, instance in enumerate(instances):
                    progressDialog.setValue(
                        int(100 * instanceIndex / numberOfInstances))
                    slicer.app.processEvents()
                    cancelled = progressDialog.wasCanceled
                    if cancelled:
                        break
                    filename = outputDirectoryPath + "/" + str(
                        fileNumber) + ".dcm"
                    instance.save_as(filename)
                    fileNumber += 1

                if cancelled:
                    # cancel was requested in instance retrieve loop,
                    # stop the entire import process
                    break

                importDicom(outputDirectoryPath)
                seriesImported.append(currentSeriesInstanceUID)

            except Exception as e:
                import traceback
                errors.append(
                    f"Error importing series {currentSeriesInstanceUID}: {str(e)} ({traceback.format_exc()})"
                )

    except Exception as e:
        import traceback
        errors.append(f"{str(e)} ({traceback.format_exc()})")

    finally:
        progressDialog.close()
        clientLogger.setLevel(originalClientLogLevel)

    if errors:
        slicer.util.errorDisplay(
            f"Errors occurred during DICOMweb import of {len(errors)} series.",
            detailedText="\n\n".join(errors))
    elif cancelled and (len(seriesImported) < len(seriesInstanceUIDs)):
        slicer.util.infoDisplay(
            f"DICOMweb import has been interrupted after completing {len(seriesImported)} out of {len(seriesInstanceUIDs)} series."
        )

    return seriesImported
コード例 #4
0
ファイル: DICOMUtils.py プロジェクト: yehan0223/Slicer
def importFromDICOMWeb(dicomWebEndpoint,
                       studyInstanceUID,
                       seriesInstanceUID=None,
                       accessToken=None):
    """
  Downloads and imports DICOM series from a DICOMweb instance.
  Example usage:
    from DICOMLib import DICOMUtils

    loadedUIDs = DICOMUtils.importFromDICOMWeb(dicomWebEndpoint="https://yourdicomweburl/dicomWebEndpoint",
                                             studyInstanceUID="2.16.840.1.113669.632.20.1211.10000509338")
                                             accessToken="YOUR_ACCESS_TOKEN")
  :param dicomWebEndpoint: Endpoint URL for retrieving the study/series from DICOMweb
  :param studyInstanceUID: UID for the study to be downloaded
  :param seriesInstanceUID: UID for the series to be downloaded. If not specified, all series will be downloaded from the study
  :param accessToken: Optional access token for the query
  :return: List of imported study UIDs
  """

    from dicomweb_client.api import DICOMwebClient
    import random

    progressDialog = slicer.util.createProgressDialog(
        parent=slicer.util.mainWindow(), value=0, maximum=100)
    progressDialog.labelText = f'Retrieving series list...'
    slicer.app.processEvents()

    if accessToken is None:
        client = DICOMwebClient(url=dicomWebEndpoint,
                                callback=progressCallback)
    else:
        client = DICOMwebClient(
            url=dicomWebEndpoint,
            headers={"Authorization": f"Bearer {accessToken}"},
        )

    seriesList = client.search_for_series(study_instance_uid=studyInstanceUID)
    seriesInstanceUIDs = []
    if not seriesInstanceUID is None:
        seriesInstanceUIDs = [seriesInstanceUID]
    else:
        for series in seriesList:
            currentSeriesInstanceUID = series['0020000E']['Value'][0]
            seriesInstanceUIDs.append(currentSeriesInstanceUID)

    fileNumber = 0
    cancelled = False
    for seriesIndex, currentSeriesInstanceUID in enumerate(seriesInstanceUIDs):
        progressDialog.labelText = f'Retrieving series {seriesIndex+1} of {len(seriesInstanceUIDs)}...'
        slicer.app.processEvents()
        instances = client.retrieve_series(
            study_instance_uid=studyInstanceUID,
            series_instance_uid=currentSeriesInstanceUID)

        progressDialog.setValue(
            int(100 * seriesIndex / len(seriesInstanceUIDs)))
        slicer.app.processEvents()
        cancelled = progressDialog.wasCanceled
        if cancelled:
            break

        outputDirectoryBase = slicer.dicomDatabase.databaseDirectory + "/DICOMweb"
        if not os.access(outputDirectoryBase, os.F_OK):
            os.makedirs(outputDirectoryBase)
        outputDirectoryBase += "/" + qt.QDateTime.currentDateTime().toString(
            "yyyyMMdd-hhmmss")
        outputDirectory = qt.QTemporaryDir(
            outputDirectoryBase)  # Add unique substring to directory
        outputDirectory.setAutoRemove(False)
        outputDirectoryPath = outputDirectory.path()

        for instanceIndex, instance in enumerate(instances):
            filename = outputDirectoryPath + "/" + str(fileNumber) + ".dcm"
            instance.save_as(filename)
            fileNumber += 1

        importDicom(outputDirectoryPath)
        if cancelled:
            break

    progressDialog.close()
    return seriesInstanceUIDs