Esempio n. 1
0
    def test_request_data_set(self):
        # Selector
        selector = odil.webservices.Selector()
        selector.set_study("1.2").set_instance("")
        # DataSet
        dataset = odil.DataSet()
        dataset.add(odil.Tag("PatientName"), ["TOTO"])
        dataset.add(odil.Tag("00200020"))
        shared = odil.DataSet()
        shared.add(odil.Tag("StudyDate"), [20130509])
        shared.add(odil.Tag("00200035"))
        dataset.add(odil.Tag("SharedFunctionalGroupsSequence"), [shared])

        request = odil.webservices.QIDORSRequest(self.base_url_http)
        request.request_datasets(
            odil.webservices.Utils.Representation.DICOM_XML, selector, dataset)

        full_url_alphabetic_tags = odil.webservices.URL(
            "http", "example.com", "/dicom/studies/1.2/instances",
            "PatientName=TOTO&"
            "SharedFunctionalGroupsSequence.StudyDate=20130509&"
            "includefield=PatientOrientation&"
            "includefield=SharedFunctionalGroupsSequence.ImageOrientation&"
            "fuzzymatching=false", "")
        self.assertEqual(request.get_http_request().get_target(),
                         full_url_alphabetic_tags)
        self.assertEqual(request.get_http_request().get_method(), "GET")
Esempio n. 2
0
 def test_get_stacks_inversion_times(self):
     # Test multiFrame dataSet
     ds = odil.DataSet()
     shared = odil.DataSet()
     per_frame = []
     first_frame = odil.DataSet()
     mr_modifier_seq = odil.DataSet()
     mr_modifier_seq.add("InversionTimes", [300.])
     first_frame.add("MRModifierSequence", [mr_modifier_seq])
     per_frame.append(first_frame)
     second_frame = odil.DataSet()
     mr_modifier_seq.add("InversionTimes", [1000.])
     second_frame.add("MRModifierSequence", [mr_modifier_seq])
     per_frame.append(second_frame)
     third_frame = odil.DataSet()
     mr_modifier_seq.add("InversionTimes", [300.])
     third_frame.add("MRModifierSequence", [mr_modifier_seq])
     per_frame.append(third_frame)
     ds.add("SOPClassUID", [odil.registry.EnhancedMRImageStorage])
     ds.add("PerFrameFunctionalGroupsSequence", per_frame)
     ds.add("SharedFunctionalGroupsSequence", [shared])
     ds.add("NumberOfFrames", [len(per_frame)])
     stacks = get_stacks([ds])
     inversionTimes_tag = str(odil.Tag("InversionTimes"))
     mr_modifier_seq_tag = str(odil.Tag("MRModifierSequence"))
     per_frame_tag = str(odil.Tag("PerFrameFunctionalGroupsSequence"))
     wanted_stacks = {
         (((per_frame_tag, mr_modifier_seq_tag, inversionTimes_tag), (300., )), ):
         [(ds, 0), (ds, 2)],
         (((per_frame_tag, mr_modifier_seq_tag, inversionTimes_tag), (1000., )), ):
         [(ds, 1)],
     }
     self.assertEqual(wanted_stacks, stacks)
Esempio n. 3
0
    def test_hash(self):
        tag = odil.Tag(
            odil.registry.PatientName.group, odil.registry.PatientName.element)
        d = {tag: True}

        self.assertTrue(tag in d)
        self.assertTrue(odil.registry.PatientName in d)

        other = odil.Tag(
            odil.registry.PatientID.group, odil.registry.PatientID.element)
Esempio n. 4
0
 def test_query_dataset(self):
     http_request = odil.webservices.HTTPRequest("GET", self.full_url)
     http_request.set_header("Accept", "application/dicom+json")
     request = odil.webservices.QIDORSRequest(http_request)
     # Check For DataSet
     dataset = odil.DataSet()
     dataset.add(odil.Tag("PatientName"), ["TOTO"])
     dataset.add(odil.Tag("00200020"))
     shared = odil.DataSet()
     shared.add(odil.Tag("EffectiveEchoTime"), [10.5])
     shared.add(odil.Tag("00200035"))
     dataset.add(odil.Tag("SharedFunctionalGroupsSequence"), [shared])
     self.assertEqual(request.get_query_data_set(), dataset)
