Exemple #1
0
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
Exemple #2
0
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'
Exemple #5
0
 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)
Exemple #8
0
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
Exemple #9
0
 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)
Exemple #10
0
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))
Exemple #11
0
 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)
Exemple #12
0
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
Exemple #13
0
 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)
Exemple #14
0
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'}
Exemple #17
0
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'
Exemple #19
0
    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
Exemple #21
0
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'
Exemple #22
0
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
Exemple #23
0
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']
Exemple #24
0
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'
Exemple #25
0
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
Exemple #29
0
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'