def copy_contours(self): ''' copy contours to rs :param self: :return: ''' ROIContourSequence = Sequence() #ContourSequence = Sequence() StructureSetROISequence = Sequence() for i in range( len( self.contours)): StructureSetROI = Dataset() StructureSetROI.ROINumber = self.contours[i]['number'] StructureSetROI.ROIName = self.contours[i]['name'] StructureSetROI.ROIGenerationAlgorithm = 'MANUAL' StructureSetROI.ReferencedFrameOfReferenceUID = '' StructureSetROISequence.append(StructureSetROI) ContourSequence = Sequence() for k in range( len( self.contours[i]['contour'])): contour_slice = Dataset() contour_slice.ContourData = MultiValue( dicom.valuerep.DSfloat, self.contours[i]['contour'][k]) contour_slice.ContourGeometricType = 'CLOSED_PLANAR' contour_slice.NumberOfContourPoints = len( contour_slice.ContourData) /3 ########wrong contour_slice.ContourImageSequence = Sequence() ContourSequence.append( contour_slice) ROIContour = Dataset() ROIContour.ContourSequence = ContourSequence ROIContour.ROIDisplayColor = self.rs_generic.structure.ROIContourSequence[i].ROIDisplayColor ROIContour.ReferencedROINumber = self.rs_generic.structure.ROIContourSequence[i].ReferencedROINumber ROIContourSequence.append( ROIContour) self.rs.structure.ROIContourSequence = ROIContourSequence self.rs.structure.StructureSetROISequence = StructureSetROISequence return 0
def build_functional_groups(dcm, cfg): """ all values are hard coded to ensure they are present in the final file """ ds1 = Dataset() ds2 = Dataset() pv = cfg.get('OnTheFly').get('PixelSpacing') ds1.PixelSpacing = [float(x) for x in pv] ds1.SliceThickness = 1 ds2.PixelMeasuresSequence = Sequence([ds1]) ds3 = Dataset() ds3.OpticalPathIdentifier = '1' ds2.OpticalPathIdentificationSequence = Sequence([ds3]) ds4 = Dataset() ds4.FrameType = cfg['BaseAttributes']['ImageType'] ds2.WholeSlideMicroscopyImageFrameTypeSequence = Sequence([ds4]) dcm.SharedFunctionalGroupsSequence = Sequence([ds2]) del ds1, ds2, ds3 return dcm
def setUp(self): # Create simple dataset for all tests ds = Dataset() ds.PatientName = "Name^Patient" # Set up a simple nested sequence # first, the innermost sequence subitem1 = Dataset() subitem1.ContourNumber = 1 subitem1.ContourData = ['2', '4', '8', '16'] subitem2 = Dataset() subitem2.ContourNumber = 2 subitem2.ContourData = ['32', '64', '128', '196'] sub_ds = Dataset() sub_ds.ContourSequence = Sequence((subitem1, subitem2)) # Now the top-level sequence ds.ROIContourSequence = Sequence((sub_ds, )) # Comma to make one-tuple # Store so each test can use it self.ds = ds
def generate_reference_segmentation_tags(dataset_segm, ReferencedSeriesInstanceUID_segm, ReferencedSOPInstanceUID_src, StudyInstanceUID_src, segment_label, lesion_number): """ Add Reference to the tumour/ablation and source img in the DICOM segmentation metatags. :param dataset_segm: dcm file read with pydicom library :param ReferencedSOPInstanceUID_segm: SeriesInstanceUID of the related segmentation file (tumour or ablation) :param ReferencedSOPInstanceUID_src: SeriesInstanceUID of the source image :param StudyInstanceUID_src: StudyInstanceUID of the source image :param segment_label: text describing whether is tumor or ablation :param: lesion_number: a int identifying which lesion was this :return: dicom single file/slice with new General Reference Sequence Tags """ if segment_label == "Lession": dataset_segm.SegmentLabel = "Tumor" elif segment_label == "AblationZone": dataset_segm.SegmentLabel = "Ablation" dataset_segm.StudyInstanceUID = StudyInstanceUID_src dataset_segm.SegmentationType = "BINARY" dataset_segm.SegmentAlgorithmType = "SEMIAUTOMATIC" dataset_segm.DerivationDescription = "CasOneIR" dataset_segm.ImageType = "DERIVED\PRIMARY" Segm_ds = Dataset() Segm_ds.ReferencedSOPInstanceUID = ReferencedSeriesInstanceUID_segm Segm_ds.ReferencedSOPClassUID = dataset_segm.SOPClassUID Segm_ds.ReferencedSegmentNumber = lesion_number Source_ds = Dataset() Source_ds.ReferencedSOPInstanceUID = ReferencedSOPInstanceUID_src dataset_segm.ReferencedImageSequence = Sequence([Segm_ds]) dataset_segm.SourceImageSequence = Sequence([Source_ds]) return dataset_segm
def testValidInitialization(self): """Sequence: Ensure valid creation of Sequences using Dataset inputs""" inputs = { 'PatientPosition': 'HFS', 'PatientSetupNumber': '1', 'SetupTechniqueDescription': '' } patientSetups = Dataset() patientSetups.update(inputs) # Construct the sequence seq = Sequence((patientSetups, )) assert isinstance(seq[0], Dataset)
def __write_roi_contour_sequence(ds, roi_list): ds.ROIContourSequence = Sequence() roi_nums = len(roi_list) for i in range(roi_nums): ROIContourSequenceItem = Dataset() ds.ROIContourSequence.append(ROIContourSequenceItem) ROIContourSequenceItem.ROIDisplayColor = roi_list[i][ 3] # roi_display_color ROIContourSequenceItem.ContourSequence = Sequence() contour_list = roi_list[i][5] contour_nums = len(contour_list) for j in range(contour_nums): contour = contour_list[j] ContourSequenceItem = Dataset() ROIContourSequenceItem.ContourSequence.append(ContourSequenceItem) ContourSequenceItem.ContourImageSequence = Sequence() ContourImageSequenceItem = Dataset() ContourSequenceItem.ContourImageSequence.append( ContourImageSequenceItem) ContourImageSequenceItem.ReferencedSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' ContourImageSequenceItem.ReferencedSOPInstanceUID = contour[0] ContourSequenceItem.ContourGeometricType = 'CLOSED_PLANAR' #point_nums = len(contour_item[2][0]) point_nums = len(contour[1]) ContourSequenceItem.NumberOfContourPoints = point_nums ContourSequenceItem.ContourNumber = j + 1 result_point_list = contour[1] point_list_string = '' for k in range(point_nums): point_list_string += '%f\\%f\\%f' % ( result_point_list[k][0, 0], result_point_list[k][0, 1], result_point_list[k][0, 2]) if k != point_nums - 1: point_list_string += '\\' #ContourSequenceItem.ContourData = '29.420486\\13.750359\\-265.5\\29.271103\\15.171627\\-265.5\\29.085907\\15.862774\\-265.5\\28.114929\\17.768417\\-265.5\\27.664627\\18.324493\\-265.5\\26.602615\\19.280743\\-265.5\\26.002518\\19.670452\\-265.5\\24.005814\\20.436909\\-265.5\\23.299103\\20.548843\\-265.5\\21.86998\\20.548843\\-265.5\\21.163269\\20.436909\\-265.5\\19.16658\\19.670452\\-265.5\\18.566467\\19.280746\\-265.5\\17.054153\\17.768417\\-265.5\\16.664444\\17.168327\\-265.5\\15.897995\\15.171627\\-265.5\\15.786057\\14.464905\\-265.5\\15.786057\\13.035805\\-265.5\\15.897995\\12.329084\\-265.5\\16.664444\\10.332386\\-265.5\\17.054153\\9.7322922\\-265.5\\18.010406\\8.6702652\\-265.5\\18.566467\\8.219965\\-265.5\\19.16658\\7.8302593\\-265.5\\19.804123\\7.5054169\\-265.5\\21.163269\\7.0638008\\-265.5\\21.86998\\6.9518661\\-265.5\\23.299103\\6.9518661\\-265.5\\24.005814\\7.0638008\\-265.5\\26.002518\\7.8302593\\-265.5\\26.602615\\8.2199688\\-265.5\\28.114929\\9.7322941\\-265.5\\28.504639\\10.332388\\-265.5\\28.829483\\10.969931\\-265.5\\29.085907\\11.637936\\-265.5\\29.383026\\13.035809\\-265.5' ContourSequenceItem.ContourData = point_list_string ROIContourSequenceItem.ReferencedROINumber = roi_list[i][ 1] # roi_number
def add_rt_roi_observations_sequence(ds): # RT ROI Observations Sequence rtroi_observations_sequence = Sequence() ds.RTROIObservationsSequence = rtroi_observations_sequence # RT ROI Observations Sequence: RT ROI Observations 1 rtroi_observations1 = Dataset() rtroi_observations1.ObservationNumber = "27" rtroi_observations1.ReferencedROINumber = "27" rtroi_observations1.RTROIInterpretedType = "ORGAN" rtroi_observations1.ROIInterpreter = "" rtroi_observations_sequence.append(rtroi_observations1) return ds
def derive_image_sequence(sop_class_uid, sop_instance_uid): source_image = Dataset() source_image.ReferencedSOPClassUID = sop_class_uid source_image.ReferencedSOPInstanceUID = sop_instance_uid purpose_of_reference = Dataset() purpose_of_reference.CodeValue = '113130' purpose_of_reference.CodingSchemeDesignator = 'DCM' purpose_of_reference.CodeMeaning = \ 'Predecessor containing group of imaging subjects' source_image.PurposeOfReferenceCodeSequence = \ Sequence([purpose_of_reference]) derivation_image = Dataset() derivation_image.SourceImageSequence = Sequence([source_image]) derivation_code = Dataset() derivation_code.CodeValue = '113131' derivation_code.CodingSchemeDesignator = 'DCM' derivation_code.CodeMeaning = \ 'Extraction of individual subject from group' derivation_image.DerivationCodeSequence = Sequence([derivation_code]) derivation_image_sequence = Sequence([derivation_image]) return derivation_image_sequence
def build_seq(df, index, parent_path, seq_attr): """ Builds and returns a pydicom sequence and : 0 for a basic sequence | 1 for an empty sequence that needs to be represented even if it is empty. """ seq = Sequence() for ds_attr in get_ds_attr(df, parent_path, seq_attr): ds = build_dicom(df, index, parent_path + seq_attr + ds_attr) if ds != None: seq.append(ds) else: return [], 1 return seq, 0
def add_structure_set_roi_sequence(ds): # Structure Set ROI Sequence structure_set_roi_sequence = Sequence() ds.StructureSetROISequence = structure_set_roi_sequence # Structure Set ROI Sequence: Structure Set ROI 1 structure_set_roi1 = Dataset() structure_set_roi1.ROINumber = "27" structure_set_roi1.ReferencedFrameOfReferenceUID = dcm.FrameOfReferenceUID structure_set_roi1.ROIName = "Vacbag" structure_set_roi1.ROIGenerationAlgorithm = "AUTOMATIC" structure_set_roi_sequence.append(structure_set_roi1) return ds
def get_idis_code_sequence(ruleset_names: List[str]) -> DataElement: """Create the element (0012,0064) - DeIdentificationMethodCodeSequence This sequence specifies what kind of anonymization has been performed. It is quite free form. This implementation uses the following format: DeIdentificationMethodCodeSequence will contain the code of each official DICOM deidentification profile that was used. Codes are taken from Table CID 7050 Parameters ---------- ruleset_names: List[str] list of names as defined in nema.E1_1_METHOD_INFO Returns ------- DataElement Sequence element (0012,0064) - DeIdentificationMethodCodeSequence. Will contain the code of each official DICOM deidentification profile passed Raises ------ ValueError When any name in ruleset_names is not recognized as a standard DICOM rule set """ code_per_name = {x.full_name: x for x in E1_1_METHOD_INFO} codes = [] for name in ruleset_names: try: # check whether we know this ruleset as a standard DICOM one ruleset_info = code_per_name[name] except KeyError: raise ValueError( f'Could not find the code for rule set "{name}". I do' f" not know this ruleset") # Create the required designation for this dataset code_dataset = Dataset() code_dataset.CodeValue = ruleset_info.code code_dataset.CodingSchemeDesignator = "DCM" code_dataset.CodeMeaning = ruleset_info.full_name codes.append(code_dataset) element = DataElement( tag=Tag("DeidentificationMethodCodeSequence"), VR=VRs.Sequence.short_name, value=Sequence(codes), ) return element
def create_contour_sequence(roi_data: ROIData, series_data): contour_sequence = Sequence() for i, series_slice in enumerate(series_data): mask_slice = roi_data.mask[:, :, i] # Do not add ROI's for blank slices if np.sum(mask_slice) == 0: print("Skipping empty mask layer") continue contour_coords = get_contours_coords(mask_slice, series_slice, roi_data.use_pin_hole) for contour_data in contour_coords: contour = create_contour(series_slice, contour_data) contour_sequence.append(contour) return contour_sequence
def generate_rtplan(field_list, save_path): # Generate new pydicom Dataset containing main DICOM RT PLan file info ds = generate_rtplan_skeleton() # Fraction Group Sequence & Fraction Group frxn_gp_sequence = Sequence() frxn_gp = Dataset() frxn_gp.FractionGroupNumber = "1" frxn_gp.NumberOfFractionsPlanned = "1" frxn_gp.NumberOfBeams = len(field_list) frxn_gp.NumberOfBrachyApplicationSetups = "0" # Beam Sequence & Referenced Beam Sequence beam_sequence = Sequence() refd_beam_sequence = Sequence() # Generate beams to add to Beam & Refd Beam Sequences for field in field_list: beam_data, refd_beam_data = generate_rtplan_beam(field) beam_sequence.append(beam_data) refd_beam_sequence.append(refd_beam_data) # Assign Sequences to Dataset frxn_gp.ReferencedBeamSequence = refd_beam_sequence frxn_gp_sequence.append(frxn_gp) ds.FractionGroupSequence = frxn_gp_sequence ds.BeamSequence = beam_sequence # ds.is_implicit_VR = True ds.is_little_endian = True ds.save_as(save_path, write_like_original=False)
def add_referenced_frame_of_reference_sequence(self): """Fill the frame of reference module.""" self.ds_rs.ReferencedFrameOfReferenceSequence.append(Dataset()) referenced_frame_of_reference_sequence = self.ds_rs.ReferencedFrameOfReferenceSequence[-1] referenced_frame_of_reference_sequence.FrameOfReferenceUID = self.ds_rs.FrameOfReferenceUID referenced_frame_of_reference_sequence.add_new('RTReferencedStudySequence', 'SQ', Sequence()) referenced_frame_of_reference_sequence.RTReferencedStudySequence.append(Dataset()) rt_referenced_study_sequence = referenced_frame_of_reference_sequence.RTReferencedStudySequence[-1] rt_referenced_study_sequence.ReferencedSOPClassUID = UID('1.2.840.10008.3.1.2.3.1') rt_referenced_study_sequence.ReferencedSOPInstanceUID = self.ds_ct_reference.SeriesInstanceUID rt_referenced_study_sequence.add_new('RTReferencedSeriesSequence', 'SQ', Sequence()) rt_referenced_study_sequence.RTReferencedSeriesSequence.append(Dataset()) rt_referenced_series_sequence = rt_referenced_study_sequence.RTReferencedSeriesSequence[-1] rt_referenced_series_sequence.SeriesInstanceUID = self.ds_ct_reference.SeriesInstanceUID rt_referenced_series_sequence.add_new('ContourImageSequence', 'SQ', Sequence()) for i, sop_instance_uid in enumerate(self.ds_ct_sop_instance_uid): rt_referenced_series_sequence.ContourImageSequence.append(Dataset()) contour_image_sequence = rt_referenced_series_sequence.ContourImageSequence[i] contour_image_sequence.ReferencedSOPClassUID = UID('1.2.840.10008.5.1.4.1.1.2') contour_image_sequence.ReferencedSOPInstanceUID = sop_instance_uid
def add_teeth(self, teeth): logging.debug("Adding teeth") if teeth == defaults.ADD_MAX_ALLOWED_TEETH: logging.debug("Setting all possibly allowed teeth.") teeth = ALLOWED_TEETH[self.image_type] if len(teeth) > 0: if not hasattr(self._ds, 'PrimaryAnatomicStructureSequence'): self._ds.PrimaryAnatomicStructureSequence = Sequence([]) for tooth in teeth: if ToothCodes.is_valid_tooth_number(tooth): self._ds.PrimaryAnatomicStructureSequence.append( _get_sct_code_dataset( *ToothCodes.SCT_TOOTH_CODES[tooth]))
def create_contour_sequence(roi_data: ROIData, series_data) -> Sequence: """ Iterate through each slice of the mask For each connected segment within a slice, create a contour """ contour_sequence = Sequence() contours_coords = get_contours_coords(roi_data, series_data) for series_slice, slice_contours in zip(series_data, contours_coords): for contour_data in slice_contours: contour = create_contour(series_slice, contour_data) contour_sequence.append(contour) return contour_sequence
def create_contour(series_slice: Dataset, contour_data: np.ndarray): contour_image = Dataset() contour_image.ReferencedSOPClassUID = series_slice.file_meta.MediaStorageSOPClassUID contour_image.ReferencedSOPInstanceUID = series_slice.file_meta.MediaStorageSOPInstanceUID # Contour Image Sequence contour_image_sequence = Sequence() contour_image_sequence.append(contour_image) contour = Dataset() contour.ContourImageSequence = contour_image_sequence contour.ContourGeometricType = 'CLOSED_PLANAR' # TODO figure out how to get this value contour.NumberOfContourPoints = len( contour_data) / 3 # Each point has an x, y, and z value contour.ContourData = contour_data return contour
def put_attribute_in_path(ds: Dataset, path: list, a: DataElementX): if not path: if a.tag not in ds: ds[a.tag] = a else: kw = path.pop(0) tg = Dictionary.tag_for_keyword(kw) vr = Dictionary.dictionary_VR(tg) if vr == 'SQ': if tg in ds and ds[tg].VM > 0: inner_sq = ds[tg] item = inner_sq.value[0] else: item = Dataset() new_element = DataElementX(tg, vr, Sequence([item])) ds[tg] = new_element put_attribute_in_path(item, path, a)
def get_patient(patient_name, patient_id, n, patient_names=None, patient_ids=None, order=None): name_trailing, id_trailing = '', '' if patient_names is None: patient_names, name_trailing = parse_patient(patient_name) if patient_ids is None: patient_ids, id_trailing = parse_patient(patient_name) # in case patient id format is different # patient_ids, id_trailing = parse_patient(patient_id) # print(patient_names) if len(patient_names) != n: tmpName = 3 * ['blank'] for i in range(len(order)): if int(order[i]) != 0: try: tmpName[i] = patient_names.pop(0) except: continue patient_names = tmpName warnings.warn('failed to parse PatientName %s, append a blank' % patient_name) if len(patient_ids) != n: tmpId = 3 * ['blank'] for i in range(len(order)): if int(order[i]) != 0: try: tmpId[i] = patient_ids.pop(0) except: continue patient_ids = tmpId warnings.warn('failed to parse PatientID %s, append a blank' % patient_id) source_patient = Dataset() # FIXME: remove '_1'? source_patient.PatientName = patient_name source_patient.PatientID = patient_id return (patient_names, patient_ids), Sequence([source_patient ]), (name_trailing, id_trailing)
def _convert_value(self, val): """Convert `val` to an appropriate type and return the result. Uses the element's VR in order to determine the conversion method and resulting type. """ if self.VR == 'SQ': # a sequence - leave it alone from pydicom.sequence import Sequence if isinstance(val, Sequence): return val else: return Sequence(val) # if the value is a list, convert each element try: val.append except AttributeError: # not a list return self._convert(val) else: return MultiValue(lambda x: self._convert(x), val)
def _convert_value(self, val): """Convert Dicom string values if possible to e.g. numbers. Handle the case of multiple value data_elements""" if self.VR == 'SQ': # a sequence - leave it alone from pydicom.sequence import Sequence if isinstance(val, Sequence): return val else: return Sequence(val) # if the value is a list, convert each element try: val.append except AttributeError: # not a list return self._convert(val) else: returnvalue = [] for subval in val: returnvalue.append(self._convert(subval)) return returnvalue
def add_dicom_sequence(ds, seq_keyword, data_set_dict): """Add a sequence to a data set. Parameters ---------- ds : pydicom Dataset The pydicom dataset for the sequence to be added to. seq_keyword : str The DICOM keyword for the sequence. data_set_dict : dict Dictionary of tags and values for the sequence element. """ seq_ds = Dataset() for tag, value in data_set_dict.items(): set_dicom_tag_value(seq_ds, tag, value) if hasattr(ds, seq_keyword): getattr(ds, seq_keyword).append(seq_ds) else: setattr(ds, seq_keyword, Sequence([seq_ds]))
def create_new_contour(self, roi_id, extents, z): """Create a new contour sequence for the given ROI id.""" roic = self.rtss.ds.ROIContourSequence[roi_id - 1] new_contour = Dataset() # Create a ContourImageSequence for the referenced Image new_contour.ContourImageSequence = Sequence([]) contour_image = Dataset() last_contour = roic.ContourSequence[-1].ContourImageSequence[-1] contour_image.ReferencedSOPClassUID = \ last_contour.ReferencedSOPClassUID contour_image.ReferencedSOPInstanceUID = \ last_contour.ReferencedSOPInstanceUID new_contour.ContourImageSequence.append(contour_image) new_contour.ContourGeometricType = 'CLOSED_PLANAR' new_contour.NumberOfContourPoints = 4 xmin, ymin, xmax, ymax = extents new_contour.ContourData = [ xmin, ymin, z, xmax, ymin, z, xmax, ymax, z, xmin, ymax, z ] roic.ContourSequence.append(new_contour)
def create_contour_sequence(roi_data: ROIData, series_data) -> Sequence: """ Iterate through each slice of the mask For each connected segment within a slice, create a contour """ contour_sequence = Sequence() for i, series_slice in enumerate(series_data): mask_slice = roi_data.mask[:,:,i] # Do not add ROI's for blank slices if np.sum(mask_slice) == 0: print("Skipping empty mask layer") continue contour_coords = get_contours_coords(mask_slice, series_slice, roi_data) for contour_data in contour_coords: contour = create_contour(series_slice, contour_data) contour_sequence.append(contour) return contour_sequence
def __add_circles(dataset, circles): circle_objects = [] for circle in circles: ds_cir_object = Dataset() cir_pos_x = circle["x"] cir_pos_y = circle["y"] cir_rad = circle["radius"] ds_cir_object.GraphicAnnotationUnits = "PIXEL" ds_cir_object.GraphicDimensions = 2 ds_cir_object.NumberOfGraphicPoints = 2 ds_cir_object.GraphicData = [ cir_pos_x, # x coordinate of middle of circle cir_pos_y, # y coordinate of middle of circle cir_pos_x, # x coordinate of point on circumference cir_pos_y + cir_rad ] # y coordinate of point on circumference ds_cir_object.GraphicType = "CIRCLE" ds_cir_object.GraphicFilled = "N" circle_objects.append(ds_cir_object) dataset.GraphicObjectSequence = Sequence(circle_objects) return dataset
def test_adding_datasets(self): """Tests for adding datasets to the Sequence""" ds_a = Dataset() ds_a.Rows = 1 ds_b = Dataset() ds_b.Rows = 2 ds_c = Dataset() ds_c.Rows = 3 ds_d = Dataset() ds_d.Rows = 4 ds_e = Dataset() ds_e.Rows = 5 parent = Dataset() parent.PatientName = "Parent" seq = Sequence() seq.parent = parent assert isinstance(seq.parent, weakref.ReferenceType) seq.append(ds_a) seq.append(ds_c) seq.insert(1, ds_b) assert 3 == len(seq) for ds in seq: assert isinstance(ds.parent, weakref.ReferenceType) seq[1] = ds_e assert ds_e == seq[1] assert [ds_a, ds_e, ds_c] == seq seq[1:1] = [ds_d] assert [ds_a, ds_d, ds_e, ds_c] == seq seq[1:2] = [ds_c, ds_e] assert [ds_a, ds_c, ds_e, ds_e, ds_c] == seq for ds in seq: assert isinstance(ds.parent, weakref.ReferenceType) msg = r"Can only assign an iterable of 'Dataset'" with pytest.raises(TypeError, match=msg): seq[1:1] = ds_d
def read_sequence(fp, is_implicit_VR, is_little_endian, bytelength, encoding, offset=0): """Read and return a Sequence -- i.e. a list of Datasets""" seq = [] # use builtin list to start for speed, convert to Sequence at end is_undefined_length = False if bytelength != 0: # SQ of length 0 possible (PS 3.5-2008 7.5.1a (p.40) if bytelength == 0xffffffff: is_undefined_length = True bytelength = None fp_tell = fp.tell # for speed in loop fpStart = fp_tell() while (not bytelength) or (fp_tell() - fpStart < bytelength): file_tell = fp.tell() dataset = read_sequence_item(fp, is_implicit_VR, is_little_endian, encoding, offset) if dataset is None: # None is returned if hit Sequence Delimiter break dataset.file_tell = file_tell + offset seq.append(dataset) seq = Sequence(seq) seq.is_undefined_length = is_undefined_length return seq
def _convert_value(self, val: Any) -> Any: """Convert `val` to an appropriate type and return the result. Uses the element's VR in order to determine the conversion method and resulting type. """ if self.VR == VR_.SQ: # a sequence - leave it alone from pydicom.sequence import Sequence if isinstance(val, Sequence): return val return Sequence(val) # if the value is a list, convert each element try: val.append except AttributeError: # not a list return self._convert(val) if len(val) == 1: return self._convert(val[0]) return MultiValue(self._convert, val, validation_mode=self.validation_mode)
def apply_rules(self, rules: RuleSet, dataset: Dataset) -> Dataset: """Apply rules to each element in dataset, recursing into sequence elements This creates a deep copy of the input dataset. Except for PixelData, which will be a reference. PixelData is not copied because it can take up a lot of memory """ deidentified = Dataset() pixel_data_tag = 0x7FE00010 for element in dataset: if element.tag == pixel_data_tag: deidentified.add( element) # add pixel data as reference to save mem elif element.VR == VRs.Sequence.short_name: # recurse into sequences deidentified.add( DataElement( tag=element.tag, VR=element.VR, value=Sequence([ self.apply_rules(rules, sub_dataset) for sub_dataset in element ]), )) elif rule := rules.get_rule(element): if type(rule.operation) == Remove: continue # special handling. should be removed, do not add try: new = rule.operation.apply(element, dataset) deidentified.add(new) except ElementShouldBeRemoved: # Operators signals removal continue else: # no rule found. Just copy the element over deidentified.add( DataElement(tag=element.tag, VR=element.VR, value=element.value))
def testDefaultInitialization(self): """Sequence: Ensure a valid Sequence is created""" empty = Sequence() assert 0 == len(empty)