예제 #1
0
def _write_dicom_file(np_slice: np.ndarray, header: pydicom.FileDataset,
                      file_path: str):
    """Replace data in header with 2D numpy array and write to `file_path`.

    Args:
        np_slice (np.ndarray): 2D slice to encode in dicom file.
        header (pydicom.FileDataset): DICOM header.
        file_path: File path to write to.
    """
    # Deep copy required in case headers are shared.
    header = copy.deepcopy(header)
    expected_dimensions = header.Rows, header.Columns
    assert (
        np_slice.shape == expected_dimensions
    ), "In-plane dimension mismatch - expected shape {}, got {}".format(
        str(expected_dimensions), str(np_slice.shape))

    np_slice_bytes = np_slice.tobytes()
    bit_depth = int(
        len(np_slice_bytes) / (np_slice.shape[0] * np_slice.shape[1]) * 8)
    if bit_depth != header.BitsAllocated:
        np_slice = _update_np_dtype(np_slice, header.BitsAllocated)
        np_slice_bytes = np_slice.tobytes()
        bit_depth = int(
            len(np_slice_bytes) / (np_slice.shape[0] * np_slice.shape[1]) * 8)

    assert bit_depth == header.BitsAllocated, "Bit depth mismatch: Expected {:d} got {:d}".format(
        header.BitsAllocated, bit_depth)

    header.PixelData = np_slice_bytes

    header.save_as(file_path)
예제 #2
0
    def __write_dicom_file__(self, np_slice: np.ndarray,
                             header: pydicom.FileDataset, filepath: str):
        """
        Replace data in header with 2D numpy array and write to filepath
        :param np_slice: a 2D numpy array
        :param header: a pydicom.FileDataset with fields populated
        :param filepath: Filepath to write dicom to
        """
        expected_dimensions = header.Rows, header.Columns
        assert np_slice.shape == expected_dimensions, "In-plane dimension mismatch - expected shape %s, got %s" % (
            str(expected_dimensions), str(np_slice.shape))

        np_slice_bytes = np_slice.tobytes()
        bit_depth = int(
            len(np_slice_bytes) / (np_slice.shape[0] * np_slice.shape[1]) * 8)
        if bit_depth != header.BitsAllocated:
            np_slice = __update_np_dtype__(np_slice, header.BitsAllocated)
            np_slice_bytes = np_slice.tobytes()
            bit_depth = int(
                len(np_slice_bytes) / (np_slice.shape[0] * np_slice.shape[1]) *
                8)

        assert bit_depth == header.BitsAllocated, "Bit depth mismatch: Expected %d got %d" % (
            header.BitsAllocated, bit_depth)

        header.PixelData = np_slice_bytes

        header.save_as(filepath)
예제 #3
0
def _get_window(dicom_file: pydicom.FileDataset, window='default', unit=None):
    if isinstance(window, dict):
        wc = window.get('window_center')
        ww = window.get('window_width')
    elif window == 'default' or unit is None:
        try:
            wc = dicom_file.WindowCenter
            ww = dicom_file.WindowWidth
            if isinstance(wc, pydicom.multival.MultiValue):
                wc = wc[0]
            if isinstance(ww, pydicom.multival.MultiValue):
                ww = ww[0]
        except:
            BitsStored = dicom_file.get('BitsStored')
            wc = 2**(BitsStored - 1)
            ww = 2**BitsStored
    elif isinstance(window, str) and unit in ['HU', 'Hounsfield Unit']:
        wc, ww = get_ct_window(window)
    else:
        try:
            wc = dicom_file.WindowCenter
            ww = dicom_file.WindowWidth
            if isinstance(wc, pydicom.multival.MultiValue):
                wc = wc[0]
            if isinstance(ww, pydicom.multival.MultiValue):
                ww = ww[0]
        except:
            wc = None
            ww = None

    if wc is None or ww is None:
        raise ValueError('Either window center or window width not found')
    return wc, ww
