def test_read(self): l = LETCube() l.read(self.let001) v = create_sphere(l, name="sph", center=[10, 10, 10], radius=8) self.assertIsNotNone(v) logger.info("Calculating DVH") result = l.calculate_lvh(v) self.assertIsNotNone(result) lvh, min_l, max_l, mean, area = result self.assertGreater(area, 2.0) self.assertEqual(len(lvh.shape), 1) self.assertEqual(lvh.shape[0], 3000) self.assertEqual(min_l, 0.0) self.assertEqual(max_l, 1.0) self.assertGreater(l.get_max(), 30.0) fd, outfile = tempfile.mkstemp() os.close(fd) # Windows needs it os.remove(outfile) # we need only temp filename, not the file l.write(outfile) hed_file = outfile + LETCube.header_file_extension dos_file = outfile + LETCube.data_file_extension self.assertTrue(os.path.exists(hed_file)) self.assertTrue(os.path.exists(dos_file)) logger.info("Checking if output file " + hed_file + " is not empty") self.assertGreater(os.path.getsize(hed_file), 1) logger.info("Checking if output file " + dos_file + " is not empty") self.assertGreater(os.path.getsize(dos_file), 1) os.remove(hed_file) os.remove(dos_file)
def test_read(self): let = LETCube() let.read(self.let001) v = create_sphere(let, name="sph", center=[10, 10, 10], radius=8) self.assertIsNotNone(v) logger.info("Calculating DVH") result = let.calculate_lvh(v) self.assertIsNotNone(result) lvh, min_l, max_l, mean, area = result self.assertGreater(area, 2.0) self.assertEqual(len(lvh.shape), 1) self.assertEqual(lvh.shape[0], 3000) self.assertEqual(min_l, 0.0) self.assertEqual(max_l, 1.0) self.assertGreater(let.get_max(), 30.0) fd, outfile = tempfile.mkstemp() os.close(fd) # Windows needs it os.remove(outfile) # we need only temp filename, not the file let.write(outfile) hed_file = outfile + LETCube.header_file_extension dos_file = outfile + LETCube.data_file_extension self.assertTrue(os.path.exists(hed_file)) self.assertTrue(os.path.exists(dos_file)) logger.info("Checking if output file " + hed_file + " is not empty") self.assertGreater(os.path.getsize(hed_file), 1) logger.info("Checking if output file " + dos_file + " is not empty") self.assertGreater(os.path.getsize(dos_file), 1) os.remove(hed_file) os.remove(dos_file)
def test_dvh_simple(self): c = DosCube() c.read(self.cube000) v = create_sphere(c, name="sph", center=[10, 10, 10], radius=8) self.assertIsNotNone(v) logger.info("Calculating DVH simple") x, y = volume_histogram(c.cube, v) self.assertIsNotNone(x) self.assertIsNotNone(y) logger.info("Calculating DVH simple for entire cube") x, y = volume_histogram(c.cube) self.assertIsNotNone(x) self.assertIsNotNone(y)
def test_dvh(self): c = DosCube() c.read(self.cube000) v = create_sphere(c, name="sph", center=[10, 10, 10], radius=8) self.assertIsNotNone(v) logger.info("Calculating DVH") result = c.calculate_dvh(v) self.assertIsNotNone(result) dvh, min_dose, max_dose, mean, area = result self.assertGreater(area, 2.0) self.assertEqual(len(dvh.shape), 2) self.assertEqual(dvh.shape[1], 2) self.assertEqual(dvh.shape[0], 1500) self.assertEqual(min_dose, 0.0) self.assertEqual(max_dose, 0.001)
def _validate_voi(self) -> bool: voi_widget = self.view.voi_layout.itemAt(0).widget() # validate fields if not voi_widget.validate(): return False # check if name isn't already being used if voi_widget.name.lower() in self.used_voi_names: self.view.info.text = "This name is already being used by another VOI." return False ctx = self.model center_no_offsets = [a - b for (a, b) in zip(voi_widget.center, [ctx.xoffset, ctx.yoffset, ctx.zoffset])] if isinstance(voi_widget, SphericalVOIWidget): voi = create_sphere( cube=ctx, name=voi_widget.name, center=center_no_offsets, radius=voi_widget.radius ) elif isinstance(voi_widget, CuboidalVOIWidget): voi = create_cube( cube=ctx, name=voi_widget.name, center=center_no_offsets, width=voi_widget.width, height=voi_widget.height, depth=voi_widget.depth, ) elif isinstance(voi_widget, CylindricalVOIWidget): voi = create_cylinder( cube=ctx, name=voi_widget.name, center=center_no_offsets, radius=voi_widget.radius, depth=voi_widget.depth, ) else: logger.debug("VOI widget unrecognised") return False # validate containment in ctx if not voi.is_fully_contained(): self.view.info.text = "VOI isn't fully contained in the given patient." return False return True
def _set_model_from_view(self) -> None: ctx = self.model.ctx vdx = self.model.vdx list_vois = self.view.voi_scroll_area.widget().layout() # iterating over every element of the list of vois while ignoring a trailing vertical spacer for index in range(list_vois.count() - 1): # the actual voi widget is embedded in the list element, we need to shell it list_voi_element = list_vois.itemAt(index).widget() voi_widget = list_voi_element.voi_space.itemAt(0).widget() center_no_offsets = [ a - b for (a, b) in zip( voi_widget.center, [ctx.xoffset, ctx.yoffset, ctx.zoffset]) ] if isinstance(voi_widget, SphericalVOIWidget): voi = create_sphere( cube=ctx, name=voi_widget.name, center=center_no_offsets, radius=voi_widget.radius, ) elif isinstance(voi_widget, CuboidalVOIWidget): voi = create_cube( cube=ctx, name=voi_widget.name, center=center_no_offsets, width=voi_widget.width, height=voi_widget.height, depth=voi_widget.depth, ) elif isinstance(voi_widget, CylindricalVOIWidget): voi = create_cylinder( cube=ctx, name=voi_widget.name, center=center_no_offsets, radius=voi_widget.radius, depth=voi_widget.depth, ) else: logger.debug("VOI widget unrecognised") return vdx.add_voi(voi)
def voxelplan_header_path(tmpdir_factory): ctx = CtxCube() ctx.create_empty_cube(value=0, dimx=100, dimy=100, dimz=25, pixel_size=1, slice_distance=2, slice_offset=0) file_obj = tmpdir_factory.mktemp("data").join("patient") patient_base_path = str(file_obj) ctx.write(patient_base_path) vdx = VdxCube(cube=ctx) voi = create_sphere(cube=ctx, name="target", center=[50, 50, 25], radius=10) vdx.add_voi(voi) vdx.write(patient_base_path + '.vdx') yield patient_base_path + '.hed'
def test_dvh_simple(self): c = DosCube() c.read(self.cube000) v = create_sphere(c, name="sph", center=[10, 10, 10], radius=8) self.assertIsNotNone(v) logger.info("Calculating DVH simple") vh = VolHist(c, v) self.assertIsNotNone(vh.x) self.assertIsNotNone(vh.y) outdir = tempfile.mkdtemp() c.write_dicom(outdir) f1 = os.path.join(outdir, "foobar_1.dvh") vh.write(f1, header=True) self.assertTrue(os.path.exists(f1)) self.assertGreater(os.path.getsize(f1), 0) f2 = os.path.join(outdir, "foobar_2.dvh") vh.write(f2, header=False) self.assertTrue(os.path.exists(f2)) self.assertGreater(os.path.getsize(f2), 0) logger.info("Calculating DVH simple for entire cube") vh = VolHist(c) self.assertIsNotNone(vh.x) self.assertIsNotNone(vh.y) f3 = os.path.join(outdir, "foobar_3.dvh") vh.write(f3, header=True) self.assertTrue(os.path.exists(f3)) self.assertGreater(os.path.getsize(f3), 0) f4 = os.path.join(outdir, "foobar_4.dvh") vh.write(f4, header=False) self.assertTrue(os.path.exists(f4)) self.assertGreater(os.path.getsize(f4), 0) shutil.rmtree(outdir)
def test_create_voi_sphere(self): logger.info("Creating CT cube from path " + self.cube000) c = pt.CtxCube() c.read(self.cube000) logger.info("Generating and adding sphere VOI") v = create_sphere(c, name="cube3", center=[10, 10, 10], radius=8) self.assertEqual(v.number_of_slices(), 6) logger.info("Checking Voi vdx_string method") self.assertGreater(len(v.vdx_string()), 1) logger.info("Checking Voi get_slice_at_pos method, non-existent slice") self.assertIsNone(v.get_slice_at_pos(137)) logger.info("Checking Voi get_slice_at_pos method, good slice") s = v.get_slice_at_pos(11) self.assertIsNotNone(s) logger.info("Checking Slice vdx_string method") self.assertGreater(len(s.vdx_string()), 1) logger.info("Checking Slice number_of_contours method") self.assertEqual(s.number_of_contours(), 1) logger.info("Checking Contour create_dicom_contours method") dicom_cont = s.create_dicom_contours(v.cube.create_dicom()) self.assertEqual(len(dicom_cont), 1) contour = s.contours[0] logger.info("Checking Contour calculate_center method") center, area = contour.calculate_center() self.assertAlmostEqual(center[0], 10.0) self.assertAlmostEqual(center[1], 10.0) self.assertAlmostEqual(center[2], 12.0) # TODO why 12 ? self.assertGreater(area, 100.0) logger.info("Checking Contour vdx_string method") self.assertGreater(len(contour.vdx_string()), 1) logger.info("Checking Contour number_of_points method") self.assertEqual(contour.number_of_points(), 99) logger.info("Checking Contour has_childs method") self.assertFalse( contour.has_childs()) # TODO why doesn't have children ? contour.print_child(level=0) logger.info("Test of Voi get_min_max method") s_min, s_max = v.get_min_max() self.assertIsNotNone(s_min) self.assertIsNotNone(s_max) # TODO check why get_min_max returns tuple, not a number self.assertEqual(s_max[2], 18.0) self.assertEqual(s_min[2], 3.0) logger.info( "Subsequent test of Voi get_min_max method, as it modifies the object" ) s_min, s_max = v.get_min_max() self.assertIsNotNone(s_min) self.assertIsNotNone(s_max) # TODO check why get_min_max returns tuple, not a number self.assertEqual(s_max[2], 18.0) self.assertEqual(s_min[2], 3.0) logger.info("Test of Voi get_2d_slice method (sagittal)") s2 = v.get_2d_slice(plane=pt.Voi.sagittal, depth=10.0) self.assertIsNotNone(s2) logger.info("Test of Voi get_2d_slice method (coronal)") s3 = v.get_2d_slice(plane=pt.Voi.coronal, depth=5.0) self.assertIsNotNone(s3) logger.info("Test of Voi get_2d_projection_on_basis method") v.get_2d_projection_on_basis(basis=((1, 0, 0), (0, 2, 0))) logger.info("Test of Voi create_point_tree method") v.create_point_tree() self.assertIsNotNone(v.points) self.assertEqual(len(v.points), 496) logger.info("Test of Voi get_row_intersections method") isec = v.get_row_intersections(pos=(10, 10, 9)) self.assertIsNotNone(isec) self.assertEqual(len(isec), 2) logger.info("Test of Voi get_voi_cube method") vc = v.get_voi_cube() self.assertIsNotNone(vc) center_pos = v.calculate_center() self.assertAlmostEqual(center_pos[0], 10.0)
def test_create_voi_sphere(self): logger.info("Creating CT cube from path " + self.cube000) c = pt.CtxCube() c.read(self.cube000) logger.info("Generating and adding sphere VOI") v = create_sphere(c, name="cube3", center=[10, 10, 10], radius=8) self.assertEqual(v.number_of_slices(), 6) logger.info("Checking Voi vdx_string method") self.assertGreater(len(v.vdx_string()), 1) logger.info("Checking Voi get_slice_at_pos method, non-existent slice") self.assertIsNone(v.get_slice_at_pos(137)) logger.info("Checking Voi get_slice_at_pos method, good slice") s = v.get_slice_at_pos(11) self.assertIsNotNone(s) logger.info("Checking Slice vdx_string method") self.assertGreater(len(s.vdx_string()), 1) logger.info("Checking Slice number_of_contours method") self.assertEqual(s.number_of_contours(), 1) logger.info("Checking Contour create_dicom_contours method") dicom_cont = s.create_dicom_contours(v.cube.create_dicom()) self.assertEqual(len(dicom_cont), 1) contour = s.contours[0] logger.info("Checking Contour calculate_center method") center, area = contour.calculate_center() self.assertAlmostEqual(center[0], 10.0) self.assertAlmostEqual(center[1], 10.0) self.assertAlmostEqual(center[2], 12.0) # TODO why 12 ? self.assertGreater(area, 100.0) logger.info("Checking Contour vdx_string method") self.assertGreater(len(contour.vdx_string()), 1) logger.info("Checking Contour number_of_points method") self.assertEqual(contour.number_of_points(), 99) logger.info("Checking Contour has_childs method") self.assertFalse(contour.has_childs()) # TODO why doesn't have children ? contour.print_child(level=0) logger.info("Test of Voi get_min_max method") s_min, s_max = v.get_min_max() self.assertIsNotNone(s_min) self.assertIsNotNone(s_max) # TODO check why get_min_max returns tuple, not a number self.assertEqual(s_max[2], 18.0) self.assertEqual(s_min[2], 3.0) logger.info("Subsequent test of Voi get_min_max method, as it modifies the object") s_min, s_max = v.get_min_max() self.assertIsNotNone(s_min) self.assertIsNotNone(s_max) # TODO check why get_min_max returns tuple, not a number self.assertEqual(s_max[2], 18.0) self.assertEqual(s_min[2], 3.0) logger.info("Test of Voi get_2d_slice method (sagittal)") s2 = v.get_2d_slice(plane=pt.Voi.sagittal, depth=10.0) self.assertIsNotNone(s2) logger.info("Test of Voi get_2d_slice method (coronal)") s3 = v.get_2d_slice(plane=pt.Voi.coronal, depth=5.0) self.assertIsNotNone(s3) logger.info("Test of Voi get_2d_projection_on_basis method") v.get_2d_projection_on_basis(basis=((1, 0, 0), (0, 2, 0))) logger.info("Test of Voi create_point_tree method") v.create_point_tree() self.assertIsNotNone(v.points) self.assertEqual(len(v.points), 496) logger.info("Test of Voi get_row_intersections method") isec = v.get_row_intersections(pos=(10, 10, 9)) self.assertIsNotNone(isec) self.assertEqual(len(isec), 2) logger.info("Test of Voi get_voi_cube method") vc = v.get_voi_cube() self.assertIsNotNone(vc) center_pos = v.calculate_center() self.assertAlmostEqual(center_pos[0], 10.0)