/* * Copyright (C) 2010-2014 Rotimi X Ojo, Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.conrad.physics.materials.utils; import java.util.Iterator; import java.util.TreeMap; import edu.stanford.rsl.conrad.numerics.SimpleVector; import edu.stanford.rsl.conrad.physics.materials.database.ElementalMassAttenuationData; import edu.stanford.rsl.conrad.physics.materials.database.FormulaToNameMap; import edu.stanford.rsl.conrad.utils.interpolation.NumberInterpolatingTreeMap; /** * Calculates the mass attenuation coefficient of a material given its formula or weighted atomic composition. * @see WeightedAtomicComposition * @author Rotimi X Ojo */ public class LocalMassAttenuationCalculator { private static final TreeMap<String, TreeMap<AttenuationType, NumberInterpolatingTreeMap> > cache = new TreeMap<String, TreeMap<AttenuationType,NumberInterpolatingTreeMap>>(); /** * Calculates the mass attenuation coefficient of a material given its formula * @param formula is the chemical formula of the material * @param energy is the energy of interest * @param attType is the {@link AttenuationType} of interest * @return the mass attenuation coefficient of a material given its formula */ public static double getMassAttenuationData(String formula, double energy, AttenuationType attType) { return getMassAttenuationData(new WeightedAtomicComposition(formula), energy, attType); } /** * Calculates the mass attenuation coefficient of a material given its formula * @param formula is the chemical formula of the material * @param energies is the set of energy of interest * @param attType is the {@link AttenuationType} of interest * @return the mass attenuation coefficient of a material given its formula */ public static NumberInterpolatingTreeMap getMassAttenuationData(String formula, double [] energies, AttenuationType attType) { NumberInterpolatingTreeMap num = new NumberInterpolatingTreeMap(); for(double energy:energies){ num.put(energy, getMassAttenuationData(new WeightedAtomicComposition(formula), energy, attType)); } return num; } /** * Calculates the mass attenuation coefficient of a material given its {@link WeightedAtomicComposition} * @param comp is the weighted atomic composition of the material * @param energies is the set of energy of interest * @param attType is the {@link AttenuationType} of interest * @return the mass attenuation coefficient of a material given its formula */ public static NumberInterpolatingTreeMap getMassAttenuationData(WeightedAtomicComposition comp, double [] energies, AttenuationType attType) { NumberInterpolatingTreeMap num = new NumberInterpolatingTreeMap(); for(double energy:energies){ num.put(energy, getMassAttenuationData(comp, energy, attType)); } return num; } /** * Calculates the mass attenuation coefficient of a material given its weighted atomic composition. * This method uses an internal static cache to inhibit excessive file access. However, this * requires the method to be synchronized. This may lead to quite slow performance in parallel use. * * @param comp is the {@link WeightedAtomicComposition} of the material * @param energy is the energy of interest * @param attType is the {@link AttenuationType} of interest * @return the mass attenuation coefficient of a material given its weighted atomic composition. */ public static synchronized double getMassAttenuationData(WeightedAtomicComposition comp, double energy, AttenuationType attType) { SimpleVector vec = getNormalizedComposition(comp); Iterator<String> it = comp.keysIterator(); double value = 0; int counter = 0; while(it.hasNext()){ TreeMap<AttenuationType, NumberInterpolatingTreeMap> massAtt = null; String name = FormulaToNameMap.getName(it.next()); if((massAtt = cache.get(name))== null){ massAtt= ElementalMassAttenuationData.get(name); cache.put(name, massAtt); } double buff = massAtt.get(attType).interpolateValue(energy).doubleValue(); value+=vec.getElement(counter)* buff; counter++; } return value; } private static SimpleVector getNormalizedComposition(WeightedAtomicComposition comp) { SimpleVector vec = new SimpleVector(comp.size()); Iterator<Double> it = comp.valuesIterator(); int i =0; double sum = 0; while(it.hasNext()){ vec.setElementValue(i, it.next()); sum+=vec.getElement(i); i++; } vec.divideBy(sum); return vec; } }