예제 #4
0
def voi_lut_trans(dicom_file: pydicom.FileDataset,
                  image_data: numpy.ndarray,
                  depth,
                  window='default',
                  unit: str = None):
    VOILUTSequence = getattr(dicom_file, 'VOILUTSequence', [{}])[0]
    lut_descriptor = VOILUTSequence.get('LUTDescriptor')
    if lut_descriptor is None:
        lut_descriptor = VOILUTSequence.get('LUTDescriptor')

    if isinstance(lut_descriptor, bytes):
        PixelRepresentation = int(dicom_file.get('PixelRepresentation'))
        if modality_classifier(
                dicom_file) is None and PixelRepresentation == 0:
            dtype = numpy.ushort
        else:
            dtype = numpy.short
        lut_descriptor = numpy.frombuffer(lut_descriptor, dtype)

    lut_data = VOILUTSequence.get('LUTData')
    if isinstance(lut_data, bytes):
        if lut_descriptor[2] == 8:
            dtype = numpy.uint8
        elif lut_descriptor[2] == 16:
            dtype = numpy.uint16
        else:
            raise ValueError(
                f'LUTDescriptor[2] should be 8 or 16. Got {lut_descriptor[2]}')
        lut_data = numpy.frombuffer(lut_data, dtype)
    scale_factor = depth / int(2**getattr(dicom_file, 'BitsStored', 12))
    return lut_trans(image_data, lut_descriptor, lut_data, scale_factor)
예제 #5
0
 def test_force_is_true(self):
     """
         - Writes dicom file from scratch without File Meta Information Header
         - read with force = True
         - Check it doesn't raise InvalidDicomError Exception
         - Check file_meta has length 0
     """
     original_ds = FileDataset(FILENAME_PATH, {}, file_meta=None)
     ds_creation_util.save_ds_file_as_dicom(original_ds)
     ds = dcmread(FILENAME_PATH, force=True)
     self.assertTrue(len(ds.file_meta) == 0)
예제 #6
0
def voi_classifier(dicom_file: pydicom.FileDataset):
    """
    Get value of interest (voi) transform method name from dicom object

    :param dicom_file: object read from pydicom
    :return: voi transform method name. Includes
            'LINEAR', 'LINEAR_EXACT', 'SIGMOID', 'TABLE', or None
    """
    VOILUTFunction = dicom_file.get('VOILUTFunction')
    VOILUTSequence = dicom_file.get('VOILUTSequence')
    WindowCenter = dicom_file.get('WindowCenter')

    if (VOILUTSequence is not None) and (WindowCenter is None):
        return 'TABLE'
    elif WindowCenter is not None:
        if VOILUTFunction is None:
            return 'LINEAR'
        else:
            return VOILUTFunction
    else:
        return 'LINEAR'
예제 #7
0
def modality_lut_trans(dicom_file: pydicom.FileDataset, image_data: numpy.ndarray):
    ModalityLUTSequence = dicom_file.get('ModalityLUTSequence')[0]
    lut_descriptor = ModalityLUTSequence.get('LUTDescriptor')
    if lut_descriptor is None: # debug
        lut_descriptor = ModalityLUTSequence.get('LUTDescriptor') # if don't do this line, line 40 will be None

    if isinstance(lut_descriptor, bytes):
        PixelRepresentation = int(dicom_file.get('PixelRepresentation'))
        dtype = numpy.ushort if PixelRepresentation == 0 else numpy.short
        lut_descriptor = numpy.frombuffer(lut_descriptor, dtype)

    lut_data = ModalityLUTSequence.get('LUTData')
    if isinstance(lut_data, bytes):
        if lut_descriptor[2] == 8:
            dtype = numpy.uint8
        elif lut_descriptor[2] == 16:
            dtype = numpy.uint16
        else:
            raise ValueError(f'LUTDescriptor[2] should be 8 or 16. Got {lut_descriptor[2]}')
        lut_data = numpy.frombuffer(lut_data, dtype)
    unit = ModalityLUTSequence.get('ModalityLUTType')
    return lut_trans(image_data, lut_descriptor, lut_data), unit
