package edu.stanford.rsl.conrad.physics.materials; import java.io.Serializable; import java.util.ArrayList; import edu.stanford.rsl.conrad.physics.Constants; import edu.stanford.rsl.conrad.physics.materials.database.CompositionToAbsorptionEdgeMap; import edu.stanford.rsl.conrad.physics.materials.database.OnlineMassAttenuationDB; import edu.stanford.rsl.conrad.physics.materials.materialsTest.TestMassAttenuationData; import edu.stanford.rsl.conrad.physics.materials.utils.AttenuationRetrievalMode; import edu.stanford.rsl.conrad.physics.materials.utils.AttenuationType; import edu.stanford.rsl.conrad.physics.materials.utils.LocalMassAttenuationCalculator; import edu.stanford.rsl.conrad.physics.materials.utils.WeightedAtomicComposition; /** * <p>This class models an arbitrary material. Materials are defined by density and their characteristic attenuation of XRays of different energies.</p> * <p> Note. A material without a defined energy dependent attenuation cannot be used in polychromatic XRay projection modeling</p>. * @author Rotimi X Ojo */ public class Material implements Serializable, Cloneable{ private static final long serialVersionUID = -335499247531855579L; private String name = ""; private double density = -1; private transient double CTValue = 0; private WeightedAtomicComposition comp; public Material(){} /** * Initializes a material with a given density. To support polychromatic absorption, an energy dependent attenuation TreeMap must be provided. * @param density is density of initialized material */ public Material(double density){ setDensity(density); } public Material(Material material) { this.name = new String(material.name); this.density = material.density; this.CTValue = material.CTValue; // shallow copy of composition tree! this.comp = material.comp; } /** * Update the name of the material. * @param name is name of material */ public void setName(String name) { this.name = name; } /** * Retrieve the name of the material * @return the name of the material */ public String getName() { return name; } /** * Retrieve the CT value of a given material in [HU] * @return 0 if CTValue is not available */ public double getCTValue() { return CTValue; } /** * Retrieve the energy dependent attenuation of material * @param energy is energy of interest in KeV * @param attType is type of attenuation, all types of attenuation are supported. * @return double representing the energy dependent attenuation of material sourced locally in [cm^-1]. * @see AttenuationType * @see TestMassAttenuationData */ public double getAttenuation(double energy, AttenuationType attType) { return getAttenuation(energy, attType, AttenuationRetrievalMode.LOCAL_RETRIEVAL); } /** * Retrieve the energy dependent attenuation of material. * @param energy is energy of interest in KeV * @param attType is type of attenuation, all types of attenuation are supported. * @param mode is retrieval mode. * @return is type of attenuation, all types of attenuation are supported. * @see AttenuationType * @see AttenuationRetrievalMode * @see TestMassAttenuationData */ public double getAttenuation(double energy, AttenuationType attType, AttenuationRetrievalMode mode){ if(mode.equals(AttenuationRetrievalMode.ONLINE_RETRIEVAL)){ return density * OnlineMassAttenuationDB.getMassAttenuationData(comp, energy/1000, attType); }else{ return density * LocalMassAttenuationCalculator.getMassAttenuationData(comp, energy/1000, attType); } } /** * Update the density and CT Value of the material with given value * @param density is density of the material */ public void setDensity(double density) { this.density = density; CTValue = Constants.computeCTValue(density); } /** * Retrieves the density of the material in [g/cm^3] * @return -1 if density is not available */ public double getDensity() { return density; } /** * Update the atomic composition of material by mass * @param comp is Treemap containing the atomic composition of material by mass */ public void setWeightedAtomicComposition(WeightedAtomicComposition comp){ this.comp = comp; } /** * Retrieve the atomic composition of material by mass * @return null if atomic composition table is not available */ public WeightedAtomicComposition getWeightedAtomicComposition(){ return comp; } /** * Retrieve all the absorption edges of material in MeV. * @return an empty array if there are no absorption edge */ public ArrayList<Double> getAbsorptionEdges(){ return CompositionToAbsorptionEdgeMap.getAbsorptionEdges(comp); } /** * Materials are hashed by their name. * @return the hash code of the material name. */ public int hashCode(){ return getName().hashCode(); } @Override public boolean equals(Object other){ if (other instanceof Material) return getName().equals(((Material)other).getName()); else return false; } /** * Materials are equal if they have the same name. * @param other the other material * @return true if name is the same. */ public boolean equals(Material other){ return getName().equals(other.getName()); } @Override public String toString(){ return name; } @Override public Material clone(){ return new Material(this); } } /* * Copyright (C) 2010-2014 Rotimi X Ojo * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */