예제 #1
0
def a_mock_ae_associate():
    """Mock the main function used in retrieving DICOM-QR information"""
    assoc = Mock(spec=pynetdicom.association.Association)
    assoc.send_c_find = Mock(
        return_value=iter(
            [
                ("status", quick_dataset(PatientName="patient")),
                ("status2", quick_dataset(PatientName="patient2")),
            ]
        )
    )
    assoc.is_established = True
    return assoc
예제 #2
0
def test_storage_dir_write(tmpdir):
    """Make sure writing to disk works. Seems slight overkill. But coverage."""
    expected_path = Path(str(tmpdir)) / "unknown/unknown/unknown"
    assert not expected_path.exists()
    DICOMStorageDir(str(tmpdir)).save(quick_dataset())
    assert expected_path.exists()
    assert "tmp" in str(DICOMStorageDir("/tmp"))
예제 #3
0
def test_trolley_download(
    a_trolley, tmpdir, a_mint_study_with_instances, monkeypatch
):
    a_trolley.fetch_all_datasets = Mock(
        return_value=iter(
            [
                quick_dataset(PatientName="pat1", StudyDescription="a study"),
                quick_dataset(PatientName="pat2", StudyDescription="a study2"),
            ]
        )
    )
    storage = Mock(spec=DICOMStorageDir)

    monkeypatch.setattr(
        "dicomtrolley.trolley.DICOMStorageDir", Mock(return_value=storage)
    )
    a_trolley.download(a_mint_study_with_instances, tmpdir)
    assert storage.save.called
예제 #4
0
def test_trolley_get_dataset(a_trolley, some_mint_studies, tmpdir):
    a_trolley.searcher.find_studies = Mock(return_value=some_mint_studies)
    a_trolley.wado.get_dataset = Mock(
        return_value=quick_dataset(
            StudyInstanceUID="foo",
            SeriesInstanceUID="baz",
            SOPInstanceUID="bimini",
        )
    )

    datasets = list(a_trolley.fetch_all_datasets(some_mint_studies))
    assert len(datasets) == 14
    assert datasets[0].SOPInstanceUID == "bimini"
예제 #5
0
def test_trolley_download_study(a_trolley, some_mint_studies, tmpdir):
    a_trolley.fetch_all_datasets = Mock(
        return_value=iter(
            [
                quick_dataset(
                    StudyInstanceUID="foo",
                    SeriesInstanceUID="baz",
                    SOPInstanceUID="bimini",
                )
            ]
        )
    )
    expected_path = Path(str(tmpdir)) / "foo/baz/bimini"
    assert not expected_path.exists()
    a_trolley.download(some_mint_studies, output_dir=tmpdir)
    assert expected_path.exists()
예제 #6
0
def test_trolley_get_dataset_async(a_trolley, some_mint_studies):
    a_trolley.wado.datasets_async = Mock(
        return_value=iter(
            [
                quick_dataset(
                    StudyInstanceUID="foo",
                    SeriesInstanceUID="baz",
                    SOPInstanceUID="bimini",
                )
            ]
            * 3
        )
    )

    datasets = list(a_trolley.fetch_all_datasets_async(some_mint_studies))
    assert len(datasets) == 3
    assert datasets[0].SOPInstanceUID == "bimini"
예제 #7
0
def test_required_dataset():
    """A Dataset that raises specific exception for missing keys"""
    ds = quick_dataset(PatientID="1", Modality="CT")

    # this should work
    ds.PatientID
    ds["PatientID"]

    # this should not work
    with pytest.raises(AttributeError):
        ds.PatientName
    with pytest.raises(KeyError):
        ds["PatientName"]

    # with required dataset this should be the same exception
    with pytest.raises(RequiredTagNotFound):
        RequiredDataset(ds).PatientName
    with pytest.raises(RequiredTagNotFound):
        RequiredDataset(ds)["PatientName"]
예제 #8
0
def test_reject_non_standard():

    a_core = Core(profile=Profile(rule_sets=[]), bouncers=[RejectNonStandardDicom()])

    # this should not raise anything
    a_core.deidentify(quick_dataset(SOPClassUID="1.2.840.10008"))

    with pytest.raises(DeidentificationException):
        a_core.deidentify(quick_dataset(SOPClassUID="123"))