예제 #8
0
 def test_force_is_default_false_raise_exception(self):
     """
         - Writes dicom file from scratch without File Meta Information Header
         - read with force = False
         - Check it raises InvalidDicomError Exception
     """
     original_ds = FileDataset(FILENAME_PATH, {})
     ds_creation_util.save_ds_file_as_dicom(original_ds)
     try:
         dcmread(FILENAME_PATH)
         self.fail()
     except InvalidDicomError:
         pass
     except:
         self.fail()
예제 #9
0
 def __init__(self, iod_type):
     """
     Parameters
     ----------
     iod_type : Type of IOD, i.e. DICOM object of class IODTypes
     """
     self.iod_type = iod_type
     file_meta = Dataset()
     file_meta.MediaStorageSOPClassUID = iod_type.value
     file_meta.MediaStorageSOPInstanceUID = uid.generate_uid()
     file_meta.ImplementationClassUID = "1.2.752.24.16.4.1"
     self.dataset = FileDataset(None, {},
                                file_meta=file_meta,
                                preamble=b"\0" * 128)
     self.dataset.is_little_endian = True
     self.dataset.is_implicit_VR = False
     self.dataset.file_meta.TransferSyntaxUID = uid.ExplicitVRLittleEndian
예제 #10
0
 def on_c_store(self, ds: Dataset, context, info):
     logger.info('C-Store processing')
     file_meta = Dataset()
     file_meta.TransferSyntaxUID = ImplicitVRLittleEndian
     file_meta.MediaStorageSOPClassUID = ds.SOPClassUID
     file_meta.MediaStorageSOPInstanceUID = ds.SOPInstanceUID
     file_meta.ImplementationClassUID = '1.3.6.1.4.1.9590.100.1.0.100.4.0'
     fds = FileDataset(None, {}, file_meta=file_meta, preamble=b'\0' * 128)
     fds.update(ds)
     fds.is_little_endian = True
     fds.is_implicit_VR = True
     DicomSaver.save(fds)
     logger.info('C-Store succeeded')
     return 0x0000
예제 #11
0
 def get_dcm_filed(__dcm: pydicom.FileDataset, __field_name: str):
     __field = __dcm.get(__field_name)
     if type(__field) == pydicom.multival.MultiValue:
         return int(__field[0])
     else:
         return int(__field)
예제 #12
0
def dump_dicom(data, folder, spacing=(1, 1, 1),
               origin=(0, 0, 0), intercept=0, slope=1):
    """ Dump 3D scan in dicom format.

    Parameters
    ----------
    data : ndarray
        3D numpy array containing ct scan's data.
    folder : str
        folder where dicom files will be dumped.
    spacing : ArrayLike
        ndarray of shape (3,) that contains spacing along z, y, x axes.
    origin : ArrayLike
        ndarray of shape (3,) that contains origin for z, y, x axes.
    interception : float
        interception value. Default is 0.
    slope : float
        slope value. Default is 1.
    """
    spacing = np.array(spacing).reshape(-1)
    origin = np.array(origin).reshape(-1)

    if not os.path.exists(folder):
        os.makedirs(folder)

    num_slices = data.shape[0]
    scan_id = np.random.randint(2 ** 16)
    for i in range(num_slices):
        slice_name = (
            hex(scan_id + i)
            .replace('x', '')
            .upper()
            .zfill(8)
        )
        filename = os.path.join(folder, slice_name)
        pixel_array = (data[i, ...] - intercept) / slope
        locZ, locY, locX = (float(origin[0] + spacing[0] * i),
                            float(origin[1]), float(origin[2]))

        file_meta = Dataset()
        file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage'
        file_meta.MediaStorageSOPInstanceUID = (
            hex(scan_id)
            .replace('x', '')
            .upper()
            .zfill(8)
        )
        file_meta.ImplementationClassUID = slice_name

        dataset = FileDataset(filename, {},
                              file_meta=file_meta,
                              preamble=b"\0"*128)

        dataset.PixelData = pixel_array.astype(np.uint16).tostring()
        dataset.RescaleSlope = slope
        dataset.RescaleIntercept = intercept

        dataset.ImagePositionPatient = MultiValue(type_constructor=float,
                                                  iterable=[locZ, locY, locX])

        dataset.PixelSpacing = MultiValue(type_constructor=float,
                                          iterable=[float(spacing[1]),
                                                    float(spacing[2])])
        dataset.SliceThickness = float(spacing[0])

        dataset.Modality = 'WSD'
        dataset.Columns = pixel_array.shape[0]
        dataset.Rows = pixel_array.shape[1]
        dataset.file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian
        dataset.PixelRepresentation = 1
        dataset.BitsAllocated = 16
        dataset.BitsStored = 16
        dataset.SamplesPerPixel = 1

        write_file(filename, dataset)
