Exemple #1
0
    def post_process(self):
        phys_dose = None
        bio_dose = None
        dose_mean_let = None
        temp_dos = None
        for projectile in self.projectiles:
            name = os.path.join(
                self.path,
                self.plan_name) + "_" + self.projectiles[projectile]["name"]
            factor = float(self.projectile_dose_level[projectile]) / 1000
            factor = 1
            if os.path.exists(name +
                              ".bio.dos") and self.plan.get_out_bio_dose():
                path = os.path.join(name + ".bio.dos")
                temp = DosCube()
                temp.read(path)
                temp *= factor
                if self.mult_proj:
                    self.plan.add_dose(temp, "bio_%s" % projectile)
                if bio_dose is None:
                    bio_dose = temp
                else:
                    bio_dose += temp

            if os.path.exists(name +
                              ".phys.dos") and self.plan.get_out_phys_dose():
                path = os.path.join(name + ".phys.dos")
                temp_dos = DosCube()
                temp_dos.read(path)
                temp_dos *= factor
                if self.mult_proj:
                    self.plan.add_dose(temp_dos, "phys_%s" % projectile)
                if phys_dose is None:
                    phys_dose = temp_dos
                else:
                    phys_dose += temp_dos
            if os.path.exists(name + ".dosemlet.dos"
                              ) and self.plan.get_out_dose_mean_let():

                path = os.path.join(name + ".dosemlet.dos")
                temp = LETCube()
                temp.read(path)
                if not self.mult_proj:
                    dose_mean_let = temp
                else:
                    if dose_mean_let is None:
                        dose_mean_let = temp * temp_dos
                    else:
                        dose_mean_let = dose_mean_let + temp * temp_dos
        out_path = os.path.join(self.path, self.plan_name)
        if bio_dose is not None:
            bio_dose.write(out_path + ".bio.dos")
        if phys_dose is not None:
            phys_dose.write(out_path + ".phys.dos")
        if dose_mean_let is not None:
            if self.mult_proj:
                dose_mean_let /= phys_dose

            dose_mean_let.write(out_path + ".hed")
Exemple #2
0
    def create_trip_exec_simple(self, no_output=False):
        """
        Generates the .exec script and stores it into self.trip_exec.
        """
        logger.info("Generating the trip_exec script...")
        oar_list = self.oar_list
        targets = self.targets
        fields = self.plan.get_fields()

        projectile = fields[0].get_projectile()
        output = []
        output.extend(self.create_exec_header())
        output.extend(self.create_exec_load_data_files(projectile))
        output.extend(self.create_exec_field(fields))
        output.extend(self.create_exec_oar(oar_list))
        dosecube = None
        if len(targets) > 1:
            dosecube = DosCube(self.images)
            for i, voi in enumerate(targets):
                temp = DosCube(self.images)
                dose_level = int(voi.get_dose() / self.target_dose * 1000)
                if dose_level == 0:
                    dose_level = -1
                temp.load_from_structure(voi.get_voi().get_voi_data(),
                                         dose_level)
                if i == 0:
                    dosecube = temp * 1
                else:
                    dosecube.merge_zero(temp)
            dosecube.cube[dosecube.cube == -1] = int(0)

        if not self.plan.get_target_dose_cube() is None:
            dosecube = self.plan.get_target_dose_cube()

        if dosecube is not None:
            if not no_output:
                dosecube.write(os.path.join(self.path, "target_dose.dos"))
            output.extend(self.create_exec_plan(incube="target_dose"))
        else:
            output.extend(self.create_exec_plan())
        if self.plan.get_optimize():
            output.extend(self.create_exec_opt())

        name = self.plan_name
        output.extend(self.create_exec_output(name, fields))
        out = "\n".join(output) + "\nexit\n"
        self.trip_exec = out
Exemple #3
0
 def load_dose(self, path, _type, target_dose=0.0):
     """ Load and append a new DosCube from path to self.doscubes.
     """
     dos = DosCube()
     dos.read(os.path.splitext(path)[0] + DosCube.data_file_extension)
     dos._type = _type
     dos.target_dose = target_dose
     self.dosecubes.append(dos)
