Exemplo 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")
Exemplo n.º 2
0
    def test_write_file_path(self):
        data_set = odil.DataSet()
        data_set.add("SOPClassUID", ["1.2.3.4"])
        data_set.add("SOPInstanceUID", ["1.2.3.4.5"])
        data_set.add("PatientName", ["Foo^Bar"])
        
        fd, path = tempfile.mkstemp()
        os.close(fd)
        
        string_io = BytesIO()
        stream = odil.iostream(string_io)

        odil.Writer.write_file(
            data_set, path, odil.DataSet(),
            odil.registry.ExplicitVRLittleEndian)

        data = (
            128*b"\0"+b"DICM"+
            b"\x02\x00\x00\x00" b"UL" b"\x04\x00" b"\x80\x00\x00\x00"
            b"\x02\x00\x01\x00" b"OB" b"\x00\x00" b"\x02\x00\x00\x00" b"\x00\x01"
            b"\x02\x00\x02\x00" b"UI" b"\x08\x00" b"1.2.3.4\x00"
            b"\x02\x00\x03\x00" b"UI" b"\x0a\x00" b"1.2.3.4.5\x00"
            b"\x02\x00\x10\x00" b"UI" b"\x14\x00" b"1.2.840.10008.1.2.1\x00"
            b"\x02\x00\x12\x00" b"UI" b"\x1e\x00" b"1.2.826.0.1.3680043.9.55600.0\x00"
            b"\x02\x00\x13\x00" b"SH" b"\x06\x00" b"Odil 0"
            b"\x08\x00\x16\x00" b"UI" b"\x08\x00" b"1.2.3.4\x00"
            b"\x08\x00\x18\x00" b"UI" b"\x0a\x00" b"1.2.3.4.5\x00"
            b"\x10\x00\x10\x00" b"PN" b"\x08\x00" b"Foo^Bar ")
        
        with open(path, "rb") as fd:
            contents = fd.read()
        os.remove(path)
        
        self.assertEqual(contents, data)
Exemplo n.º 3
0
    def setUp(self):
        data_set_1 = odil.DataSet()
        data_set_1.add("SOPClassUID", [odil.registry.RawDataStorage])
        data_set_1.add("SOPInstanceUID", ["1.2.3.4"])
        data_set_1.add("PatientID", ["DJ1234"])
        data_set_1.add("PixelSpacing", [1.5, 2.5])

        data_set_2 = odil.DataSet()
        data_set_2.add("SOPClassUID", [odil.registry.MRImageStorage])
        data_set_2.add("SOPInstanceUID", ["1.2.3.5"])
        data_set_2.add("PatientName", ["Doe^John"])
        data_set_2.add("PatientAge", ["042Y"])

        self.data_sets = [data_set_1, data_set_2]

        bin = odil.Value.BinaryItem()
        bin.append(0x01)
        bin.append(0x02)
        bulk_data_1 = odil.webservices.BulkData(bin, "foo/bar", "here")

        bin = odil.Value.BinaryItem()
        bin.append(0x03)
        bin.append(0x04)
        bulk_data_2 = odil.webservices.BulkData(bin, "plip/plop", "not/here")

        self.bulk_data = [bulk_data_1, bulk_data_2]
Exemplo n.º 4
0
    def test_kwargs_constructor(self):
        data_set = odil.DataSet(
            odil.registry.ImplicitVRLittleEndian,
            PatientName=["Doe^John"],
            PatientWeight=[70],
            ReferencedStudySequence=[odil.DataSet(StudyInstanceUID=["1.2.3"])],
            PixelData=[odil.Value.BinaryItem([1, 2, 3])])

        self.assertEqual(data_set.size(), 4)

        self._test_element_value(data_set, "PatientName", [b"Doe^John"],
                                 odil.VR.PN, odil.DataSet.is_string,
                                 odil.DataSet.as_string)
        self._test_element_value(data_set, "PatientWeight", [70], odil.VR.DS,
                                 odil.DataSet.is_int, odil.DataSet.as_int)
        self._test_element_value(data_set, "ReferencedStudySequence",
                                 [odil.DataSet(StudyInstanceUID=["1.2.3"])],
                                 odil.VR.SQ, odil.DataSet.is_data_set,
                                 odil.DataSet.as_data_set)
        self._test_element_value(data_set, "PixelData",
                                 [odil.Value.BinaryItem([1, 2, 3])],
                                 odil.VR.OW, odil.DataSet.is_binary,
                                 odil.DataSet.as_binary)

        with self.assertRaises(odil.Exception):
            odil.DataSet(FooBar=["foo"])
