def datasetFromJSON(data: dict): #return Dataset.from_json(data) ds = Dataset() for key in data.keys(): tag = Tag(key) try: if 'Value' in data[key].keys(): if data[key]['vr'] == 'SQ': tempds = [] for subdata in data[key]['Value']: tempds.append(datasetFromJSON(subdata)) seq = Sequence(tempds) ds[key] = DataElement(tag, data[key]['vr'], seq) elif type( data[key]['Value'][0] ) == dict and 'Alphabetic' in data[key]['Value'][0].keys(): ds[key] = DataElement(tag, data[key]['vr'], data[key]['Value'][0]['Alphabetic']) else: if len(data[key]['Value']) > 1: ds[key] = DataElement(tag, data[key]['vr'], data[key]['Value']) else: ds[key] = DataElement(tag, data[key]['vr'], data[key]['Value'][0]) else: ds[key] = DataElement(tag, data[key]['vr'], '') except: from IPython import embed embed() return ds
def test_patient_find_text_filter_negative(pacs_srv: pacs.PACS): request = Dataset() request.PatientSex = None request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'PATIENT' request.PatientName = 'Test1^*' assert not list(pacs_srv.c_find(request))
def test_update_patient_result_raise_if_id_change(patient_dataset_factory): slice_1 = patient_dataset_factory(PatientID='1') slice_2 = patient_dataset_factory(PatientID='2') result = Dataset() update_patient_result(result, slice_1) with pytest.raises(ValueError): update_patient_result(result, slice_2)
def test_update_patient_result_additional_tags_present( patient_dataset_factory): result = Dataset() dataset = patient_dataset_factory(PatientSex='M') additional_tags = ['PatientSex'] update_patient_result(result, dataset, additional_tags) assert result.PatientSex == 'M'
def __init__(self, sequence_data): """Object initialization Parameters ---------- sequence_data : List of items with data to generate each sequence item, in the format of a list with a dictionary for each item, which in turn can contain a sequence, e.g. list of dictionaries """ super().__init__() for sequence_item in sequence_data: # Initiate dataset ds = Dataset() # Set required DICOM attributes ds.SeriesInstanceUID = generate_uid() ds.ReferencedSOPSequence = generate_sequence( "ReferencedSOPSequence", dict()) # Update and insert additional DICOM attributes as available ds = update_and_insert_additional_DICOM_attributes_in_ds( ds, sequence_item) # Remove mutually exclusive elemenets if "ReferencedSOPSequence" in sequence_item and "ReferencedImageSequence" in ds: del ds.ReferencedImageSequence elif "ReferencedImageSequence" in sequence_item and "ReferencedSOPSequence" in ds: del ds.ReferencedSOPSequence self.sequence.append(ds)
def test_when_patient_birth_date(self): expected = '002Y' dicom = Dataset() dicom.update({'StudyDate': '20181217', 'PatientBirthDate': '20161210'}) assert age_in_years(dicom) == expected
def test_update_patient_result_missing_study_date(patient_dataset_factory): result = Dataset() update_patient_result(result, patient_dataset_factory(StudyDate='')) assert result.PatientMostRecentStudyDate == '' update_patient_result(result, patient_dataset_factory(StudyDate=date(2018, 1, 1))) assert result.PatientMostRecentStudyDate == date(2018, 1, 1)
def dicom_dataset_from_dict(input_dict: dict, template_ds=None): """Create a pydicom DICOM object from a dictionary""" if template_ds is None: dataset = Dataset() else: dataset = deepcopy(template_ds) for key, value in input_dict.items(): if key not in DICOM_NAMES: raise ValueError( "{} is not within the DICOM dictionary.".format(key)) if isinstance(value, dict): setattr(dataset, key, dicom_dataset_from_dict(value)) elif isinstance(value, list): if np.all([not isinstance(item, dict) for item in value]): convert_nparray_and_set_key_value_in_dataset( dataset, key, value) elif np.all([isinstance(item, dict) for item in value]): setattr(dataset, key, [dicom_dataset_from_dict(item) for item in value]) else: raise ValueError( "{} should contain either only dictionaries, or no " "dictionaries".format(key)) else: convert_nparray_and_set_key_value_in_dataset(dataset, key, value) return dataset
def __init__(self, sequence_data): """Object initialization Parameters ---------- sequence_data : List of items with data to generate each sequence item, in the format of a list with a dictionary for each item, which in turn can contain a sequence, e.g. list of dictionaries """ super().__init__() for sequence_item in sequence_data: # Initiate dataset ds = Dataset() # Set required DICOM attributes ds.AnchorPointAnnotationUnits = "PIXEL" ds.UnformattedTextValue = "DEFAULT VALUE" ds.AnchorPoint = [100, 100] ds.AnchorPointVisibility = "N" # Update and insert additional DICOM attributes as available ds = update_and_insert_additional_DICOM_attributes_in_ds( ds, sequence_item) # Remove mutually exclusive elemenets if "AnchorPoint" in sequence_item and "BoundingBoxTopLeftHandCorner" in ds: del ds.BoundingBoxTopLeftHandCorner del ds.BoundingBoxBottomRightHandCorner del ds.BoundingBoxAnnotationUnits del ds.BoundingBoxTextHorizontalJustification elif "BoundingBoxTopLeftHandCorner" in sequence_item and "AnchorPoint" in ds: del ds.AnchorPoint del ds.AnchorPointAnnotationUnits del ds.AnchorPointVisibility # Add dataset to sequence self.sequence.append(ds)
def test_study_find_patient_attrs_with_filters_negative(pacs_srv: pacs.PACS): request = Dataset() request.PatientName = 'Test1^*' request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'STUDY' request.AccessionNumber = '1234' assert not list(pacs_srv.c_find(request))
def add_graphical_layer(self, layer_name, layer_order, recommended_grayscale_value=None, recommended_cielab_value=None, layer_description=None): """Add graphical layer Arguments: layer_name {str} -- Name of layer layer_order {int} -- Order of layer Keyword Arguments: recommended_grayscale_value {[type]} -- [description] (default: {None}) recommended_cielab_value {[type]} -- [description] (default: {None}) layer_description {[type]} -- [description] (default: {None}) """ ds = Dataset() ds.GraphicLayer = layer_name ds.GraphicLayerOrder = layer_order if recommended_grayscale_value is not None: ds.GraphicLayerRecommendedDisplayGrayscaleValue = recommended_grayscale_value if recommended_cielab_value is not None: ds.GraphicLayerRecommendedDisplayCIELabValue = recommended_cielab_value if layer_description is not None: ds.GraphicLayerDescription = layer_description if "GraphicLayerSequence" not in self.dataset: self.dataset.GraphicLayerSequence = generate_sequence( "GraphicLayerSequence", [{}]) self.dataset.GraphicLayerSequence.append(ds)
def move_study_uid(study_uid, one_per_series=False): """Move a full study, one_per_series doesn't work yet""" d = Dataset() d.QueryRetrieveLevel = 'STUDY' d.StudyInstanceUID = study_uid x = do_move(d) return x
def __init__(self, sequence_data): """Object initialization Parameters ---------- sequence_data : List of items with data to generate each sequence item, in the format of a list with a dictionary for each item, which in turn can contain a sequence, e.g. list of dictionaries """ super().__init__() for sequence_item in sequence_data: # Initiate dataset ds = Dataset() # Set required DICOM attributes ds.PatternOnColorCIELabValue = [65535, 32896, 32896] # white ds.PatternOnOpacity = 1.0 ds.LineThickness = 1.0 ds.LineDashingStyle = "SOLID" ds.ShadowStyle = "NORMAL" ds.ShadowOffsetX = 1.0 ds.ShadowOffsetY = 1.0 ds.ShadowColorCIELabValue = [0, 32896, 32896] # black ds.ShadowOpacity = 1.0 # Update and insert additional DICOM attributes as available ds = update_and_insert_additional_DICOM_attributes_in_ds( ds, sequence_item) # Add dataset to sequence self.sequence.append(ds)
def test_study_find_no_patient_attrs(pacs_srv: pacs.PACS): request = Dataset() request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'STUDY' request.AccessionNumber = '1234' results = list(pacs_srv.c_find(request)) assert len(results) == 1 assert results[0].AccessionNumber == '1234'
def create_empty_iod(self): """Creates and empty IOD with the required DICOM tags but no values Parameters ---------- """ super().create_empty_iod() self.copy_required_dicom_attributes(Dataset(), include_optional=True)
def test_update_patient_result_multiple_studys(patient_dataset_factory): result = Dataset() update_patient_result(result, patient_dataset_factory(StudyInstanceUID='1')) update_patient_result(result, patient_dataset_factory(StudyInstanceUID='2')) assert len(result.PatientStudyInstanceUIDs) == 2 assert {uid.name for uid in result.PatientStudyInstanceUIDs} == {'1', '2'}
def test_patient_find_date_range_negative(pacs_srv: pacs.PACS): request = Dataset() request.PatientName = None request.PatientSex = None request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'PATIENT' request.PatientBirthDate = '19670101-19680102' assert not list(pacs_srv.c_find(request))
def test_update_patient_result_single_study(patient_dataset_factory): result = Dataset() update_patient_result(result, patient_dataset_factory(StudyInstanceUID='1')) update_patient_result(result, patient_dataset_factory(StudyInstanceUID='1')) assert len(result.PatientStudyInstanceUIDs) == 1 assert result.PatientStudyInstanceUIDs[0].name == '1'
def create_dcm_file(self): suffix = '.dcm' filename_little_endian = tempfile.NamedTemporaryFile( suffix=suffix).name filename_big_endian = tempfile.NamedTemporaryFile(suffix=suffix).name print("Setting file meta information...") file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = "1.2.3" file_meta.ImplementationClassUID = "1.2.3.4" print("Setting dataset values...") ds = FileDataset(filename_little_endian, {}, file_meta=file_meta, preamble=b"\0" * 128) ds.PatientName = self.get_patient_name( ) + " " + self.get_patient_surname() ds.PatientID = self.get_patient_id() ds.PatientSex = self.get_patient_sex() ds.PatientAge = self.get_patient_age() ds.PatientWeight = self.get_patient_weight() ds.ImageComment = self.get_patient_comment() ds.PatientBirthDate = self.get_patient_birth() # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True # Set creation date/time dt = datetime.datetime.now() ds.ContentDate = dt.strftime('%Y%m%d') timeStr = dt.strftime('%H%M%S.%f') # long format with micro seconds ds.ContentTime = timeStr ds.BitsAllocated = 16 ds.Rows = self.image.shape[0] ds.Columns = self.image.shape[1] ds.PixelRepresentation = 0 ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" image = self.image image *= 255 image = image.astype("uint16") ds.PixelData = Image.fromarray(image).tobytes() print("Writing test file", filename_little_endian) ds.save_as(filename_little_endian) print("File saved.") ds.file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRBigEndian ds.is_little_endian = False ds.is_implicit_VR = False print("Writing test file as Big Endian Explicit VR", filename_big_endian) ds.save_as(filename_big_endian) return ds
def test_basic(self): """Test basic operation of the QR get service.""" self.p = p = self.func([ "--database-location", self.db_location, "--instance-location", self.instance_location.name, "-d", ]) time.sleep(1) _send_datasets() time.sleep(1) query = Dataset() query.QueryRetrieveLevel = "PATIENT" query.PatientID = "1CT1" datasets = [] def handle_store(event): datasets.append(event.dataset) return 0x0000 self.ae = ae = AE() ae.acse_timeout = 5 ae.dimse_timeout = 5 ae.network_timeout = 5 ae.add_supported_context(CTImageStorage) scp = ae.start_server( ("localhost", 11113), block=False, evt_handlers=[(evt.EVT_C_STORE, handle_store)], ) model = PatientRootQueryRetrieveInformationModelMove ae.add_requested_context(model) assoc = ae.associate("localhost", 11112) assert assoc.is_established responses = assoc.send_c_move(query, "STORESCP", model) status, ds = next(responses) assert status.Status == 0xFF00 assert ds is None status, ds = next(responses) assert status.Status == 0x0000 assert ds is None pytest.raises(StopIteration, next, responses) assoc.release() scp.shutdown() p.terminate() p.wait() assert 1 == len(datasets) assert "CompressedSamples^CT1" == datasets[0].PatientName
def test_patient_find_text_filter_positive(pacs_srv: pacs.PACS): request = Dataset() request.PatientSex = None request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'PATIENT' request.PatientName = 'Test^*' for patient in pacs_srv.c_find(request): assert patient.PatientName == 'Test^Test^Test' assert patient.PatientSex == 'M'
def test_series_find_patient_filter(pacs_srv: pacs.PACS): request = Dataset() request.PatientName = 'Test^*' request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'SERIES' request.SeriesInstanceUID = None request.Modality = None results = list(pacs_srv.c_find(request)) assert len(results) == 4
def test_study_find_modalities_in_study_no_filter(pacs_srv: pacs.PACS): request = Dataset() request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'STUDY' request.AccessionNumber = '1234' request.ModalitiesInStudy = None results = list(pacs_srv.c_find(request)) assert len(results) == 1 assert results[0].ModalitiesInStudy == ['DX', 'SR']
def test_patient_find_date_range_positive(pacs_srv: pacs.PACS): request = Dataset() request.PatientName = None request.PatientSex = None request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'PATIENT' request.PatientBirthDate = '19650101-19660102' for patient in pacs_srv.c_find(request): assert patient.PatientName == 'Test^Test^Test' assert patient.PatientSex == 'M'
def test_study_find_patient_attrs_with_filters_positive(pacs_srv: pacs.PACS): request = Dataset() request.PatientName = 'Test^*' request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'STUDY' request.AccessionNumber = '1234' results = list(pacs_srv.c_find(request)) assert len(results) == 1 assert results[0].AccessionNumber == '1234' assert results[0].PatientName == 'Test^Test^Test'
def setup(self): """Setup the tests.""" # Create a dataset skeleton for use in the cycle tests ds = Dataset() ds.file_meta = FileMetaDataset() ds.file_meta.TransferSyntaxUID = '1.2.840.10008.1.2' ds.Rows = 2 ds.Columns = 4 ds.SamplesPerPixel = 3 ds.PlanarConfiguration = 1 self.ds = ds
def factory(**overrides): nonlocal counter ds = Dataset() attributes = {**defaults, **overrides} for key, value in attributes.items(): if callable(value): value = value(counter, attributes) if value is not None: setattr(ds, key, value) counter += 1 return ds
def test_update_patient_result_single_slice(patient_dataset_factory): slice_dataset = patient_dataset_factory() result = Dataset() update_patient_result(result, slice_dataset) assert result.PatientID == slice_dataset.PatientID assert result.PatientName == slice_dataset.PatientName assert result.PacsmanPrivateIdentifier == PRIVATE_ID assert len(result.PatientStudyInstanceUIDs) == 1 assert result.PatientStudyInstanceUIDs[ 0].name == slice_dataset.StudyInstanceUID.name assert result.PatientMostRecentStudyDate == slice_dataset.StudyDate
def test_patient_find_with_count(pacs_srv: pacs.PACS): request = Dataset() request.PatientName = None request.PatientSex = None request.SpecificCharacterSet = 'ISO_IR 192' request.QueryRetrieveLevel = 'PATIENT' request.NumberOfPatientRelatedStudies = None for patient in pacs_srv.c_find(request): assert patient.PatientName == 'Test^Test^Test' assert patient.PatientSex == 'M' assert patient.NumberOfPatientRelatedStudies == 2
def test_update_patient_result_no_raise_if_name_change( patient_dataset_factory): ''' At the moment, we grab values from the first dataset that we see, and we don't change any of them after that. This is probably the desired behaviour, but it may be worth considering grabbing details from the most recent DICOM dataset ''' result = Dataset() update_patient_result(result, patient_dataset_factory(PatientName='1')) update_patient_result(result, patient_dataset_factory(PatientName='2')) assert result.PatientName == '1'