Exemple #4
0
    def test_dicom_plan(self):
        c = DosCube()
        c.read(self.cube000)

        dp = c.create_dicom_plan()
        self.assertIsNotNone(dp)

        d = c.create_dicom()
        self.assertIsNotNone(d)
Exemple #5
0
    def analyse_cube(self):
        keys = self.projectiles.keys()

        p1 = self.projectiles[keys[0]]
        p2 = self.projectiles[keys[1]]

        cube1 = p1["target_dos"]
        cube2 = p2["target_dos"]

        if not self.cube_in_other_cube(cube1, cube2):
            temp = p1
            p1 = p2
            p2 = temp
            cube1 = p1["target_dos"]
            cube2 = p2["target_dos"]
            self.execute_order = [keys[0], keys[1]]
            self.split_proj_key = keys[1]

        else:
            self.execute_order = [keys[1], keys[0]]
            self.split_proj_key = keys[0]

        target_cube = copy.deepcopy(cube1)
        shadow_cubes = []
        for i, field in enumerate(p1["fields"]):
            d = DosCube(cube1)

            basis = get_basis_from_angles(field.get_gantry(),
                                          field.get_couch())
            basis = basis[0]
            basis = np.array([
                basis[0] / cube1.pixel_size, basis[1] / cube1.pixel_size,
                basis[2] / cube1.slice_distance
            ])
            basis /= np.max(np.abs(basis))

            d.cube = pytriplib.create_field_shadow(
                cube1.cube, cube2.cube, np.array(basis, dtype=np.double))
            target_cube -= d
            shadow_cubes.append(d)

        target_cube.cube[target_cube.cube < 0] = 0
        cube2.cube = cube2.cube + target_cube.cube
        # ~ cube2.cube = pytriplib.extend_cube(cube2.cube)
        cube1.cube = cube1.cube - target_cube.cube
        if len(p1["fields"]) == 2:
            a = self.execute_order.pop(1)
            b = self.projectile_dose_level[a]
            self.execute_order.append(a + str(1))
            self.execute_order.append(a + str(2))
            self.projectile_dose_level[a + str(1)] = b
            self.projectile_dose_level[a + str(2)] = b
Exemple #6
0
    def test_write_dicom(self):
        c = DosCube()
        c.read(self.cube000)

        outdir = tempfile.mkdtemp()
        c.write_dicom(outdir)
        self.assertTrue(os.path.exists(os.path.join(outdir, "rtdose.dcm")))
        self.assertTrue(os.path.exists(os.path.join(outdir, "rtplan.dcm")))
        self.assertGreater(os.path.getsize(os.path.join(outdir, "rtdose.dcm")),
                           0)
        self.assertGreater(os.path.getsize(os.path.join(outdir, "rtplan.dcm")),
                           0)
        shutil.rmtree(outdir)
Exemple #7
0
 def calculate_rest_dose(self, proj):
     self.rest_dose = copy.deepcopy(self.target_dos)
     for k, projectile in self.projectiles.items():
         if k == proj:
             continue
         name = os.path.join(self.path,
                             self.plan_name) + "_" + projectile["name"]
         path = os.path.join(name + ".phys.dos")
         if os.path.exists(path):
             temp = DosCube()
             temp.read(path)
             temp = temp
             self.rest_dose.cube = self.rest_dose.cube - temp.cube
Exemple #8
0
    def test_read(self):
        c = DosCube()
        c.read(self.cube000)
        self.assertEqual(c.cube.shape[0], 300)
        self.assertEqual(c.cube.shape[1], 512)
        self.assertEqual(c.cube.shape[2], 512)

        # test method from C extension
        dose_center = pytriplib.calculate_dose_center(np.array(c.cube))
        self.assertEqual(dose_center.shape[0], 3)
        self.assertGreater(dose_center[0], 0.0)
        self.assertGreater(dose_center[1], 0.0)
        self.assertGreater(dose_center[2], 0.0)
Exemple #9
0
    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)
Exemple #10
0
    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)