Exemplo n.º 5
0
    def setUp(self):
        data_set_1 = odil.DataSet()
        data_set_1.add("RetrieveURL",
                       ["http://example.com/dicom/studies/7.8.9"])
        data_set_1.add("FailedSOPSequence", [odil.DataSet()], odil.VR.SQ)
        referenceSOPSequence_item1 = odil.DataSet()
        referenceSOPSequence_item1.add("ReferencedSOPClassUID",
                                       [odil.registry.MRImageStorage])
        referenceSOPSequence_item1.add("ReferencedSOPInstanceUID",
                                       ["1.2.3.6.1"])
        referenceSOPSequence_item1.add("RetrieveURL", [
            "http://example.com/dicom/studies/7.8.9/series/4.5/instances/1.2.3.6.1"
        ])

        referenceSOPSequence_item2 = odil.DataSet()
        referenceSOPSequence_item2.add("ReferencedSOPClassUID",
                                       [odil.registry.RawDataStorage])
        referenceSOPSequence_item2.add("ReferencedSOPInstanceUID",
                                       ["1.2.3.6.2"])
        referenceSOPSequence_item2.add("RetrieveURL", [
            "http://example.com/dicom/studies/7.8.9/series/4.5/instances/1.2.3.6.2"
        ])

        data_set_1.add(
            "ReferencedSOPSequence",
            [referenceSOPSequence_item1, referenceSOPSequence_item2])

        self.data_set = data_set_1
Exemplo n.º 6
0
    def test_write_file(self):
        data_set = odil.DataSet()
        data_set.add("SOPClassUID", ["1.2.3.4"])
        data_set.add("SOPInstanceUID", ["1.2.3.4.5"])
        data_set.add("PatientName", ["Foo^Bar"])

        string_io = BytesIO()
        stream = odil.iostream(string_io)

        odil.Writer.write_file(
            data_set, stream, odil.DataSet(),
            odil.registry.ExplicitVRLittleEndian)

        data = (
            128*b"\0"+b"DICM"+
            b"\x02\x00\x00\x00" b"UL" b"\x04\x00" b"\x80\x00\x00\x00"
            b"\x02\x00\x01\x00" b"OB" b"\x00\x00" b"\x02\x00\x00\x00" b"\x00\x01"
            b"\x02\x00\x02\x00" b"UI" b"\x08\x00" b"1.2.3.4\x00"
            b"\x02\x00\x03\x00" b"UI" b"\x0a\x00" b"1.2.3.4.5\x00"
            b"\x02\x00\x10\x00" b"UI" b"\x14\x00" b"1.2.840.10008.1.2.1\x00"
            b"\x02\x00\x12\x00" b"UI" b"\x1e\x00" b"1.2.826.0.1.3680043.9.55600.0\x00"
            b"\x02\x00\x13\x00" b"SH" b"\x06\x00" b"Odil 0"
            b"\x08\x00\x16\x00" b"UI" b"\x08\x00" b"1.2.3.4\x00"
            b"\x08\x00\x18\x00" b"UI" b"\x0a\x00" b"1.2.3.4.5\x00"
            b"\x10\x00\x10\x00" b"PN" b"\x08\x00" b"Foo^Bar ")

        self.assertEqual(string_io.getvalue(), data)
Exemplo n.º 7
0
    def test_data_sets(self):
        data_set_1 = odil.DataSet(PatientID=["DJ1234"])
        data_set_2 = odil.DataSet(EchoTime=[100])
        data_set_3 = odil.DataSet(PixelSpacing=[2.3, 4.5])

        self._test(odil.Value.DataSets(), [data_set_1, data_set_2, data_set_3],
                   [data_set_2, data_set_1], odil.VR.SQ, odil.VR.UN,
                   odil.Element.is_data_set, odil.Element.as_data_set)
Exemplo n.º 8
0
 def test_get_position_single_frame(self):
     data_set = odil.DataSet()
     planePositionSeq = odil.DataSet()
     position = [0.0, 0.0, 1.0]
     planePositionSeq.add("ImagePositionPatient", position)
     data_set.add("PlanePositionSequence", [planePositionSeq])
     val = dicomifier.dicom_to_nifti.odil_getter._get_position(data_set, 0)
     self.assertEqual(None, val)
