def print_data_set( data_set, decode_uids, padding, max_length, specific_character_set): for tag, element in data_set.items(): name = "{:04x},{:04x}".format(tag.group, tag.element) if tag in odil.registry.public_dictionary: entry = odil.registry.public_dictionary[tag] name = entry.name if tag == odil.registry.SpecificCharacterSet: specific_character_set = element.as_string() if element.is_data_set(): value = "(sequence, {} item{})".format( len(element), "s" if len(element)>1 else "") elif element.is_binary(): lengths = [len(x) for x in element.as_binary()] value = "(binary, {} item{}, {} byte{})".format( len(element), "s" if len(element)>1 else "", "+".join(str(x) for x in lengths), "s" if sum(lengths)>1 else "") else: getter = None if element.empty(): getter = lambda: [] elif element.is_int(): getter = element.as_int elif element.is_real(): getter = element.as_real elif element.is_string(): getter = lambda: [ odil.as_unicode(x, specific_character_set) for x in element.as_string()] value = [x for x in getter()] if decode_uids and element.vr == odil.VR.UI: value = [ odil.registry.uids_dictionary[uid].name if uid in odil.registry.uids_dictionary else uid for uid in value ] print("{}{}{} {:04x},{:04x} {} {}".format( padding, name, (max_length-len(name)-len(padding))*" ", tag.group, tag.element, element.vr, value)) if element.is_data_set(): sequence = element.as_data_set() if sequence: for item in sequence[:-1]: print_data_set( item, decode_uids, padding+" ", max_length, specific_character_set) print() print_data_set( sequence[-1], decode_uids, padding+" ", max_length, specific_character_set)
def print_data_set(data_set, decode_uids, padding, max_length, specific_character_set): for tag, element in data_set.items(): name = "{:04x},{:04x}".format(tag.group, tag.element) if tag in odil.registry.public_dictionary: entry = odil.registry.public_dictionary[tag] name = entry.name if tag == odil.registry.SpecificCharacterSet: specific_character_set = element.as_string() if element.is_data_set(): value = "(sequence, {} item{})".format( len(element), "s" if len(element) > 1 else "") elif element.is_binary(): lengths = [len(x) for x in element.as_binary()] value = "(binary, {} item{}, {} byte{})".format( len(element), "s" if len(element) > 1 else "", "+".join(str(x) for x in lengths), "s" if sum(lengths) > 1 else "") else: getter = None if element.empty(): getter = lambda: [] elif element.is_int(): getter = element.as_int elif element.is_real(): getter = element.as_real elif element.is_string(): getter = lambda: [ odil.as_unicode(x, specific_character_set) for x in element.as_string() ] value = [x for x in getter()] if decode_uids and element.vr == odil.VR.UI: value = [ odil.registry.uids_dictionary[uid].name if uid in odil.registry.uids_dictionary else uid for uid in value ] print("{}{}{} {:04x},{:04x} {} {}".format( padding, name, (max_length - len(name) - len(padding)) * " ", tag.group, tag.element, element.vr, value)) if element.is_data_set(): sequence = element.as_data_set() if sequence: for item in sequence[:-1]: print_data_set(item, decode_uids, padding + " ", max_length, specific_character_set) print() print_data_set(sequence[-1], decode_uids, padding + " ", max_length, specific_character_set)
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.vr == odil.VR.PN: data_set = odil.DataSet() if specific_character_set: data_set.add("SpecificCharacterSet", specific_character_set) data_set.add(odil.registry.PersonName, element.as_string(), element.vr) json_data_set = json.loads(odil.as_json(data_set)) result = json_data_set[str(odil.registry.PersonName)]["Value"] elif element.is_string(): result = list( odil.as_unicode(x, specific_character_set) for x in 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()).decode() for x in element.as_binary() ] else: raise Exception("Unknown element type") return result
def store(self, data_set): specific_character_set = odil.Value.Strings() if "SpecificCharacterSet" in data_set: specific_character_set = data_set.as_string( "SpecificCharacterSet") as_unicode = lambda x: odil.as_unicode(x, specific_character_set) if layout == "flat": directory = "" elif layout == "tree": # Patient directory: <PatientName> or <PatientID>. patient_directory = None if "PatientName" in data_set and data_set.as_string( "PatientName"): patient_directory = data_set.as_string("PatientName")[0] else: patient_directory = data_set.as_string("PatientID")[0] patient_directory = as_unicode(patient_directory) # Study directory: <StudyID>_<StudyDescription>, both parts are # optional. If both tags are missing or empty, default to a # numeric index based on StudyInstanceUID. study_directory = [] if "StudyID" in data_set and data_set.as_string("StudyID"): study_directory.append(data_set.as_string("StudyID")[0]) if ("StudyDescription" in data_set and data_set.as_string("StudyDescription")): study_directory.append( data_set.as_string("StudyDescription")[0]) if not study_directory: study_instance_uid = data_set.as_string( "StudyInstanceUID")[0] study_directory.append( self._study_ids.setdefault(study_instance_uid, 1 + len(self._study_ids))) study_directory = "_".join( as_unicode(x) for x in study_directory) # Study directory: <SeriesNumber>_<SeriesDescription>, both # parts are optional. If both tags are missing or empty, default # to a numeric index based on SeriesInstanceUID. series_directory = [] if "SeriesNumber" in data_set and data_set.as_int( "SeriesNumber"): series_directory.append( str(data_set.as_int("SeriesNumber")[0])) if ("SeriesDescription" in data_set and data_set.as_string("SeriesDescription")): series_directory.append( data_set.as_string("SeriesDescription")[0]) if not series_directory: series_instance_uid = data_set.as_string( "series_instance_uid")[0] series_directory.append( self._series_ids.setdefault(series_instance_uid, 1 + len(self._series_ids))) series_directory = "_".join( as_unicode(x) for x in series_directory) if iso_9660: patient_directory = to_iso_9660(patient_directory) study_directory = to_iso_9660(study_directory) series_directory = to_iso_9660(series_directory) directory = os.path.join(patient_directory, study_directory, series_directory) if not os.path.isdir(os.path.join(self.directory, directory)): os.makedirs(os.path.join(self.directory, directory)) else: raise NotImplementedError() self.stored.setdefault(directory, 0) if iso_9660: filename = "IM{:06d}".format(1 + self.stored[directory]) else: filename = as_unicode(data_set.as_string("SOPInstanceUID")[0]) with odil.open(os.path.join(self.directory, directory, filename), "wb") as fd: odil.Writer.write_file(data_set, fd) self.stored[directory] += 1 self.files.append(os.path.join(directory, filename))
def decode(value): return odil.as_unicode( value, data_set.as_string("SpecificCharacterSet") if "SpecificCharacterSet" in data_set else odil.Value.Strings())
def store(self, data_set): specific_character_set = odil.Value.Strings() if "SpecificCharacterSet" in data_set: specific_character_set = data_set.as_string( "SpecificCharacterSet") as_unicode = lambda x: odil.as_unicode(x, specific_character_set) if layout == "flat": directory = "" elif layout == "tree": # Patient directory: <PatientName> or <PatientID>. patient_directory = None if "PatientName" in data_set and data_set.as_string("PatientName"): patient_directory = data_set.as_string("PatientName")[0] else: patient_directory = data_set.as_string("PatientID")[0] patient_directory = as_unicode(patient_directory) # Study directory: <StudyID>_<StudyDescription>, both parts are # optional. If both tags are missing or empty, default to a # numeric index based on StudyInstanceUID. study_directory = [] if "StudyID" in data_set and data_set.as_string("StudyID"): study_directory.append(data_set.as_string("StudyID")[0]) if ("StudyDescription" in data_set and data_set.as_string("StudyDescription")): study_directory.append( data_set.as_string("StudyDescription")[0]) if not study_directory: study_instance_uid = data_set.as_string("StudyInstanceUID")[0] study_directory.append( self._study_ids.setdefault( study_instance_uid, 1+len(self._study_ids))) study_directory = "_".join(as_unicode(x) for x in study_directory) # Study directory: <SeriesNumber>_<SeriesDescription>, both # parts are optional. If both tags are missing or empty, default # to a numeric index based on SeriesInstanceUID. series_directory = [] if "SeriesNumber" in data_set and data_set.as_int("SeriesNumber"): series_directory.append(str(data_set.as_int("SeriesNumber")[0])) if ("SeriesDescription" in data_set and data_set.as_string("SeriesDescription")): series_directory.append( data_set.as_string("SeriesDescription")[0]) if not series_directory: series_instance_uid = data_set.as_string("series_instance_uid")[0] series_directory.append( self._series_ids.setdefault( series_instance_uid, 1+len(self._series_ids))) series_directory = "_".join(as_unicode(x) for x in series_directory) if iso_9660: patient_directory = to_iso_9660(patient_directory) study_directory = to_iso_9660(study_directory) series_directory = to_iso_9660(series_directory) directory = os.path.join( patient_directory, study_directory, series_directory) if not os.path.isdir(os.path.join(self.directory, directory)): os.makedirs(os.path.join(self.directory, directory)) else: raise NotImplementedError() self.stored.setdefault(directory, 0) if iso_9660: filename = "IM{:06d}".format(1+self.stored[directory]) else: filename = as_unicode(data_set.as_string("SOPInstanceUID")[0]) with odil.open(os.path.join(self.directory, directory, filename), "wb") as fd: odil.Writer.write_file(data_set, fd) self.stored[directory] += 1 self.files.append(os.path.join(directory, filename))
def get_series_directory(data_set, iso_9660): """ Return the directory associated with the patient, study and series of the DICOM data set. """ # Patient directory: <PatientName> or <PatientID>. patient_directory = None if "PatientName" in data_set and data_set.as_string("PatientName"): patient_directory = odil.as_unicode( data_set.as_string("PatientName")[0], data_set.as_string("SpecificCharacterSet") if "SpecificCharacterSet" in data_set else odil.Value.Strings()) else: patient_directory = odil.as_unicode( data_set.as_string("PatientID")[0], data_set.as_string("SpecificCharacterSet") if "SpecificCharacterSet" in data_set else odil.Value.Strings()) # Study directory: <StudyID>_<StudyDescription>, both parts are # optional. If both tags are missing or empty, raise an exception study_directory = [] if "StudyID" in data_set and data_set.as_string("StudyID"): study_directory.append( odil.as_unicode( data_set.as_string("StudyID")[0], data_set.as_string("SpecificCharacterSet") if "SpecificCharacterSet" in data_set else odil.Value.Strings())) if "StudyDescription" in data_set and data_set.as_string("StudyDescription"): study_directory.append( odil.as_unicode( data_set.as_string("StudyDescription")[0], data_set.as_string("SpecificCharacterSet") if "SpecificCharacterSet" in data_set else odil.Value.Strings())) if not study_directory: raise Exception("Study ID and Study Description are both missing") study_directory = "_".join(study_directory) # Study directory: <SeriesNumber>_<SeriesDescription>, both # parts are optional. If both tags are missing or empty, raise an exception series_directory = [] if "SeriesNumber" in data_set and data_set.as_int("SeriesNumber"): series_number = data_set.as_int("SeriesNumber")[0] if series_number > 2**16: # Bruker ID based on experiment number and reconstruction number is # not readable: separate the two values series_directory.append(str(divmod(series_number, 2**16)[0])) else: series_directory.append(str(series_number)) if not iso_9660: if "SeriesDescription" in data_set and data_set.as_string("SeriesDescription"): series_directory.append( odil.as_unicode( data_set.as_string("SeriesDescription")[0], data_set.as_string("SpecificCharacterSet") if "SpecificCharacterSet" in data_set else odil.Value.Strings())) if not series_directory: raise Exception("Series Number and Series Description are both missing") series_directory = "_".join(series_directory) if iso_9660: patient_directory = to_iso_9660(patient_directory) study_directory = to_iso_9660(study_directory) series_directory = to_iso_9660(series_directory) return os.path.join(patient_directory, study_directory, series_directory)