content: /*
   * Copyright (C) 2010-2014 Andreas Maier
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */
  package edu.stanford.rsl.conrad.phantom;
  
  import edu.stanford.rsl.conrad.geometry.General;
  import edu.stanford.rsl.conrad.geometry.Rotations;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Ellipsoid;
  import edu.stanford.rsl.conrad.geometry.transforms.ComboTransform;
  import edu.stanford.rsl.conrad.geometry.transforms.ScaleRotate;
  import edu.stanford.rsl.conrad.geometry.transforms.Translation;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  import edu.stanford.rsl.conrad.physics.PhysicalObject;
  import edu.stanford.rsl.conrad.physics.materials.Material;
  import edu.stanford.rsl.conrad.physics.materials.database.MaterialsDB;
  
  /**
   * 3-D definition of the Shepp-Logan Phantom. The center slice is identical to the original publication
   * of Shepp and Logan. The third dimension was created by the taking the minimal extent of the x- and y-directions.
   * <br><br><b>Be careful when using this phantom and have a look at <a href=http://lists.fau.de/pipermail/project-conrad/2014-October/000054.html>this comment</a> on the CONRAD mailing list</b>
   * @author Happy Coding Seminar
   *
   */
  public class SheppLoganPhantom extends AnalyticPhantom {
  
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = 5781085850910993618L;
  
  	@Override
  	public String getBibtexCitation() {
  		String bibtex = "@Article{Shepp74-TFR,\n" +
  		"  author = {{Shepp}, L. A. and {Logan}, B. F.},\n" +
  		"  title = {{The Fourier reconstruction of a head section}},\n" +
  		"  journal = {IEEE Transactions on Nuclear Science},\n" +
  		"  volume = {21},\n" +
  		"  pages = {21-43},\n" +
  		"  year = {1974}\n" +
  		"}";
  		return bibtex;
  	}
  
  	@Override
  	public String getMedlineCitation() {
  		return "Shepp LA, Logan BF. The Fourier reconstruction of a head section. IEEE Transactions on nuclear science 21:21-43. 1974";
  	}
  
  
  	@Override
  	public String getName() {
  		return "Shepp Logan Phantom (Adapted)";
  	}
  
  	public SheppLoganPhantom() {
  		float scalingFactor = 100;
  		ScaleRotate scaling = new ScaleRotate(new SimpleMatrix("[[1 0 0];[0 1 0];[0 0 1]]").multipliedBy(scalingFactor));
  		// Body of the phantom.
  		Ellipsoid a = new Ellipsoid(.69, .92, .69);
  		Ellipsoid b = new Ellipsoid(.6624, .874, .6624);
  		Ellipsoid c = new Ellipsoid(.11, .31, .11);
  		Ellipsoid d = new Ellipsoid(.16, .41, .16);
  		Ellipsoid e = new Ellipsoid(.21, .25, .21);
  		Ellipsoid f = new Ellipsoid(.046, .046, .046);
  		Ellipsoid g = new Ellipsoid(.046, .046, .046);
  		Ellipsoid h = new Ellipsoid(.046, .023, .023);
  		Ellipsoid i = new Ellipsoid(.023, .023, .023);
  		Ellipsoid j = new Ellipsoid(.023, .046, .023);
  
  		a.applyTransform(scaling);
  		b.applyTransform(new ComboTransform(new Translation(new SimpleVector(0, -.0184, 0)), scaling));
  		c.applyTransform(new ComboTransform(new ScaleRotate(Rotations.createBasicZRotationMatrix(General.toRadians(-18))),
  											new Translation(new SimpleVector(.22, 0, 0)),
  											scaling));
  		d.applyTransform(new ComboTransform(new ScaleRotate(Rotations.createBasicZRotationMatrix(General.toRadians(18))),
  											new Translation(new SimpleVector(-.22, 0, 0)),
  											scaling));
  		e.applyTransform(new ComboTransform(new Translation(new SimpleVector(0, .35, 0)), scaling));
  		f.applyTransform(new ComboTransform(new Translation(new SimpleVector(0, .1, 0)), scaling));
  		g.applyTransform(new ComboTransform(new Translation(new SimpleVector(0, -.1, 0)), scaling));
  		h.applyTransform(new ComboTransform(new Translation(new SimpleVector(-.08, -.605, 0)), scaling));
  		i.applyTransform(new ComboTransform(new Translation(new SimpleVector(0, -.605, 0)), scaling));
  		j.applyTransform(new ComboTransform(new Translation(new SimpleVector(.06, -.605, 0)), scaling));
  
  		PhysicalObject po;
  		Material water = MaterialsDB.getMaterial("water");
  		po = new PhysicalObject();
  		Material mat = (Material) water.clone();
  		mat.setDensity(2.0);
  		po.setMaterial(mat);
  		po.setShape(a);
  		add(po);
  		
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(2.0-.98);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(b);
  		add(po);
  		
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.0-.02);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(c);
  		add(po);
  		
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.0-.02);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(d);
  		add(po);
  		
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.01);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(e);
  		add(po);
  
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.01);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(f);
  		add(po);
  
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.01);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(g);
  		add(po);
  
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.01);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(h);
  		add(po);
  
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.01);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(i);
  		add(po);
  
  		po = new PhysicalObject();
  		mat = (Material) water.clone();
  		mat.setDensity(1.01);
  		po.setMaterial(mat); // D = 1.95
  		po.setShape(j);
  		add(po);
  
  	}
  }
  