@pytest.mark.parametrize(
    "dataset",
    [
        quick_dataset(SOPClassUID="1.2.840.10008.1234"),  # Not a bad SOPClass
        quick_dataset(
            SOPClassUID="1.2.840.10008.5.1.4.1.1.11.1", SeriesDescription="Annotation"
        ),  # bad, but annotation
    ],
)
def test_reject_kogsps_pass(dataset):
    """Datasets that should be passed"""
    # should not raise exceptions
    assert Core(profile=Profile(rule_sets=[]), bouncers=[RejectKOGSPS()]).deidentify(
        dataset
    )


@pytest.mark.parametrize(
    "dataset",
예제 #9
0
def test_parse_tree_exceptions():
    tree = DICOMParseTree()
    tree.insert_dataset(quick_dataset(StudyInstanceUID="1"))
    with pytest.raises(DICOMTrolleyError):
        tree.insert_dataset(quick_dataset(StudyInstanceUID="1"))
예제 #10
0
def test_needs_cleaning():
    """Verify that DICOM files that do not need cleaning are not cleaned"""
    processor = PixelProcessor(location_list=PIILocationList([]))
    assert processor.needs_cleaning(quick_dataset(Modality="US")) is True
    assert (processor.needs_cleaning(
        quick_dataset(Modality="CT", SOPClassUID="123")) is False)
    assert (processor.needs_cleaning(
        quick_dataset(Modality="SC", BurnedInAnnotation="No")) is False)
    assert (processor.needs_cleaning(
        quick_dataset(Modality="SC", BurnedInAnnotation="Yes")) is True)


@pytest.mark.parametrize(
    "dataset",
    [Dataset(), quick_dataset(Modality="CT")],  # No Modality  # no SOPClassUID
)
def test_needs_cleaning_exceptions(dataset):
    """Verify cannot determine whether this needs cleaning"""
    with pytest.raises(PixelDataProcessorException):
        PixelProcessor(PIILocationList([])).needs_cleaning(dataset)


def test_process_pixel_data_exception():
    """A suspicious dataset that cannot be cleaned should raise exception"""

    processor = PixelProcessor(location_list=PIILocationList([]))
    with pytest.raises(PixelDataProcessorException) as e:
        processor.clean_pixel_data(CTDatasetFactory(Modality="US"))

    assert "could not find any location to clean" in str(e.value)
예제 #11
0
    quick_image_level_study,
)


@pytest.fixture
def a_trolley(a_mint, a_wado) -> Trolley:
    """Trolley instance that will not hit any server"""
    return Trolley(searcher=a_mint, wado=a_wado, query_missing=False)


@pytest.mark.parametrize(
    "dataset, expected_path",
    [
        (
            quick_dataset(
                StudyInstanceUID="A", SeriesInstanceUID="B", SOPInstanceUID="C"
            ),
            "/tmp/A/B/C",
        ),
        (
            quick_dataset(StudyInstanceUID="A", SeriesInstanceUID="B"),
            "/tmp/A/B/unknown",
        ),
        (quick_dataset(), "/tmp/unknown/unknown/unknown"),
    ],
)
def test_storage_dir_generate_path(dataset, expected_path):
    storage = DICOMStorageDir("/tmp")
    assert storage.generate_path(dataset) == Path("/tmp") / expected_path

예제 #12
0
    '/instance><instance><attr tag="00080018" vr="UI" '
    'val="1.2.840.113663.1500.1.460388269.3.21.20201105.85626.622" /><attr '
    'tag="00020010" vr="UI" val="1.2.840.10008.1.2.4.70" /></instance><attr '
    'tag="0020000e" vr="UI" '
    'val="1.2.840.113663.1500.1.460388269.2.1.20201105.84519.348" /><'
    '/series><attr tag="00100020" vr="LO" val="1392052" /><attr '
    'tag="00100010" vr="PN" val="BEELDENZORG^W^I L" /><attr tag="0020000d" '
    'vr="UI" val="1.2.840.114350.2.357.2.798268.2.125886546.1" /></study><'
    "/studySearchResults>",
)

# a Response that contains a valid DICOM bytes
WADO_RESPONSE_DICOM = MockResponse(
    url=MockUrls.WADO_URL + MockWadoParameters.as_wado_query_string(),
    content=create_dicom_bytestream(
        quick_dataset(PatientName="Jane", StudyDescription="Test")
    ),
)

WADO_RESPONSE_INVALID_DICOM = MockResponse(
    url=MockUrls.WADO_URL + MockWadoParameters.as_wado_query_string(),
    content=bytes(1234),
)

WADO_RESPONSE_INVALID_NON_DICOM = MockResponse(
    url=MockUrls.WADO_URL + MockWadoParameters.as_wado_query_string(),
    status_code=502,
    text="Error, server really does not know anymore",
)