Exemplo n.º 9
0
 def test_getter_data_set(self):
     data_set = odil.DataSet()
     planePositionSeq = odil.DataSet()
     position = [0.0, 0.0, 1.0]
     planePositionSeq.add("ImagePositionPatient", position)
     data_set.add("PlanePositionSequence", [planePositionSeq])
     val = dicomifier.dicom_to_nifti.odil_getter._getter(
         data_set, odil.registry.PlanePositionSequence)
     self.assertEqual((planePositionSeq, ), val)
Exemplo n.º 10
0
 def test_diffusion_getter_directionality_iso_none(self):
     data_set = odil.DataSet()
     mr_diff_seq = odil.DataSet()
     mr_diff_seq.add("DiffusionBValue", [1000.])
     mr_diff_seq.add("DiffusionDirectionality", ["ISOTROPIC"])
     data_set.add("MRDiffusionSequence", [mr_diff_seq])
     val = dicomifier.dicom_to_nifti.odil_getter._diffusion_getter(
         data_set, odil.registry.MRDiffusionSequence)
     self.assertEqual(val, None)
Exemplo n.º 11
0
    def test_data_sets(self):
        data_set_1 = odil.DataSet()
        data_set_1.add("PatientID", ["DJ1234"])

        data_set_2 = odil.DataSet()
        data_set_2.add("EchoTime", [100])

        self._test(odil.Value.DataSets(), [data_set_1, data_set_2],
                   [data_set_2, data_set_1], odil.VR.SQ, odil.VR.UN,
                   odil.Element.is_data_set, odil.Element.as_data_set)
Exemplo n.º 12
0
    def test_delitem(self):
        data_set = odil.DataSet()
        data_set.add("PatientName", ["Doe^John"])
        del data_set[odil.registry.PatientName]
        self.assertTrue(data_set.empty())

        data_set = odil.DataSet()
        data_set.add("PatientName", ["Doe^John"])
        del data_set["PatientName"]
        self.assertTrue(data_set.empty())
Exemplo n.º 13
0
    def test_data_sets(self):
        data_set_1 = odil.DataSet()
        data_set_1.add("PatientID", ["DJ1234"])
    
        data_set_2 = odil.DataSet()
        data_set_2.add("EchoTime", [100])

        self._test(
            odil.Value.DataSets(), 
            [data_set_1, data_set_2], [data_set_2, data_set_1],
            odil.Value.Type.DataSets, odil.Value.as_data_sets)
Exemplo n.º 14
0
    def test_data_set(self):
        data_set_1 = odil.DataSet()
        data_set_1.add("PatientID", ["DJ1234"])

        data_set_2 = odil.DataSet()
        data_set_2.add("EchoTime", [100])

        self._test_element(odil.registry.ReferencedStudySequence,
                           odil.Value.DataSets(), [data_set_1, data_set_2],
                           odil.VR.SQ, odil.DataSet.is_data_set,
                           odil.DataSet.as_data_set)
Exemplo n.º 15
0
 def test_get_in_stack_position_index_none(self):
     data_set = odil.DataSet()
     dimension_index_seq = odil.DataSet()
     data_set.add("DimensionIndexSequence", [dimension_index_seq])
     idx = dicomifier.dicom_to_nifti.odil_getter.get_in_stack_position_index(
         data_set)
     self.assertEqual(idx, None)
     data_set_empty = odil.DataSet()
     idx = dicomifier.dicom_to_nifti.odil_getter.get_in_stack_position_index(
         data_set_empty)
     self.assertEqual(idx, None)
Exemplo n.º 16
0
    def test_orientation_getter_differents(self):
        d1 = odil.DataSet()
        d1.add("ImageOrientationPatient", [1., 0., 0., 0., 1., 0.])
        d2 = odil.DataSet()
        d2.add("ImageOrientationPatient", [-1., 0.5, 0.2, 0., 1., -0.5])

        orientationGetter = dicomifier.dicom_to_nifti.odil_getter.OrientationGetter(
        )
        orientationGetter(d1, "ImageOrientationPatient")
        orientationGetter(d2, "ImageOrientationPatient")
        orientations = orientationGetter._orientations
        self.assertEqual(2, len(orientations))
Exemplo n.º 17
0
    def initialize(self, message):
        data_set_1 = odil.DataSet()
        data_set_1.add("PatientName", ["Hello^World"])
        data_set_1.add("PatientID", ["1234"])
        self._responses.append(data_set_1)

        data_set_2 = odil.DataSet()
        data_set_2.add("PatientName", ["Doe^John"])
        data_set_2.add("PatientID", ["5678"])
        self._responses.append(data_set_2)

        self._response_index = 0
Exemplo n.º 18
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)
Exemplo n.º 19
0
 def test_get_position(self):
     data_set = odil.DataSet()
     first_frame = odil.DataSet()
     planePositionSeq = odil.DataSet()
     position = [0.0, 0.0, 1.0]
     planePositionSeq.add("ImagePositionPatient", position)
     first_frame.add("PlanePositionSequence", [planePositionSeq])
     per_frame = [first_frame]
     data_set.add("PerFrameFunctionalGroupsSequence", per_frame)
     data_set.add("NumberOfFrames", [1])
     val = list(
         dicomifier.dicom_to_nifti.odil_getter._get_position(data_set, 0))
     self.assertEqual([0.0, 0.0, 1.0], val)
Exemplo n.º 20
0
 def test_get_spacing_with_index(self):
     data_set = odil.DataSet()
     first_frame = odil.DataSet()
     pixelMeasuresSeq = odil.DataSet()
     spacing = [0.2, 0.2]
     pixelMeasuresSeq.add("PixelSpacing", spacing)
     first_frame.add("PixelMeasuresSequence", [pixelMeasuresSeq])
     per_frame = [first_frame]
     data_set.add("PerFrameFunctionalGroupsSequence", per_frame)
     data_set.add("NumberOfFrames", [1])
     val = list(
         dicomifier.dicom_to_nifti.odil_getter._get_spacing(data_set, 0))
     self.assertEqual([0.2, 0.2], val)
Exemplo n.º 21
0
 def test_check_frame_idx_out_of_bounds(self):
     data_set = odil.DataSet()
     first_frame = odil.DataSet()
     per_frame = [first_frame]
     data_set.add("PerFrameFunctionalGroupsSequence", per_frame)
     data_set.add("NumberOfFrames", [1])
     frame_idx = 1
     numberOfFrames = data_set.as_int("NumberOfFrames")[0]
     with self.assertRaises(Exception) as context:
         val = list(
             dicomifier.dicom_to_nifti.odil_getter.check_frame_index(
                 data_set, 1))
     self.assertTrue("Frame index out of bound ({}/{})".format(
         frame_idx, numberOfFrames) in context.exception)
Exemplo n.º 22
0
    def test_orientation_getter_equal(self):
        d1 = odil.DataSet()
        d1.add("ImageOrientationPatient", [1., 0., 0., 0., 1., 0.])
        d2 = odil.DataSet()
        d2.add("ImageOrientationPatient", [1., 0., 0., 0., 1., 0.])

        orientationGetter = dicomifier.dicom_to_nifti.odil_getter.OrientationGetter(
        )
        orientationGetter(d1, "ImageOrientationPatient")
        orientationGetter(d2, "ImageOrientationPatient")
        orientations = orientationGetter._orientations
        self.assertEqual(1, len(orientations))
        self.assertEqual(list(orientations.values()[0]),
                         [1., 0., 0., 0., 1., 0.])
Exemplo n.º 23
0
    def _test_implicit_container(self, tag, empty_content, vr, type_check,
                                 accessor):

        # Implicit empty content
        data_set = odil.DataSet()
        data_set.add(tag)
        self._test_element_value(data_set, tag, empty_content, vr, type_check,
                                 accessor)

        # Explicit empty content
        data_set = odil.DataSet()
        data_set.add(tag, empty_content)
        self._test_element_value(data_set, tag, empty_content, vr, type_check,
                                 accessor)