예제 #13
0
def generate_dicom_scans(dst, num_scans=10, intercept=0, slope=1):
    spacing = (0.4 + 0.4 * np.random.rand(num_scans, 3) +
               np.array([1 + 0.5 * np.random.rand(), 0, 0]))
    origin = np.random.randint(-200, 200, (num_scans, 3))
    for i in range(num_scans):
        num_slices = np.random.randint(128, 169)
        scan_id = np.random.randint(2**16)
        scan_data = np.random.randint(0, 256, (num_slices, 128, 128))
        folder = os.path.join(dst,
                              hex(scan_id).replace('x', '').upper().zfill(8))

        if not os.path.exists(folder):
            os.makedirs(folder)

        for k in range(num_slices):
            slice_name = (hex(scan_id + k).replace('x', '').upper().zfill(8))
            filename = os.path.join(folder, slice_name)
            pixel_array = (scan_data[k, ...] - intercept) / slope
            locZ = float(origin[i, 0] + spacing[i, 0] * k)
            locY, locX = float(origin[i, 1]), float(origin[i, 2])

            file_meta = DicomDataset()
            file_meta.MediaStorageSOPClassUID = "Secondary Capture Image Storage"
            file_meta.MediaStorateSOPInstanceUID = (hex(scan_id).replace(
                'x', '').upper().zfill(8))

            file_meta.ImplementationClassUID = slice_name

            dataset = DicomFileDataset(filename, {},
                                       file_meta=file_meta,
                                       preamble=b"\0" * 128)

            dataset.PixelData = pixel_array.astype(np.uint16).tostring()
            dataset.RescaleSlope = slope
            dataset.RescaleIntercept = intercept

            dataset.ImagePositionPatient = MultiValue(
                type_constructor=float, iterable=[locZ, locY, locX])

            dataset.PixelSpacing = MultiValue(
                type_constructor=float,
                iterable=[float(spacing[i, 1]),
                          float(spacing[i, 2])])
            dataset.SliceThickness = float(spacing[i, 0])

            dataset.Modality = 'WSD'
            dataset.Columns = pixel_array.shape[0]
            dataset.Rows = pixel_array.shape[1]
            dataset.file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian
            dataset.PixelRepresentation = 1
            dataset.BitsAllocated = 16
            dataset.BitsStored = 16
            dataset.SamplesPerPixel = 1

            write_file(filename, dataset)
