def test_too_many_headers_file(tmpdir): # Generate test file... test_file_path = Path(tmpdir) / "test.mhd" with open(test_file_path, "w", encoding="utf-8") as f: for i in range(1000000): f.write(f"key{i} = {i}\n") with pytest.raises(ValidationError): parse_mh_header(test_file_path)
def test_line_too_long(tmpdir): # Generate test file... test_file_path = Path(tmpdir) / "test.mhd" with open(test_file_path, "w", encoding="utf-8") as f: f.write("key = ") for i in range(1000000): f.write(f"{i}") with pytest.raises(ValidationError): parse_mh_header(test_file_path)
def get_mh_header(self) -> Mapping[str, Union[str, None]]: """ Return header from mhd/mha file as key value pairs Returns ------- MetaIO headers as key value pairs. Raises ------ FileNotFoundError Raised when Image has no related mhd/mha ImageFile or actual file cannot be found on storage """ mh_file = None try: mh_file = self.files.get(image_type=ImageFile.IMAGE_TYPE_MHD, file__endswith=".mha") except ObjectDoesNotExist: # Fallback to files that are still stored as mhd/(z)raw mh_file = self.files.get(image_type=ImageFile.IMAGE_TYPE_MHD, file__endswith=".mhd") if mh_file is None or not mh_file.file.storage.exists( name=mh_file.file.name): raise FileNotFoundError(f"No file found for {mh_file.file}") return parse_mh_header(mh_file.file)
def test_does_not_choke_on_empty_file(tmpdir): # Generate test file... test_file_path = Path(tmpdir) / "test.mhd" with open(test_file_path, "w", encoding="utf-8") as f: f.write("\n") assert parse_mh_header(test_file_path) == {}
def get_mh_header(self) -> Mapping[str, Union[str, None]]: """ Return header from mhd/mha file as key value pairs Returns ------- MetaIO headers as key value pairs. Raises ------ FileNotFoundError Raised when Image has no related mhd/mha ImageFile or actual file cannot be found on storage """ mh_file, _ = self.get_metaimage_files() return parse_mh_header(mh_file.file)
def test_image_builder_dicom_4dct(tmpdir): files = {Path(d[0]).joinpath(f) for d in os.walk(DICOM_DIR) for f in d[2]} result = _build_files(builder=image_builder_dicom, files=files, output_directory=tmpdir) assert result.consumed_files == { Path(DICOM_DIR).joinpath(f"{x}.dcm") for x in range(1, 77) } assert len(result.new_images) == 1 image = Image(**asdict(result.new_images.pop())) assert image.shape == [19, 4, 2, 3] assert len(result.new_image_files) == 1 mha_file_obj = [ x for x in result.new_image_files if x.file.suffix == ".mha" ][0] headers = parse_mh_header(mha_file_obj.file) direction = headers["TransformMatrix"].split() origin = headers["Offset"].split() spacing = headers["ElementSpacing"].split() exposures = headers["Exposures"].split() content_times = headers["ContentTimes"].split() assert len(exposures) == 19 assert exposures == [str(x) for x in range(100, 2000, 100)] assert len(content_times) == 19 assert content_times == [str(x) for x in range(214501, 214520)] dcm_ref = pydicom.dcmread(str(DICOM_DIR / "1.dcm")) assert np.array_equal( np.array(list(map(float, direction))).reshape((4, 4)), np.eye(4)) assert np.allclose( list(map(float, spacing))[:2], list(map( float, list(dcm_ref.PixelSpacing), )), ) assert np.allclose( list(map(float, origin)), list(map(float, dcm_ref.ImagePositionPatient)) + [0.0], )
def test_parse_header_valid_mhd(): headers = parse_mh_header(RESOURCE_PATH / "image10x10x10.mhd") assert headers == { "ObjectType": "Image", "NDims": "3", "BinaryData": "True", "BinaryDataByteOrderMSB": "False", "CompressedData": "True", "CompressedDataSize": "7551", "TransformMatrix": "1 0 0 0 1 0 0 0 1", "Offset": "0 0 0", "CenterOfRotation": "0 0 0", "AnatomicalOrientation": "RAI", "ElementSpacing": "1 1 1", "DimSize": "10 10 10", "ElementType": "MET_DOUBLE", "ElementDataFile": "image10x10x10.zraw", }
def test_parse_header_valid_4d_mhd(): headers = parse_mh_header(RESOURCE_PATH / "image10x11x12x13.mhd") assert headers == { "ObjectType": "Image", "NDims": "4", "BinaryData": "True", "BinaryDataByteOrderMSB": "False", "CompressedData": "True", "CompressedDataSize": "39", "TransformMatrix": "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1", "Offset": "-131 -99 -917 0", "CenterOfRotation": "0 0 0 0", "AnatomicalOrientation": "RAI", "ElementSpacing": "0.429 0.429 0.5 1", "DimSize": "10 11 12 13", "ElementType": "MET_UCHAR", "ElementDataFile": "image10x11x12x13.zraw", }
def test_staged_mhd_upload_with_additional_headers( settings, tmp_path, images: List[str] ): # Override the celery settings settings.task_eager_propagates = (True,) settings.task_always_eager = (True,) session, uploaded_images = create_raw_upload_image_session(images=images) session.refresh_from_db() assert session.status == session.SUCCESS assert session.error_message is None images = Image.objects.filter(origin=session).all() assert len(images) == 1 raw_image_file: RawImageFile = list(uploaded_images.values())[0] raw_image_file.refresh_from_db() assert raw_image_file.staged_file_id is None image: Image = images[0] tmp_header_filename = tmp_path / "tmp_header.mhd" with image.files.get(file__endswith=".mha").file.open( "rb" ) as in_file, open(tmp_header_filename, "wb") as out_file: out_file.write(in_file.read()) headers = parse_mh_header(tmp_header_filename) for key in headers.keys(): assert (key in ADDITIONAL_HEADERS) or (key in EXPECTED_HEADERS) sitk_image: SimpleITK.Image = image.get_sitk_image() for key in ADDITIONAL_HEADERS: assert key in sitk_image.GetMetaDataKeys() if key in HEADERS_MATCHING_NUM_TIMEPOINTS: if sitk_image.GetDimension() >= 4: assert ( len(sitk_image.GetMetaData(key).split(" ")) == sitk_image.GetSize()[3] ) else: assert len(sitk_image.GetMetaData(key).split(" ")) == 1 assert "Bogus" not in sitk_image.GetMetaDataKeys()
def test_dicom_rescaling(folder, element_type, tmpdir): """ 2.dcm in dicom_intercept and dicom_slope has been modified to add a small intercept (0.01) or slope (1.001) respectively. """ files = [ Path(d[0]).joinpath(f) for d in os.walk(RESOURCE_PATH / folder) for f in d[2] ] result = _build_files(builder=image_builder_dicom, files=files, output_directory=tmpdir) assert len(result.new_image_files) == 1 mha_file_obj = [ x for x in result.new_image_files if x.file.suffix == ".mha" ][0] headers = parse_mh_header(mha_file_obj.file) assert headers["ElementType"] == element_type
def test_dicom_window_level(tmpdir): files = { Path(d[0]).joinpath(f) for d in os.walk(RESOURCE_PATH / "dicom") for f in d[2] } result = _build_files(builder=image_builder_dicom, files=files, output_directory=tmpdir) assert len(result.new_image_files) == 1 mha_file_obj = [ x for x in result.new_image_files if x.file.suffix == ".mha" ][0] headers = parse_mh_header(mha_file_obj.file) assert headers["WindowCenter"] == "30" assert headers["WindowWidth"] == "200" assert len(result.new_images) == 1 image_obj = result.new_images.pop() assert image_obj.window_center == 30.0 assert image_obj.window_width == 200.0
def test_fail_on_invalid_utf8(): with pytest.raises(ValidationError): parse_mh_header(RESOURCE_PATH / "invalid_utf8.mhd")