package edu.stanford.rsl.conrad.phantom; import edu.stanford.rsl.conrad.geometry.shapes.simple.Cylinder; import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND; import edu.stanford.rsl.conrad.geometry.shapes.simple.Sphere; import edu.stanford.rsl.conrad.physics.PhysicalObject; import edu.stanford.rsl.conrad.physics.materials.database.MaterialsDB; import edu.stanford.rsl.conrad.utils.CONRAD; import edu.stanford.rsl.conrad.utils.DoubleArrayUtil; import edu.stanford.rsl.jpop.utils.UserUtil; /** * Phantom to test forward and back projection resolution. * * Creates seven small beads of high contrast at several locations at the boundary of a water cylinder. * In the middle of the water cylinder, there is another cylinder representing bones. * The material of the beads is set to Plexiglass (density of 1.95). * * * @author Martin Berger * */ public class BeadRemovalPhantom extends AnalyticPhantom { /** * */ private static final long serialVersionUID = 572931430014588123L; int noOfBeads = 8; double beadRadius = 3; double beadZRangebegin = 0.05; double beadZRangeend = 0.95; double outerCylRadius = 100; double innerCylRadius = 40; double cylHeight = 200; @Override public String getBibtexCitation() { return CONRAD.CONRADBibtex; } @Override public String getMedlineCitation() { return CONRAD.CONRADMedline; } @Override public String getName() { return "Bead Removal Test Phantom"; } @Override public void configure() { try { noOfBeads = UserUtil.queryInt("Number Of Beads", noOfBeads); beadRadius = UserUtil.queryDouble("Bead radius", beadRadius); outerCylRadius = UserUtil.queryDouble("Radius of the outer cylinder", outerCylRadius); innerCylRadius = UserUtil.queryDouble("Radius of the inner cylinder", innerCylRadius); cylHeight = UserUtil.queryDouble("Height of the cylinder", cylHeight); buildPhantom(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public double giveRandomZBeadPosition(double[] zlimits){ double[] minMax = DoubleArrayUtil.minAndMaxOfArray(zlimits); double out = Math.random()*(minMax[1]-minMax[0])+minMax[0]; return out; } public double giveRandomAngle(double[] angleLimits){ return giveRandomZBeadPosition(angleLimits); } protected void buildPhantom(){ Cylinder s = new Cylinder(outerCylRadius, outerCylRadius, cylHeight); s.setName("Water Cylinder"); PhysicalObject po = new PhysicalObject(); po.setMaterial(MaterialsDB.getMaterialWithName("Water")); // D = 1.95 po.setShape(s); add(po); s = new Cylinder(innerCylRadius, innerCylRadius, cylHeight); s.setName("Bone Cylinder"); po = new PhysicalObject(); po.setMaterial(MaterialsDB.getMaterialWithName("Femur")); // D = 1.95 po.setShape(s); add(po); s = new Cylinder(0.9*innerCylRadius, 0.9*innerCylRadius, cylHeight); s.setName("Bone Marrow Cylinder"); po = new PhysicalObject(); po.setMaterial(MaterialsDB.getMaterialWithName("BoneMarrow")); // D = 1.95 po.setShape(s); add(po); double beadPosRadius = outerCylRadius+0.8*beadRadius; double alpha = 0; double zInc = 0; double alphaInc = 0; double zpos = cylHeight*beadZRangebegin - cylHeight/2; if (noOfBeads > 1){ alphaInc = (2*Math.PI)/(noOfBeads-1); zInc = (beadZRangeend-beadZRangebegin)*cylHeight/(noOfBeads-1); } for (int i = 0; i < noOfBeads; i++) { PointND center = new PointND(Math.cos(alpha)*beadPosRadius, Math.sin(alpha)*beadPosRadius,zpos); // the bead Sphere sp = new Sphere(beadRadius, center); sp.setName("High Constrast Bead"); po = new PhysicalObject(); po.setMaterial(MaterialsDB.getMaterialWithName("SS304")); // D = 1.95 po.setShape(sp); add(po); alpha += alphaInc; zpos += zInc; } } public BeadRemovalPhantom() { } } /* * Copyright (C) 2010-2014 Martin Berger * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */