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)
def test_convert_element_required(self): bruker_data_set = {} dicom_data_set = odil.DataSet() generator = dicomifier.bruker_to_dicom.FrameIndexGenerator( bruker_data_set) frame_index = [0] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object( tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) with self.assertRaises(Exception) as context: val = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, "VisuSubjectName", "PatientName", 1, None, None, frame_index, generator, vr_finder_function) self.assertTrue("PatientName must be present" in context.exception)
def test_convert_element_getter(self): bruker_data_set = {} dicom_data_set = odil.DataSet() generator = dicomifier.bruker_to_dicom.FrameIndexGenerator( bruker_data_set) frame_index = [0] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object( tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) val = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, None, "PixelPresentation", 1, lambda d, g, i: ["MONOCHROME"], None, frame_index, generator, vr_finder_function) self.assertEqual(val, ["MONOCHROME"]) dicom_val = list(dicom_data_set.as_string("PixelPresentation")) self.assertEqual(["MONOCHROME"], dicom_val)
def test_convert_element_getter_none(self): bruker_data_set = {"VisuSubjectName": ["Mouse^Mickey"]} dicom_data_set = odil.DataSet() generator = dicomifier.bruker_to_dicom.FrameIndexGenerator( bruker_data_set) frame_index = [0] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object( tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) val = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, "VisuSubjectName", "PatientName", 1, None, None, frame_index, generator, vr_finder_function) # Check first the returned value of the convert_element function self.assertEqual(val, ["Mouse^Mickey"]) # Check then the content of the dicom_data_set (should contain the correct value...) dicom_val = list(dicom_data_set.as_string("PatientName")) self.assertEqual(["Mouse^Mickey"], dicom_val)
def test_convert_element_setter_dict(self): bruker_data_set = {"VisuSubjectSex": ["MALE"]} dicom_data_set = odil.DataSet() generator = dicomifier.bruker_to_dicom.FrameIndexGenerator( bruker_data_set) frame_index = [0] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object( tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) val = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, "VisuSubjectSex", "PatientSex", 1, None, { "MALE": "M", "FEMALE": "F", "UNDEFINED": "O", "UNKNOWN": "O", None: None }, frame_index, generator, vr_finder_function) self.assertEqual(val, ["M"]) dicom_val = list(dicom_data_set.as_string("PatientSex")) self.assertEqual(["M"], dicom_val)
def test_convert_element_getter_frame_index(self): bruker_data_set = { # Only two group, with each one a different Echo Time "VisuFGOrderDesc": [[2, "FG_SLICE", "", 0, 1]], "VisuGroupDepVals": [["VisuAcqEchoTime", 0]], "VisuAcqEchoTime": [10., 20.] } dicom_data_set = odil.DataSet() generator = dicomifier.bruker_to_dicom.FrameIndexGenerator( bruker_data_set) frame_index = [1] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object( tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) val = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, "VisuAcqEchoTime", "EchoTime", 1, None, None, frame_index, generator, vr_finder_function) self.assertEqual(val, [20.]) dicom_val = list(dicom_data_set.as_real("EchoTime")) self.assertEqual([20.], dicom_val)
def test_convert_element_setter_function(self): bruker_data_set = { # Here we make a simple example with only one frame => only one position "VisuCorePosition": [-20., -20., -2.] } dicom_data_set = odil.DataSet() generator = dicomifier.bruker_to_dicom.FrameIndexGenerator( bruker_data_set) frame_index = [0] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object( tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) val = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, "VisuCorePosition", "ImagePositionPatient", 1, lambda d, g, i: numpy.reshape(d["VisuCorePosition"], (-1, 3)), lambda x: x[0].tolist(), frame_index, generator, vr_finder_function) self.assertEqual(val, [-20., -20., -2.]) dicom_val = list(dicom_data_set.as_real("ImagePositionPatient")) self.assertEqual([-20., -20., -2.], dicom_val)
def enhanced_mr_image_storage(bruker_data_set, transfer_syntax): """ Convert bruker_data_set into dicom_data_set by using the correct transfer_syntax This function will create one data_set per reconstruction (multiFrame format) :param bruker_data_set: Json dataSet containing bruker information :param transfer_syntax: Wanted transfer syntax for the conversion """ if int(bruker_data_set.get("VisuCoreDim", [0])[0]) == 3: to_2d(bruker_data_set) vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object(tag, helper, transfer_syntax) helper = odil.DataSet() generator = FrameIndexGenerator(bruker_data_set) dicom_data_set = odil.DataSet() number_of_frames = generator._get_frames_count() dicom_data_set.add("SpecificCharacterSet", ["ISO_IR 192"]) shared = [odil.DataSet()] dicom_data_set.add(odil.registry.SharedFunctionalGroupsSequence, shared) per_frame = [odil.DataSet() for x in range(number_of_frames) ] # Modules factory modules = [ patient.Patient, study.GeneralStudy, study.PatientStudy, series.GeneralSeries + [(None, "Modality", 1, lambda d,g,i: ["MR"], None)] , frame_of_reference.FrameOfReference, equipment.GeneralEquipment, equipment.EnhancedGeneralEquipment, image.MutliFrameFunctionalGroups, image.MultiFrameDimension, image.AcquisitionContext, image.EnhancedMRImage, image.MRPulseSequence, image.SOPCommon + [(None, "SOPClassUID", 1, lambda d,g,i: [odil.registry.EnhancedMRImageStorage], None)], image.ImagePixel, ] framegroups = [ fg.PixelMeasures, fg.FrameContent, fg.PlanePosition, fg.PlaneOrientation, fg.FrameAnatomy, fg.PixelValueTransformation, fg.MRImageFrameType, fg.MRTimingAndRelatedParameters, fg.MREcho, fg.MRModifier, fg.MRImagingModifier, fg.MRFOVGeometry, fg.MRAverages ] if "FG_DIFFUSION" in [x[1] for x in generator.frame_groups]: framegroups.append(fg.MRDiffusion) # parse here classical modules for i, frame_index in enumerate(generator): for bruker_name, dicom_name, type_, getter, setter in itertools.chain(*modules): value = convert_element( bruker_data_set, dicom_data_set, bruker_name, dicom_name, type_, getter, setter, frame_index, generator, vr_finder_function ) if dicom_name in ["BitsAllocated", "PixelRepresentation"]: helper.add(getattr(odil.registry, dicom_name), value) # parse here frame groups for frame_g in framegroups : fg_modules = frame_g.values() d = odil.DataSet() for bruker_name, dicom_name, type_, getter, setter in itertools.chain(*fg_modules): value = convert_element( bruker_data_set, d, bruker_name, dicom_name, type_, getter, setter, frame_index, generator, vr_finder_function ) per_frame[i].add(next(iter(frame_g.keys()))[0], [d]) dicom_data_set.add(odil.registry.PerFrameFunctionalGroupsSequence, per_frame) regroup_shared_data(dicom_data_set, framegroups) pixel_data_list = [] for i, frame_index in enumerate(generator): pixel_data_list.append( image._get_pixel_data(bruker_data_set, generator, frame_index)[0] ) dicom_data_set.add( odil.registry.PixelData, [b"".join(pixel_data_list)], vr_finder_function("PixelData")) # Add the raw Bruker meta-data, convert paths to Unicode if needed paths = [ x.decode() if hasattr(x, "decode") else x for x in bruker_data_set["reco_files"] ] bruker_files = { os.path.basename(x): open(x).read() for x in paths } dicom_data_set.add("EncapsulatedDocument", [json.dumps(bruker_files)]) dicom_data_set.add("MIMETypeOfEncapsulatedDocument", ["application/json"]) return [dicom_data_set]
def mr_image_storage(bruker_data_set, transfer_syntax): """ Function to convert specific burker images into dicom :param bruker_data_set: bruker data set to convert :param transfer_syntax: target transfer syntax """ if int(bruker_data_set.get("VisuCoreDim", [0])[0]) == 3: to_2d(bruker_data_set) dicom_data_sets = [] modules = [ patient.Patient, study.GeneralStudy, study.PatientStudy, series.GeneralSeries + [(None, "Modality", 1, lambda d, g, i: ["MR"], None)], frame_of_reference.FrameOfReference, equipment.GeneralEquipment, image.GeneralImage, image.ImagePlane, image.ImagePixel, image.MRImage, [(None, "PixelValueTransformationSequence", 1, lambda bruker_data_set, generator, frame_index: [ convert_elements(bruker_data_set, odil.DataSet( ), image.PixelValueTransformation, frame_index, generator, vr_finder_function) ], None)], [(None, "MRDiffusionSequence", 3, lambda bruker_data_set, generator, frame_index: [ convert_elements(bruker_data_set, odil.DataSet( ), image.MRDiffusion, frame_index, generator, vr_finder_function) ] if "FG_DIFFUSION" in [x[1] for x in generator.frame_groups] else None, None)], image.SOPCommon + [(None, "SOPClassUID", 1, lambda d, g, i: [odil.registry.MRImageStorage], None)] ] vr_finder_object = odil.VRFinder() vr_finder_function = lambda tag: vr_finder_object(tag, helper, transfer_syntax) helper = odil.DataSet() generator = FrameIndexGenerator(bruker_data_set) for frame_index in generator: dicom_data_set = odil.DataSet() dicom_data_set.add("SpecificCharacterSet", ["ISO_IR 192"]) for bruker_name, dicom_name, type_, getter, setter in itertools.chain( *modules): value = convert_element(bruker_data_set, dicom_data_set, bruker_name, dicom_name, type_, getter, setter, frame_index, generator, vr_finder_function) for name in ["BitsAllocated", "PixelRepresentation"]: if dicom_name == name: helper.add(getattr(odil.registry, name), value) # FIXME: storing the Bruker meta-data in all instances is rather # inefficient. It can amount to over 50 % of the total size of the # DICOM file # dict_files = {} # path_list = bruker_data_set["reco_files"] # for path in path_list: # dict_files[os.path.basename(path)] = open(path).read() # reco_files_tag = odil.Tag("67890010") # dicom_data_set.add(reco_files_tag, [json.dumps(dict_files)], odil.VR.OB) dicom_data_sets.append(dicom_data_set) return dicom_data_sets