예제 #14
0
    def createStructDS(self, planData, ImageInfoUIDs, setupPosition,
                       roiShiftVector):
        print("Creating Data structure")
        # create RS SOPInstanceUID
        structSOPInstanceUID = pydicom.uid.generate_uid()
        structSeriesInstanceUID = pydicom.uid.generate_uid()

        # get image header info from ImageSet_0.ImageInfo
        structFrameUID = ''
        structStudyInstanceUID = ''
        structSeriesUID = ''
        structClassUID = '1.2.840.10008.5.1.4.1.1.481.3'
        if "ImageInfoList" in ImageInfoUIDs:
            structFrameUID = ImageInfoUIDs.ImageInfoList[0].FrameUID
            structStudyInstanceUID = ImageInfoUIDs.ImageInfoList[
                0].StudyInstanceUID
            structSeriesUID = ImageInfoUIDs.ImageInfoList[0].SeriesUID
            # structClassUID = ImageInfoUIDs.ImageInfoList[0].ClassUID

        # Populate required values for file meta information
        file_meta = Dataset()
        # RT Structure Set Storage
        file_meta.MediaStorageSOPClassUID = structClassUID
        file_meta.MediaStorageSOPInstanceUID = structSOPInstanceUID
        structfilename = "RS." + structSOPInstanceUID + ".dcm"
        # this value remains static since implementation for creating file is the same
        file_meta.ImplementationClassUID = '1.2.826.0.1.3680043.8.498.75006884747854523615841001'
        # Create the FileDataset instance (initially no data elements, but file_meta supplied)
        ds = FileDataset(structfilename, {},
                         file_meta=file_meta,
                         preamble=b'\x00' * 128)
        # print(file_meta.preamble)

        # add info_data,basic patientinfo
        # [0008,0005] - [0008,0018]
        ds.SpecificCharacterSet = 'ISO_IR 100'
        ds.InstanceCreationDate = time.strftime("%Y%m%d")
        ds.InstanceCreationTime = time.strftime("%H%M%S")
        ds.SOPClassUID = structClassUID
        ds.SOPInstanceUID = structSOPInstanceUID
        ds.Modality = 'RTSTRUCT'
        ds.AccessionNumber = ""
        ds.Manufacturer = 'Pinnalce3'  # from sample dicom file, maybe should change?
        # not sure where to get information for this element can find this and read in from
        ds.StationName = "adacp3u7"
        # ds.ManufacturersModelName = 'Pinnacle3'
        ds = self.modifyPatientInfo(ds, planData)

        # [0008,1110]
        ds.ReferencedStudySequence = Sequence()
        ReferencedStudy1 = Dataset()
        ds.ReferencedStudySequence.append(ReferencedStudy1)
        # Study Component Management SOP Class (chosen from template)
        ds.ReferencedStudySequence[
            0].ReferencedSOPClassUID = '1.2.840.10008.3.1.2.3.2'
        ds.ReferencedStudySequence[
            0].ReferencedSOPInstanceUID = structStudyInstanceUID
        # ds.StudyInstanceUID = StudyInstanceUID
        print("Setting structure file study instance: " +
              str(structStudyInstanceUID))
        # [0020,000d]
        ds.StudyInstanceUID = structStudyInstanceUID
        # [0020,000e]
        ds.SeriesInstanceUID = structSeriesInstanceUID

        # [3006,0010]
        ds.ReferencedFrameOfReferenceSequence = Sequence()
        ReferencedFrameofReference1 = Dataset()
        ds.ReferencedFrameOfReferenceSequence.append(
            ReferencedFrameofReference1)
        ds.ReferencedFrameOfReferenceSequence[
            0].FrameofReferenceUID = structFrameUID
        # [3006,0012]
        ds.ReferencedFrameOfReferenceSequence[
            0].RTReferencedStudySequence = Sequence()
        RTReferencedStudy1 = Dataset()
        ds.ReferencedFrameOfReferenceSequence[
            0].RTReferencedStudySequence.append(RTReferencedStudy1)
        ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
            0].ReferencedSOPClassUID = '1.2.840.10008.3.1.2.3.2'
        ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
            0].ReferencedSOPInstanceUID = structStudyInstanceUID
        # ds.StudyInstanceUID = StudyInstanceUID
        # [3006,0014]
        ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
            0].RTReferencedSeriesSequence = Sequence()
        RTReferencedSeries1 = Dataset()
        ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
            0].RTReferencedSeriesSequence.append(RTReferencedSeries1)
        ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
            0].RTReferencedSeriesSequence[
                0].SeriesInstanceUID = structSeriesUID

        # [3006,0016]
        ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
            0].RTReferencedSeriesSequence[0].ContourImageSequence = Sequence()

        # [fffe,e000]
        for i, value in enumerate(ImageInfoUIDs.ImageInfoList, 1):
            exec("ContourImage%d = Dataset()" % i)
            exec(
                "ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[0].RTReferencedSeriesSequence[0].ContourImageSequence.append(ContourImage%d)"
                % i)
            ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
                0].RTReferencedSeriesSequence[0].ContourImageSequence[
                    i - 1].ReferencedSOPClassUID = value.ClassUID
            ds.ReferencedFrameOfReferenceSequence[0].RTReferencedStudySequence[
                0].RTReferencedSeriesSequence[0].ContourImageSequence[
                    i - 1].ReferencedSOPInstanceUID = value.InstanceUID
            # exec("del ContourImage%d" % i)

        # [3006,0020]
        roiListData = planData.planROIsRawData.roiList
        ds.StructureSetROISequence = Sequence()
        for i, value in enumerate(roiListData, 1):
            exec("ROISet%d = Dataset()" % i)
            exec("ds.StructureSetROISequence.append(ROISet%d)" % i)
            ds.StructureSetROISequence[i - 1].ROIName = value.name
            ds.StructureSetROISequence[i - 1].ROINumber = i
            ds.StructureSetROISequence[
                i - 1].ReferencedFrameOfReferenceUID = structFrameUID
            if 'volume' in value:
                ds.StructureSetROISequence[i - 1].ROIVolume = value.volume
            ds.StructureSetROISequence[
                i - 1].ROIGenerationAlgorithm = value.roiinterpretedtype

        # [3006,0039]get each ROI
        ds.ROIContourSequence = Sequence()
        for i, value in enumerate(roiListData, 1):
            exec("ContourSequence%d = Dataset()" % i)
            exec("ds.ROIContourSequence.append(ContourSequence%d)" % i)
            ds.ROIContourSequence[i - 1].ROIDisplayColor = [0, 255, 0]
            ds.ROIContourSequence[i - 1].ReferencedROINumber = i

            # get all curves in current ROI
            ds.ROIContourSequence[i - 1].ContourSequence = Sequence()
            planROIsCurvesList = value.num_curve
            # get each ROI_Curvers
            for j, data in enumerate(planROIsCurvesList, 1):
                exec("CurvesPoint%d = Dataset()" % j)
                exec(
                    "ds.ROIContourSequence[i - 1].ContourSequence.append(CurvesPoint%d)"
                    % j)
                # [3006,0040]
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].ContourImageSequence = Sequence()
                coutourImage1 = Dataset()
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].ContourImageSequence.append(coutourImage1)
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].ContourImageSequence[
                        0].ReferencedSOPClassUID = structClassUID
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].ContourImageSequence[
                        0].ReferencedSOPInstanceUID = self.getCTInstanceUID(
                            data.Points[0], setupPosition, ImageInfoUIDs)

                # [3006,0042]
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].ContourGeometricType = "CLOSED_PLANAR"
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].NumberOfContourPoints = data.num_points
                # get each ROI_Curves_Points, using data.Points
                ds.ROIContourSequence[i - 1].ContourSequence[
                    j - 1].ContourData = self.getContourCurvePoints(
                        data.Points, setupPosition, roiShiftVector)

        # [3006,0080]
        ds.RTROIObservationsSequence = Sequence()
        for i, current_roi in enumerate(ds.StructureSetROISequence, 1):
            exec("Observation%d = Dataset()" % i)
            exec("ds.RTROIObservationsSequence.append(Observation%d)" % i)
            ds.RTROIObservationsSequence[
                i - 1].ObservationNumber = current_roi.ROINumber
            ds.RTROIObservationsSequence[
                i - 1].ReferencedROINumber = current_roi.ROINumber
            ds.RTROIObservationsSequence[i - 1].RTROIInterpretedType = 'ORGAN'
            ds.RTROIObservationsSequence[i - 1].ROIInterpreter = ""

        # find out where to get if its been approved or not
        ds.ApprovalStatus = 'UNAPPROVED'
        # Set the transfer syntax
        ds.is_little_endian = True
        ds.is_implicit_VR = True

        # # Create the FileDataset instance (initially no data elements, but file_meta supplied)
        # structds = FileDataset(structfilename, {},
        #                  file_meta=ds, preamble=b'\x00' * 128)

        # structfilepath=outputfolder + patientfolder + "/" + structfilename
        # structds.save_as("structfilepath")
        # print("Structure file being saved\n")
        ds.save_as(os.getenv('HOME') + '/PinnWork/' + structfilename)
        #
        # dcmds = pydicom.dcmread(ds)
        # print(dcmds)
        return ds