Esempio n. 5
0
    def test_get_stacks_orientation(self):
        # Test with multi_frame dataSets (one dataSet will have the orientation stored in the
        # shared and the second in the per_frame)
        # This example is only here to show the importance of the tag location (per_frame or shared)
        ds = odil.DataSet()
        ds.add("SOPClassUID", [odil.registry.EnhancedMRImageStorage])
        shared = odil.DataSet()
        plane_ori_seq = odil.DataSet()
        plane_ori_seq.add("ImageOrientationPatient",
                          [1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
        shared.add("PlaneOrientationSequence", [plane_ori_seq])
        per_frame = [odil.DataSet(), odil.DataSet()]  # two frames both empty
        ds.add("SharedFunctionalGroupsSequence", [shared])
        ds.add("PerFrameFunctionalGroupsSequence", per_frame)
        ds.add("NumberOfFrames", [len(per_frame)])

        ds2 = odil.DataSet()
        ds2.add("SOPClassUID", [odil.registry.EnhancedMRImageStorage])
        ds2.add("SharedFunctionalGroupsSequence", [odil.DataSet()])
        per_frame = []
        first_frame = odil.DataSet()
        plane_ori_seq = odil.DataSet()
        plane_ori_seq.add("ImageOrientationPatient",
                          [1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
        first_frame.add("PlaneOrientationSequence", [plane_ori_seq])
        per_frame.append(first_frame)
        second_frame = odil.DataSet()
        plane_ori_seq.add("ImageOrientationPatient",
                          [1.0, 0.0, 0.0, 0.0, -1.0, 0.0])
        second_frame.add("PlaneOrientationSequence", [plane_ori_seq])
        per_frame.append(second_frame)
        ds2.add("PerFrameFunctionalGroupsSequence", per_frame)
        ds2.add("NumberOfFrames", [len(per_frame)])

        stacks = get_stacks([ds, ds2])
        imageOrientationTag = str(odil.Tag("ImageOrientationPatient"))
        plane_ori_seq_tag = str(odil.Tag("PlaneOrientationSequence"))
        per_frame_tag = str(odil.Tag("PerFrameFunctionalGroupsSequence"))
        shared_tag = str(odil.Tag("SharedFunctionalGroupsSequence"))
        wanted_stacks = {
            (((shared_tag, plane_ori_seq_tag, imageOrientationTag), (1.0, 0.0, 0.0, 0.0, 1.0, 0.0)), ):
            [(ds, 0), (ds, 1)],
            (((per_frame_tag, plane_ori_seq_tag, imageOrientationTag), (1.0, 0.0, 0.0, 0.0, 1.0, 0.0)), ):
            [(ds2, 0)],
            (((per_frame_tag, plane_ori_seq_tag, imageOrientationTag), (1.0, 0.0, 0.0, 0.0, -1.0, 0.0)), ):
            [(ds2, 1)],
        }
        self.assertEqual(stacks, wanted_stacks)
Esempio n. 6
0
 def test_contains(self):
     self.assertTrue(
         odil.registry.PatientName in odil.registry.public_dictionary)
     self.assertFalse(
         odil.Tag(0x0001, 0x0001) in odil.registry.public_dictionary)
     self.assertTrue("60xx0010" in odil.registry.public_dictionary)
     self.assertFalse("foo" in odil.registry.public_dictionary)
Esempio n. 7
0
 def test_default_finder(self):
     finder = odil.VRFinder()
     data_set = odil.DataSet()
     data_set.add(odil.registry.BitsAllocated, [8])
     vr = finder(
         odil.Tag(0x7fe0, 0x0010), data_set,
         odil.registry.ExplicitVRLittleEndian)
     self.assertEqual(vr, odil.VR.OB)
Esempio n. 8
0
 def test_sort_in_stack_position(self):
     ds = odil.DataSet()
     stack_id_seq = odil.DataSet()
     stack_id_seq.add("DimensionOrganizationUID",
                      ["1.3.6.1.4.1.5962.1.6.5012.1.0.1166546115.14677"])
     stack_id_seq.add("DimensionIndexPointer", ["00209056"])
     stack_id_seq.add("FunctionalGroupPointer", ["00209111"])
     in_stack_seq = odil.DataSet()
     in_stack_seq.add("DimensionOrganizationUID",
                      ["1.3.6.1.4.1.5962.1.6.5012.1.0.1166546115.14677"])
     in_stack_seq.add("DimensionIndexPointer", ["00209057"])
     in_stack_seq.add("FunctionalGroupPointer", ["00209111"])
     ds.add("DimensionIndexSequence", [stack_id_seq, in_stack_seq])
     shared = odil.DataSet()
     ds.add("SharedFunctionalGroupsSequence", [shared])
     per_frame = []
     first_frame = odil.DataSet()
     frame_content_seq = odil.DataSet()
     frame_content_seq.add("DimensionIndexValues",
                           [10, 5])  # StackID , In Stack Pos
     first_frame.add("FrameContentSequence", [frame_content_seq])
     per_frame.append(first_frame)
     second_frame = odil.DataSet()
     frame_content_seq.add("DimensionIndexValues", [10, 4])
     second_frame.add("FrameContentSequence", [frame_content_seq])
     per_frame.append(second_frame)
     third_frame = odil.DataSet()
     frame_content_seq.add("DimensionIndexValues", [10, 6])
     third_frame.add("FrameContentSequence", [frame_content_seq])
     per_frame.append(third_frame)
     ds.add("PerFrameFunctionalGroupsSequence", per_frame)
     ds.add("NumberOfFrames", [len(per_frame)])
     data_sets_frame_index = [(ds, 0), (ds, 1), (ds, 2)]
     wanted_order = [(ds, 1), (ds, 0), (ds, 2)]
     per_frame_tag = str(odil.Tag("PerFrameFunctionalGroupsSequence"))
     frame_content_seq_tag = str(odil.Tag("FrameContentSequence"))
     dimension_index_values_tag = str(odil.Tag("DimensionIndexValues"))
     #input = key with value = (10,) element of DimensionIndexValue without inStackPosition
     key = ((per_frame_tag, frame_content_seq_tag,
             dimension_index_values_tag), (10, ))
     sort((key, ), data_sets_frame_index)
     print data_sets_frame_index
     self.assertEqual(wanted_order, data_sets_frame_index)
Esempio n. 9
0
 def test_get_stacks_echo_time(self):
     # Test single frame dataSets
     ds = [odil.DataSet() for x in range(3)]
     ds[0].add("SOPClassUID", [odil.registry.MRImageStorage])
     ds[0].add("EchoTime", [25.])
     ds[0].add("PatientName", ["Pacino^Al"])
     ds[1].add("SOPClassUID", [odil.registry.MRImageStorage])
     ds[1].add("EchoTime", [20.])
     ds[2].add("SOPClassUID", [odil.registry.MRImageStorage])
     ds[2].add("EchoTime", [25.])
     stacks = get_stacks(ds)
     echoTime_tag = str(odil.Tag("EchoTime"))
     wanted_stacks = {
         (((None, None, echoTime_tag), (25., )), ): [(ds[0], None),
                                                     (ds[2], None)],
         (((None, None, echoTime_tag), (20., )), ): [(ds[1], None)]
     }
     self.assertEqual(wanted_stacks, stacks)
Esempio n. 10
0
def sort(keys, data_sets_frame_idx):
    """ Sort current stack frames/datasets depending on their common keys
        :param keys: Keys shared by all element of the stack
        :param data_sets_frame_idx: List containing the data sets of the frame 
                                    with the corresponding frame when it's a multiframe data set
    """

    number_of_frames = len(data_sets_frame_idx)
    if number_of_frames == 1:
        # WARNING : Can cause some problem when opening .nii file with Slicer
        logger.debug("Only one frame in the current stack")
        return
    else:
        for key in keys:
            for tags, value in keys:
                top_seq, sub_seq, tag = tags
                if str(odil.registry.DimensionIndexValues) == tag:
                    # sort by In-Stack Position
                    in_stack_position = []
                    for data_set, index in data_sets_frame_idx:
                        in_stack_position_idx = odil_getter.get_in_stack_position_index(
                            data_set)
                        frame = data_set.as_data_set(
                            odil.registry.PerFrameFunctionalGroupsSequence
                        )[index]
                        frame_content_seq = frame.as_data_set(
                            odil.registry.FrameContentSequence)[0]
                        in_stack_position.append(
                            frame_content_seq.as_int(
                                odil.registry.DimensionIndexValues)
                            [in_stack_position_idx])
                    sorted_in_stack = sorted(
                        range(len(in_stack_position)),
                        key=lambda k: in_stack_position[k])
                    keydict = dict(zip(data_sets_frame_idx, sorted_in_stack))
                    data_sets_frame_idx.sort(key=keydict.get)
                    return
                if str(odil.registry.ImageOrientationPatient) == tag:
                    if sort_position(data_sets_frame_idx, value) == True:
                        return
        available_tags = [x[0][2] for x in keys if len(x) > 1]
        logger.warning(
            "Cannot sort frames for the moment, available tags : {}".format(
                [odil.Tag(x).get_name() for x in available_tags]))
Esempio n. 11
0
def convert_element(element, specific_character_set):
    """ Convert a DICOM element to its NIfTI+JSON representation: the "Value"
        (or "InlineBinary") attribute of its standard DICOM JSON 
        representation.
    """

    result = None
    # element can be None because a get is called above
    if element is None:
        result = None
    elif element.empty():
        result = None
    elif element.is_int():
        result = list(element.as_int())
    elif element.is_real():
        result = list(element.as_real())
    elif element.is_string():
        if element.vr.name in ["LO", "LT", "PN", "SH", "ST", "UT"]:
            data_set = odil.DataSet()
            if specific_character_set:
                data_set.add(odil.registry.SpecificCharacterSet,
                             specific_character_set)
            data_set.add(odil.Tag(0xffff, 0xffff), element.as_string(),
                         element.vr)
            result = json.loads(odil.as_json(data_set))["ffffffff"]["Value"]
        else:
            result = list(element.as_string())
    elif element.is_data_set():
        result = [
            convert_data_set(x, specific_character_set)
            for x in element.as_data_set()
        ]
    elif element.is_binary():
        result = [
            base64.b64encode(x.get_memory_view().tobytes())
            for x in element.as_binary()
        ]
    else:
        raise Exception("Unknown element type")

    return result
Esempio n. 12
0
def get_in_stack_position_index(data_set):
    """ Will return the position of in-Stack-Position element in the dimensionIndexValue
        Return None if no In-Stack-Position found
    """

    if data_set.has(odil.registry.DimensionIndexSequence) and \
            not data_set.empty(odil.registry.DimensionIndexSequence):
        dimension_index_sequences = data_set.as_data_set(
            odil.registry.DimensionIndexSequence)
        position = set()
        for i, dimension_index_sequence in enumerate(dimension_index_sequences):
            if dimension_index_sequence.has(odil.registry.DimensionIndexPointer):
                idx = dimension_index_sequence.as_string(
                    odil.registry.DimensionIndexPointer)[0]
                if odil.Tag(idx) == odil.registry.InStackPositionNumber:
                    position.add(i)
        if len(position) == 1:
            return list(position)[0]
        else:
            return None
    else:
        return None
Esempio n. 13
0
 def test_string_constructor(self):
     tag = odil.Tag("PatientID")
     self.assertEqual(tag.group, 0x0010)
     self.assertEqual(tag.element, 0x0020)
Esempio n. 14
0
 def test_str(self):
     tag = odil.Tag(0x1234, 0x5678)
     self.assertEqual(str(tag), "12345678")
Esempio n. 15
0
 def test_greater_or_equal(self):
     tag1 = odil.Tag(0x1234, 0x5678)
     tag2 = odil.Tag(0x4321, 0x8765)
     self.assertFalse(tag1 >= tag2)
     self.assertTrue(tag1 >= tag1)
     self.assertTrue(tag2 >= tag1)
Esempio n. 16
0
 def test_less_or_equal(self):
     tag1 = odil.Tag(0x1234, 0x5678)
     tag2 = odil.Tag(0x4321, 0x8765)
     self.assertTrue(tag1 <= tag2)
     self.assertTrue(tag1 <= tag1)
     self.assertFalse(tag2 <= tag1)
Esempio n. 17
0
 def test_two_ints_constructor(self):
     tag = odil.Tag(0x1234, 0x5678)
     self.assertEqual(tag.group, 0x1234)
     self.assertEqual(tag.element, 0x5678)
Esempio n. 18
0
 def test_inequality(self):
     tag1 = odil.Tag(0x1234, 0x5678)
     tag2 = odil.Tag(0x4321, 0x8765)
     self.assertFalse(tag1 != tag1)
     self.assertTrue(tag1 != tag2)
Esempio n. 19
0
 def test_get_name(self):
     tag = odil.Tag(0x0010, 0x0020)
     self.assertEqual(tag.get_name(), "PatientID")
Esempio n. 20
0
    def test_is_private(self):
        public = odil.Tag(0x1234, 0x5678)
        self.assertTrue(not public.is_private())

        private = odil.Tag(0x1235, 0x5678)
        self.assertTrue(private.is_private())
Esempio n. 21
0
 def test_element(self):
     tag = odil.Tag(0x1234, 0x5678)
     tag.element = 0x8765
     self.assertEqual(tag.group, 0x1234)
     self.assertEqual(tag.element, 0x8765)
Esempio n. 22
0
 def test_get_tag_name(self):
     patient_name_tag = odil.Tag("PatientName")
     tag_name = dicomifier.dicom_to_nifti.meta_data.get_tag_name(
         patient_name_tag)
     self.assertEqual("PatientName", tag_name)
Esempio n. 23
0
def get_image(data_sets_frame_idx, dtype, cache):
    """ Get the nifti image of the current stack
        :param data_sets_frame_idx: List containing the data sets of the frame 
                                    with the corresponding frame when it's a multiframe data set
        :param dtype: wanted type
        :return image: a nifti image
    """

    # Cache the linear pixel data since this is a time-consuming operation for
    # large data sets and needs to be repeated for multi-frame data sets.
    for data_set, frame_idx in data_sets_frame_idx:
        if data_set.as_string("SOPInstanceUID")[0] not in cache:
            linear_array = get_linear_pixel_data(data_set)
            cache[data_set.as_string("SOPInstanceUID")[0]] = linear_array

    pixel_data_list = [
        get_shaped_pixel_data(data_set,
                              cache[data_set.as_string("SOPInstanceUID")[0]],
                              frame_idx)
        for data_set, frame_idx in data_sets_frame_idx
    ]

    if dtype is None:
        has_float = any(x.dtype.kind == "f" for x in pixel_data_list)
        if has_float:
            dtype = numpy.float32
        else:
            # Assume all data sets have the same type
            dtype = pixel_data_list[0].dtype
        logger.info("dtype deduced to be: {}".format(dtype))

    pixel_data = numpy.ndarray(
        (len(data_sets_frame_idx), ) + pixel_data_list[0].shape, dtype=dtype)
    for i, data in enumerate(pixel_data_list):
        pixel_data[i] = data

    scanner_transform = numpy.identity(4)

    origin, spacing, direction = get_geometry(data_sets_frame_idx)

    image_type = (data_sets_frame_idx[0][0].as_string("ImageType")
                  if "ImageType" in data_sets_frame_idx[0][0] else [])
    if len(data_sets_frame_idx
           ) == 1 and b"MOSAIC" in image_type and "00291010" in data_set:
        data_set = data_sets_frame_idx[0][0]

        siemens_data = data_set.as_binary(odil.Tag("00291010"))[0]
        siemens_header = siemens.parse_csa(
            siemens_data.get_memory_view().tobytes())

        number_of_images_in_mosaic = siemens_header["NumberOfImagesInMosaic"][
            0]
        tiles_per_line = int(math.ceil(math.sqrt(number_of_images_in_mosaic)))

        mosaic_shape = numpy.asarray(pixel_data.shape[-2:])

        rows = round(pixel_data.shape[-2] / tiles_per_line)
        columns = round(pixel_data.shape[-1] / tiles_per_line)

        real_shape = numpy.asarray([rows, columns])

        # Re-arrange array so that tiles are contiguous
        pixel_data = pixel_data.reshape(tiles_per_line, rows, tiles_per_line,
                                        columns)
        pixel_data = pixel_data.transpose((0, 2, 1, 3))
        pixel_data = pixel_data.reshape(tiles_per_line**2, rows, columns)

        # Get the origin of the tiles (i.e. origin of the first tile), cf.
        # http://nipy.org/nibabel/dicom/dicom_mosaic.html
        # WARNING: need to invert their rows and columns
        R = direction[:, :2]
        Q = R * spacing[:2]
        origin = origin + \
            numpy.dot(Q, (mosaic_shape[::-1] - real_shape[::-1]) / 2.)

        direction[:, 2] = siemens_header["SliceNormalVector"]

    samples_per_pix = data_sets_frame_idx[0][0].as_int("SamplesPerPixel")[0]

    if samples_per_pix == 1:
        lps_to_ras = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]

        scanner_transform[:3, :3] = numpy.dot(lps_to_ras, direction)
        scanner_transform[:3, :3] = numpy.dot(scanner_transform[:3, :3],
                                              numpy.diag(spacing))
        scanner_transform[:3, 3] = numpy.dot(lps_to_ras, origin)

    elif samples_per_pix == 3 and data_sets_frame_idx[0][0].as_string(
            "PhotometricInterpretation")[0] == b"RGB":
        if dtype != numpy.uint8:
            raise Exception("Invalid dtype {} for RGB".format(dtype))
        pixel_data = pixel_data.view(
            nibabel.nifti1.data_type_codes.dtype["RGB"]).reshape(
                pixel_data.shape[:3])

    # WARNING: ArrayWriter.to_fileobj is Fortran-order by default whereas numpy
    # is C-order by default
    return nibabel.Nifti1Image(pixel_data.T, scanner_transform)
Esempio n. 24
0
 def test_group(self):
     tag = odil.Tag(0x1234, 0x5678)
     tag.group = 0x4321
     self.assertEqual(tag.group, 0x4321)
     self.assertEqual(tag.element, 0x5678)
Esempio n. 25
0
 def test_cpp_specific(self):
     tag = odil.Tag(0xdead, 0xbeef)
     with self.assertRaises(odil.Exception):
         tag.get_name()