Exemple #11
0
    def get_voi_cube(self):
        """
        This method returns a DosCube object with value 1000 in each voxel within the Voi and zeros elsewhere.
        It can be used as a mask, for selecting certain voxels.
        The function may take some time to execute the first invocation, but is faster for subsequent calls,
        due to caching.

        :returns: a DosCube object which holds the value 1000 in those voxels which are inside the Voi.
        """
        if hasattr(self, "voi_cube"):  # caching: checks if class has voi_cube attribute
            # TODO: add parameter as argument to this function. Note, this needs to be compatible with
            # caching the cube. E.g. the method might be called twice with different arguments.
            return self.voi_cube
        self.voi_cube = DosCube(self.cube)
        self.voi_cube.load_from_structure(self, 1000)
        return self.voi_cube
Exemple #12
0
    def _finish(self, plan):
        """ return requested results, copy them back in to plan._working_dir
        """

        for _file_name in plan._out_files:
            _path = os.path.join(plan._temp_dir, _file_name)

            # only copy files back, if we actually have been running TRiP
            if self._norun:
                logger.info("dummy run: would now copy {:s} to {:s}".format(
                    _path, plan._working_dir))
            else:
                logger.info("copy {:s} to {:s}".format(_path,
                                                       plan._working_dir))
                shutil.copy(_path, plan._working_dir)

        for _file_name in plan._out_files:
            _path = os.path.join(plan._temp_dir, _file_name)
            if ".phys.dos" in _file_name:
                _ctx_cube = DosCube()
                if not self._norun:
                    _ctx_cube.read(_path)
                    plan.dosecubes.append(_ctx_cube)

            if ".bio.dos" in _file_name:
                _ctx_cube = CtxCube()
                if not self._norun:
                    _ctx_cube.read(_path)
                    plan.dosecubes.append(_ctx_cube)

            if ".dosemlet.dos" in _file_name:
                _let_cube = LETCube()
                if not self._norun:
                    _let_cube.read(_path)
                    plan.letcubes.append(_let_cube)

            if ".rst" in _file_name:
                logger.warning(
                    "attaching fields to class not implemented yet {:s}".
                    format(_path))
                # TODO
                # need to access the RstClass here for each rst file. This will then need to be attached
                # to the proper field in the list of fields.

        if self._cleanup:
            logger.debug("Delete {:s}".format(plan._temp_dir))
            shutil.rmtree(plan._temp_dir)
Exemple #13
0
    def test_write(self):
        c = DosCube()
        c.read(self.cube000)

        fd, outfile = tempfile.mkstemp()
        os.close(fd)  # Windows needs it
        os.remove(outfile)  # we need only temp filename, not the file
        c.write(outfile)
        hed_file = outfile + ".hed"
        dos_file = outfile + ".dos"
        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)
Exemple #14
0
    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)
Exemple #15
0
    def split_fields(self, proj):
        if self.split_proj_key not in self.projectiles.keys():
            return
        name = os.path.join(
            self.path, self.plan_name) + "_" + self.projectiles[proj]["name"]
        path = os.path.join(name + ".phys.dos")
        temp = DosCube()
        temp.read(path)
        temp.version = "2.0"

        self.rest_dose = self.target_dos - temp

        p = self.projectiles[self.split_proj_key]
        p["target_dos"].cube = pytriplib.extend_cube(p["target_dos"].cube)
        if len(p["fields"]) == 2:
            temp.cube = (temp.cube < self.projectiles[proj]["target_dos"].cube) * \
                self.projectiles[proj]["target_dos"].cube + \
                (temp.cube > self.projectiles[proj]["target_dos"].cube) * temp.cube
            dose = self.target_dos - temp
            field1 = p["fields"][0]
            field2 = p["fields"][1]
            d1 = DosCube(temp)
            d2 = DosCube(temp)
            center = pytriplib.calculate_dose_center(p["target_dos"].cube)

            dose.cube[dose.cube < 0] = 0

            temp.cube *= self.target_dos.cube > 0

            basis = get_basis_from_angles(field1.get_gantry(),
                                          field1.get_couch())[0]
            basis = np.array([
                basis[0] / dose.pixel_size, basis[1] / dose.pixel_size,
                basis[2] / dose.slice_distance
            ])
            basis = basis / np.max(np.abs(basis)) * .5
            d1.cube = pytriplib.create_field_shadow(
                dose.cube, temp.cube, np.array(basis, dtype=np.double))
            basis = get_basis_from_angles(field2.get_gantry(),
                                          field2.get_couch())[0]
            basis = np.array([
                basis[0] / dose.pixel_size, basis[1] / dose.pixel_size,
                basis[2] / dose.slice_distance
            ])
            basis /= np.max(np.abs(basis))
            d2.cube = pytriplib.create_field_shadow(
                dose.cube, temp.cube, np.array(basis, dtype=np.double))
            a = d2.cube > d1.cube
            b = d2.cube < d1.cube
            d2.cube = p["target_dos"].cube * a
            d1.cube = p["target_dos"].cube * b

            rest = p["target_dos"].cube * ((a + b) < 1)

            b = pytriplib.split_by_plane(rest, center, basis)
            d1.cube += b
            d2.cube += rest - b
            self.plan.add_dose(d1, "H1")
            self.plan.add_dose(d2, "H2")

            self.projectiles[field1.get_projectile() + str(1)] = {
                "target_dos": d1,
                "fields": [field1],
                "name": field1.get_projectile() + str(1),
                "projectile": field1.get_projectile()
            }
            self.projectiles[field2.get_projectile() + str(2)] = {
                "target_dos": d2,
                "fields": [field2],
                "name": field2.get_projectile() + str(2),
                "projectile": field2.get_projectile()
            }
            del self.projectiles[self.split_proj_key]