Exemplo n.º 24
0
 def test_get_geometry_single_normal(self): #normal test single_frame
     data_set = odil.DataSet()
     data_set.add("ImageOrientationPatient", [1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
     data_set.add("ImagePositionPatient", [-20., -14., -4.5])
     data_set.add("PixelSpacing", [0.2, 0.2])
     val = dicomifier.dicom_to_nifti.image.get_geometry([(data_set, None)])
     data_set_2 = odil.DataSet()
     data_set_2.add("ImageOrientationPatient", [1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
     data_set_2.add("ImagePositionPatient", [-20., -14., -4.])
     data_set_2.add("PixelSpacing", [0.2, 0.2])
     val = dicomifier.dicom_to_nifti.image.get_geometry([(data_set, None), (data_set_2, None)])
     self.assertEqual(list(val[0]), [-20., -14., -4.5])
     self.assertEqual(val[1], [0.2, 0.2, 0.5])
     direction = numpy.identity(3)
     numpy.testing.assert_array_equal(val[2], direction)
Exemplo n.º 25
0
 def test_get_geometry_no_orientation (self):
     data_set = odil.DataSet()
     shared = odil.DataSet()
     per_frame = []
     first_frame = odil.DataSet()
     plane_position_seq = odil.DataSet()
     plane_position_seq.add("ImagePositionPatient", [-20., -14., -4.5])
     first_frame.add("PlanePositionSequence", [plane_position_seq])
     per_frame.append(first_frame)
     data_set.add("SharedFunctionalGroupsSequence", [shared])
     data_set.add("PerFrameFunctionalGroupsSequence", per_frame)
     val = dicomifier.dicom_to_nifti.image.get_geometry([(data_set, 0)])
     self.assertEqual(list(val[0]), [-20., -14., -4.5])
     self.assertEqual(val[1], self.default_spacing)
     numpy.testing.assert_array_equal(val[2], self.default_direction)
Exemplo n.º 26
0
 def test_sort_position_no_position(self):
     ds = odil.DataSet()
     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])
     ds.add("SharedFunctionalGroupsSequence", [shared])
     per_frame = [odil.DataSet(), odil.DataSet()]
     ds.add("PerFrameFunctionalGroupsSequence", per_frame)
     ds.add("NumberOfFrames", [len(per_frame)])
     data_sets_frame_index = [(ds, 0), (ds, 1)]
     sort_return = sort_position(data_sets_frame_index,
                                 [1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
     self.assertFalse(sort_return)
Exemplo n.º 27
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)
Exemplo n.º 28
0
 def test_values(self):
     data_set = odil.DataSet()
     data_set.add("PatientName", ["Doe^John"])
     data_set.add("PatientID", ["DJ123"])
     self.assertEqual([[item for item in element.as_string()]
                       for element in data_set.values()],
                      [[b"Doe^John"], [b"DJ123"]])
Exemplo n.º 29
0
 def test_contains(self):
     data_set = odil.DataSet()
     data_set.add("PatientName", ["Doe^John"])
     self.assertTrue("PatientName" in data_set)
     self.assertTrue(odil.registry.PatientName in data_set)
     self.assertTrue("PatientID" not in data_set)
     self.assertTrue(odil.registry.PatientID not in data_set)
Exemplo n.º 30
0
def find(host, port, calling_ae_title, called_ae_title, level, keys,
         decode_uids):
    query = odil.DataSet()
    for key in keys:
        if "=" in key:
            key, value = key.split("=", 1)
            value = value.split("\\")
        else:
            value = None

        tag = getattr(odil.registry, key)

        if value is not None:
            vr = odil.registry.public_dictionary[tag].vr
            if vr in ["DS", "FL", "FD"]:
                value = [float(x) for x in value]
            elif vr in ["IS", "SL", "SS", "UL", "US"]:
                value = [int(x) for x in value]

            query.add(tag, value)
        else:
            query.add(tag)

    sop_class = getattr(
        odil.registry,
        "{}RootQueryRetrieveInformationModelFind".format(level.capitalize()))

    find_pc = odil.AssociationParameters.PresentationContext(
        1, sop_class, [
            odil.registry.ImplicitVRLittleEndian,
            odil.registry.ExplicitVRLittleEndian
        ], odil.AssociationParameters.PresentationContext.Role.SCU)

    association = odil.Association()
    association.set_peer_host(host)
    association.set_peer_port(port)
    association.update_parameters()\
        .set_calling_ae_title(calling_ae_title)\
        .set_called_ae_title(called_ae_title) \
        .set_presentation_contexts([find_pc])
    association.associate()
    logging.info("Association established")

    find = odil.FindSCU(association)
    find.set_affected_sop_class(sop_class)
    data_sets = find.find(query)
    print("{} answer{}".format(len(data_sets),
                               "s" if len(data_sets) > 1 else ""))

    max_length = 0
    for data_set in data_sets:
        max_length = max(max_length, find_max_name_length(data_set))

    for data_set in data_sets:
        print_data_set(data_set, decode_uids, "", max_length,
                       odil.Value.Strings())
        print()

    association.release()
    logging.info("Association released")