예제 #15
0
    def create_dcm_file(self):
        suffix = '.dcm'
        filename_little_endian = tempfile.NamedTemporaryFile(
            suffix=suffix).name
        filename_big_endian = tempfile.NamedTemporaryFile(suffix=suffix).name

        print("Setting file meta information...")
        file_meta = Dataset()
        file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2'
        file_meta.MediaStorageSOPInstanceUID = "1.2.3"
        file_meta.ImplementationClassUID = "1.2.3.4"

        print("Setting dataset values...")

        ds = FileDataset(filename_little_endian, {},
                         file_meta=file_meta,
                         preamble=b"\0" * 128)

        ds.PatientName = self.get_patient_name(
        ) + " " + self.get_patient_surname()
        ds.PatientID = self.get_patient_id()
        ds.PatientSex = self.get_patient_sex()
        ds.PatientAge = self.get_patient_age()
        ds.PatientWeight = self.get_patient_weight()
        ds.ImageComment = self.get_patient_comment()
        ds.PatientBirthDate = self.get_patient_birth()

        # Set the transfer syntax
        ds.is_little_endian = True
        ds.is_implicit_VR = True

        # Set creation date/time
        dt = datetime.datetime.now()
        ds.ContentDate = dt.strftime('%Y%m%d')
        timeStr = dt.strftime('%H%M%S.%f')  # long format with micro seconds
        ds.ContentTime = timeStr
        ds.BitsAllocated = 16
        ds.Rows = self.image.shape[0]
        ds.Columns = self.image.shape[1]
        ds.PixelRepresentation = 0
        ds.SamplesPerPixel = 1
        ds.PhotometricInterpretation = "MONOCHROME2"
        image = self.image
        image *= 255
        image = image.astype("uint16")
        ds.PixelData = Image.fromarray(image).tobytes()
        print("Writing test file", filename_little_endian)
        ds.save_as(filename_little_endian)
        print("File saved.")

        ds.file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRBigEndian
        ds.is_little_endian = False
        ds.is_implicit_VR = False

        print("Writing test file as Big Endian Explicit VR",
              filename_big_endian)
        ds.save_as(filename_big_endian)
        return ds