Exemple #16
0
 def load_dose(self, path, t, target_dose=0.0):
     dos = DosCube()
     dos.read(os.path.splitext(path)[0] + ".dos")
     d = DoseCube(dos, t)
     d.set_dose(target_dose)
     self.add_dose(d)
Exemple #17
0
    def split_plan(self, plan=None):
        self.targets = []
        self.oar_list = []

        dose = 0
        for voi in self.plan.get_vois():
            if voi.is_oar():
                self.oar_list.append(voi)
            if voi.is_target():
                self.targets.append(voi)
                if voi.get_dose() > dose:
                    dose = voi.get_dose()
        if not len(self.targets):
            raise InputError("No targets")
        if not len(self.plan.get_fields()):
            raise InputError("No fields")
        self.target_dose = dose
        if plan is None:
            plan = self.plan
        proj = []
        self.projectile_dose_level = {}
        for field in plan.fields:
            if field.get_projectile() not in proj:
                proj.append(field.get_projectile())
                self.projectile_dose_level[field.get_projectile()] = 0

        if len(proj) > 1:
            self.mult_proj = True
        else:
            self.mult_proj = False

        if self.mult_proj:
            self.projectiles = {}
            for field in plan.fields:
                if field.get_projectile() not in self.projectiles.keys():
                    self.projectiles[field.get_projectile()] = {
                        "target_dos": DosCube(self.images),
                        "fields": [field],
                        "name": field.get_projectile(),
                        "projectile": field.get_projectile()
                    }
                else:
                    self.projectiles[field.get_projectile()]["fields"].append(
                        field)

            self.target_dos = DosCube(self.images)

            for i, voi in enumerate(self.targets):
                temp = DosCube(self.images)
                voi_dose_level = int(voi.get_dose() / dose * 1000)
                temp.load_from_structure(voi.get_voi().get_voi_data(), 1)
                for projectile, data in self.projectiles.items():
                    dose_percent = self.plan.get_dose_percent(projectile)
                    if not voi.get_dose_percent(projectile) is None:
                        dose_percent = voi.get_dose_percent(projectile)
                    proj_dose_lvl = int(voi.get_dose() / self.target_dose *
                                        dose_percent * 10)
                    if self.projectile_dose_level[projectile] < proj_dose_lvl:
                        self.projectile_dose_level[projectile] = proj_dose_lvl
                    if proj_dose_lvl == 0:
                        proj_dose_lvl = -1
                    if i == 0:
                        data["target_dos"] = temp * proj_dose_lvl
                    else:
                        data["target_dos"].merge_zero(temp * proj_dose_lvl)
                if i == 0:
                    self.target_dos = temp * voi_dose_level
                else:
                    self.target_dos.merge_zero(temp * voi_dose_level)
            for projectile, data in self.projectiles.items():
                data["target_dos"].cube[data["target_dos"].cube == -1] = int(0)
                self.plan.add_dose(data["target_dos"],
                                   "target_%s" % projectile)
            self.rest_dose = copy.deepcopy(self.target_dos)