예제 #16
0
    def generate_common_dicom_dataset_series(self, slice_count: int,
                                             system: Modality) -> list:
        output_dataset = []
        slice_pos = 0
        slice_thickness = 0
        study_uid = generate_uid()
        series_uid = generate_uid()
        frame_of_ref_uid = generate_uid()
        date_ = datetime.now().date()
        age = timedelta(days=45 * 365)
        time_ = datetime.now().time()
        cols = 2
        rows = 2
        bytes_per_voxel = 2

        for i in range(0, slice_count):
            file_meta = Dataset()
            pixel_array = b"\0" * cols * rows * bytes_per_voxel
            file_meta.MediaStorageSOPClassUID = sop_classes[system][1]
            file_meta.MediaStorageSOPInstanceUID = generate_uid()
            file_meta.ImplementationClassUID = generate_uid()

            tmp_dataset = FileDataset('', {},
                                      file_meta=file_meta,
                                      preamble=pixel_array)
            tmp_dataset.file_meta.TransferSyntaxUID = "1.2.840.10008.1.2.1"
            tmp_dataset.SliceLocation = slice_pos + i * slice_thickness
            tmp_dataset.SliceThickness = slice_thickness
            tmp_dataset.WindowCenter = 1
            tmp_dataset.WindowWidth = 2
            tmp_dataset.AcquisitionNumber = 1
            tmp_dataset.InstanceNumber = i
            tmp_dataset.SeriesNumber = 1
            tmp_dataset.ImageOrientationPatient = [
                1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000
            ]
            tmp_dataset.ImagePositionPatient = [
                0.0, 0.0, tmp_dataset.SliceLocation
            ]
            tmp_dataset.ImageType = ['ORIGINAL', 'PRIMARY', 'AXIAL']
            tmp_dataset.PixelSpacing = [1, 1]
            tmp_dataset.PatientName = 'John Doe'
            tmp_dataset.FrameOfReferenceUID = frame_of_ref_uid
            tmp_dataset.SOPClassUID = sop_classes[system][1]
            tmp_dataset.SOPInstanceUID = generate_uid()
            tmp_dataset.SeriesInstanceUID = series_uid
            tmp_dataset.StudyInstanceUID = study_uid
            tmp_dataset.BitsAllocated = bytes_per_voxel * 8
            tmp_dataset.BitsStored = bytes_per_voxel * 8
            tmp_dataset.HighBit = (bytes_per_voxel * 8 - 1)
            tmp_dataset.PixelRepresentation = 1
            tmp_dataset.Columns = cols
            tmp_dataset.Rows = rows
            tmp_dataset.SamplesPerPixel = 1
            tmp_dataset.AccessionNumber = '2'
            tmp_dataset.AcquisitionDate = date_
            tmp_dataset.AcquisitionTime = datetime.now().time()
            tmp_dataset.AdditionalPatientHistory = 'UTERINE CA PRE-OP EVAL'
            tmp_dataset.ContentDate = date_
            tmp_dataset.ContentTime = datetime.now().time()
            tmp_dataset.Manufacturer = 'Mnufacturer'
            tmp_dataset.ManufacturerModelName = 'Model'
            tmp_dataset.Modality = sop_classes[system][0]
            tmp_dataset.PatientAge = '064Y'
            tmp_dataset.PatientBirthDate = date_ - age
            tmp_dataset.PatientID = 'ID0001'
            tmp_dataset.PatientIdentityRemoved = 'YES'
            tmp_dataset.PatientPosition = 'FFS'
            tmp_dataset.PatientSex = 'F'
            tmp_dataset.PhotometricInterpretation = 'MONOCHROME2'
            tmp_dataset.PixelData = pixel_array
            tmp_dataset.PositionReferenceIndicator = 'XY'
            tmp_dataset.ProtocolName = 'some protocole'
            tmp_dataset.ReferringPhysicianName = ''
            tmp_dataset.SeriesDate = date_
            tmp_dataset.SeriesDescription = 'test series '
            tmp_dataset.SeriesTime = time_
            tmp_dataset.SoftwareVersions = '01'
            tmp_dataset.SpecificCharacterSet = 'ISO_IR 100'
            tmp_dataset.StudyDate = date_
            tmp_dataset.StudyDescription = 'test study'
            tmp_dataset.StudyID = ''
            if (system == Modality.CT):
                tmp_dataset.RescaleIntercept = 0
                tmp_dataset.RescaleSlope = 1
            tmp_dataset.StudyTime = time_
            output_dataset.append(tmp_dataset)
        return output_dataset