/*-
* Copyright 2015 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.xpdf;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Collections;
//import java.util.List;
//import java.util.Scanner;
//
//import org.apache.commons.lang.ArrayUtils;
//import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
//import org.apache.commons.math3.analysis.interpolation.SplineInterpolator;
/**
* A class to return the XCOM X-ray cross sections for an element.
* <p>
* Constructed from an XCOM data file, each object can return any of the XCOM
* cross-sections at a given energy. The possible cross sections are:
* <ul>
* <li>Coherent scattering
* <li>Incoherent scattering
* <li>photoelectric absorption
* <li>nuclear pair production
* <li>electronic pair production
* <li>total cross-section
* <li>total cross-section without coherent scattering
* <p>
* Each of these may be accessed by its own method, or by a master method which
* also takes the name of the requested cross-section.
*
* @author Timothy Spain timothy.spain@diamond.ac.uk
* @since 2014-09-28
*
*/
//public class XCOMElement {
//
// private static final int nEnergiesXCom = 80;
// @SuppressWarnings("unused")
// private int atomicNumber;
// private double atomicMass;
// private int nEdges;
// private int nEnergies;
// private List<Integer> edgeIndices;
// // Don't care about edge names
// private List<Double> edgeEnergies;
// private List<Double> energies;
// private List<Double> logEnergies;
// private List<Double> coherentScatteringSigma;
// private List<Double> incoherentScatteringSigma;
// private List<Double> photoelectricSigma;
// private List<Double> nuclearPairSigma;
// private List<Double> electronPairSigma;
// private List<Integer> edgeMulitplicity; // TODO: more descriptive name
// private List<List<Double>> edgeData1; // TODO: more descriptive name
// private List<List<Double>> edgeData2; // TODO: more descriptive name
// /**
// * Default constructor.
// */
// public XCOMElement() {
// this.nEdges = 0;
// this.nEnergies = nEnergiesXCom + nEdges*2;
// this.edgeIndices = new ArrayList<Integer>();
// this.edgeEnergies = new ArrayList<Double>();
// this.energies = Arrays.asList(1.0E+00,1.5E+00,2.0E+00,3.0E+00,4.0E+00,5.0E+00,
// 6.0E+00,8.0E+00,1.0E+01,1.5E+01,2.0E+01,3.0E+01,4.0E+01,
// 5.0E+01,6.0E+01,8.0E+01,1.0E+02,1.5E+02,2.0E+02,3.0E+02,
// 4.0E+02,5.0E+02,6.0E+02,8.0E+02,1.0E+03,1.022E+03,1.25E+03,
// 1.5E+03,2.0E+03,2.044E+03,3.0E+03,4.0E+03,5.0E+03,6.0E+03,
// 7.0E+03,8.0E+03,9.0E+03,1.0E+04,1.1E+04,1.2E+04,1.3E+04,
// 1.4E+04,1.5E+04,1.6E+04,1.8E+04,2.0E+04,2.2E+04,2.4E+04,
// 2.6E+04,2.8E+04,3.0E+04,4.0E+04,5.0E+04,6.0E+04,8.0E+04,
// 1.0E+05,1.5E+05,2.0E+05,3.0E+05,4.0E+05,5.0E+05,6.0E+05,
// 8.0E+05,1.0E+06,1.5E+06,2.0E+06,3.0E+06,4.0E+06,5.0E+06,
// 6.0E+06,8.0E+06,1.0E+07,1.5E+07,2.0E+07,3.0E+07,4.0E+07,
// 5.0E+07,6.0E+07,8.0E+07,1.0E+08);
// this.logEnergies = new ArrayList<Double>();
// for (double energy : this.energies) this.logEnergies.add(Math.log(energy));
// this.coherentScatteringSigma = new ArrayList<Double>();
// this.incoherentScatteringSigma = new ArrayList<Double>();
// this.photoelectricSigma = new ArrayList<Double>();
// this.nuclearPairSigma = new ArrayList<Double>();
// this.electronPairSigma = new ArrayList<Double>();
// this.edgeMulitplicity = new ArrayList<Integer>();
// this.edgeData1 = new ArrayList<List<Double>>();
// this.edgeData2 = new ArrayList<List<Double>>();
// }
//
// /**
// * Constructor from atomic number.
// */
// public XCOMElement(int atomicZ) {
//
// String rawData = XCOMData.get(atomicZ);
// Scanner s = new Scanner(rawData);
// // Line 1: atomic number and mass
// this.atomicNumber = s.nextInt();
// this.atomicMass = s.nextDouble();
// // Line 2: number of edges, number of energy samples
// this.nEdges = s.nextInt();
// this.nEnergies = s.nextInt();
// // Line 3: indices of the edges in the energy array. The original array
// // has a 1-based index, so subtract 1.
// this.edgeIndices = new ArrayList<Integer>(nEdges);
// for (int iEdge = 0; iEdge < nEdges; iEdge++)
// this.edgeIndices.add(iEdge, s.nextInt()-1);
// // Line 4; names of the edges. Discarded
// for (int iEdge = 0; iEdge < nEdges; iEdge++)
// s.next();
// // Line 5: energies of the edges, eV in the rawData, want to store keV.
// this.edgeEnergies = new ArrayList<Double>(nEdges);
// for (int iEdge = 0; iEdge < nEdges; iEdge++)
// this.edgeEnergies.add(iEdge, s.nextDouble()*1e-3);
//
// // Next nEnergy values: values of the energy coordinate, store as is
// // and as natural logarithm.
// this.logEnergies = new ArrayList<Double>(nEnergies);
// this.energies = new ArrayList<Double>(nEnergies);
// for (int iEnergy = 0; iEnergy < nEnergies; iEnergy++) {
// double energy = s.nextDouble()*1e-3;
// this.energies.add(iEnergy, energy);
// this.logEnergies.add(iEnergy, Math.log(energy));
// }
//
// // Next nEnergy values: coherent scattering cross-section in barns,
// // store as natural logarithm
// this.coherentScatteringSigma = new ArrayList<Double>(nEnergies);
// for (int iEnergy = 0; iEnergy < nEnergies; iEnergy++)
// this.coherentScatteringSigma.add(iEnergy, Math.log(s.nextDouble()));
// // Next nEnergy values: incoherent scattering cross-section in barns,
// // store as natural logarithm.
// this.incoherentScatteringSigma = new ArrayList<Double>(nEnergies);
// for (int iEnergy = 0; iEnergy < nEnergies; iEnergy++)
// this.incoherentScatteringSigma.add(iEnergy, Math.log(s.nextDouble()));
// // Next nEnergy values: photoelectric absorption cross-section in
// // barns, store as natural logarithm.
// this.photoelectricSigma = new ArrayList<Double>(nEnergies);
// for (int iEnergy = 0; iEnergy < nEnergies; iEnergy++)
// this.photoelectricSigma.add(iEnergy, Math.log(s.nextDouble()));
// // Next nEnergy values: nuclear pair production cross-section in barns,
// // store as natural logarithm.
// this.nuclearPairSigma = new ArrayList<Double>(nEnergies);
// for (int iEnergy = 0; iEnergy < nEnergies; iEnergy++)
// this.nuclearPairSigma.add(iEnergy, Math.log(s.nextDouble()));
// // Next nEnergy values: electronic pair production cross-section in
// // barns, store as natural logarithm.
// this.electronPairSigma = new ArrayList<Double>(nEnergies);
// for (int iEnergy = 0; iEnergy < nEnergies; iEnergy++)
// this.electronPairSigma.add(iEnergy, Math.log(s.nextDouble()));
//
// if (nEdges > 0) {
// // number of edges again
// s.nextInt();
// // number of coefficients per edge
// this.edgeMulitplicity = new ArrayList<Integer>(nEdges);
// for (int iEdge = 0; iEdge < nEdges; iEdge++)
// edgeMulitplicity.add(iEdge, s.nextInt());
// // next sum(edgeMultiplicity) values: edgeData1.
// // edge energy grid points in MeV. Stored as natural logarithm of
// // keV.
// this.edgeData1 = new ArrayList<List<Double>>(nEdges);
// for (int iEdge = 0; iEdge < nEdges; iEdge++) {
// edgeData1.add(iEdge, new ArrayList<Double>(edgeMulitplicity.get(iEdge)));
// for (int i = 0; i < edgeMulitplicity.get(iEdge); i++)
// edgeData1.get(iEdge).add(i, Math.log(s.nextDouble()*1e3));
// }
// // next sum(edgeMultiplicity) values: edgeData2.
// // edge photoelectric cross-sections in barns, stored as natural
// // logarithm.
// this.edgeData2 = new ArrayList<List<Double>>(nEdges);
// for (int iEdge = 0; iEdge < nEdges; iEdge++) {
// edgeData2.add(iEdge, new ArrayList<Double>(edgeMulitplicity.get(iEdge)));
// for (int i = 0; i < edgeMulitplicity.get(iEdge); i++)
// edgeData2.get(iEdge).add(i, Math.log(s.nextDouble()));
// }
// }
// s.close();
// }
//
// /**
// * Calculates an elemental cross section.
// * <p>
// * Calculates one of the available cross-sections for the element. The possible cross-sections are:
// * <ul>
// * <li>"coherent"
// * <li>"incoherent"
// * <li>"photoelectric"
// * <li>"nuclear pair production"
// * <li>"electronic pair production"
// * <li>"total"
// * <li>"total without coherent"
// * </ul>
// * @param photonEnergy
// * energy of the incident photon in keV.
// * @param crossSectionType
// * String description of the desired cross-section.
// * @return the calculated cross section in barns = 1e-30 m²
// */
// public double getCrossSection(double photonEnergy, String crossSectionType) {
// switch (crossSectionType) {
// case "coherent":
// return getInCoherentCrossSection(photonEnergy, coherentScatteringSigma);
// case "incoherent":
// return getInCoherentCrossSection(photonEnergy, incoherentScatteringSigma);
// case "photoelectric":
// return getPhotoelectricCrossSection(photonEnergy);
// case "nuclear pair production":
// return 0.0;
// case "electronic pair production":
// return 0.0;
// case "total":
// return getCrossSection(photonEnergy, "total without coherent") +
// getCrossSection(photonEnergy, "coherent");
// case "total without coherent":
// return getCrossSection(photonEnergy, "incoherent") +
// getCrossSection(photonEnergy, "photoelectric") +
// getCrossSection(photonEnergy, "nuclear pair production") +
// getCrossSection(photonEnergy, "electronic pair production");
// default:
// return 0.0;
// }
// }
//
// /**
// * Calculates the coherent or incoherent scattering.
// * @param photonEnergy
// * energy of the incident photon.
// * @param scatteringSigma
// * table of log values to interpolate
// * @return coherent or incoherent electron scattering cross-section in barns per atom.
// */
// private double getInCoherentCrossSection(double photonEnergy, List<Double> scatteringSigma) {
//
// double logPhotonEnergy = Math.log(photonEnergy);
// SplineInterpolator splint = new SplineInterpolator();
// if (logPhotonEnergy < logEnergies.get(0))
// return scatteringSigma.get(0);
// else if (logPhotonEnergy > logEnergies.get(nEnergies-1))
// return scatteringSigma.get(nEnergies-1);
// else
// return Math.exp(splint.interpolate(
// ArrayUtils.toPrimitive(logEnergies.toArray(new Double[nEnergies])),
// ArrayUtils.toPrimitive(scatteringSigma.toArray(new Double[nEnergies]))).value(logPhotonEnergy));
// }
//
// /**
// * Calculates the the photoelectric attenuation.
// * @param photonEnergy
// * energy of the incident photon
// * @return photoelectric attenuation cross-section of the element in barns per atom.
// */
// private double getPhotoelectricCrossSection(double photonEnergy) {
//
// double logPhotonEnergy = Math.log(photonEnergy);
// if (logPhotonEnergy < logEnergies.get(0))
// return photoelectricSigma.get(0);
// else if (logPhotonEnergy > logEnergies.get(nEnergies-1))
// return photoelectricSigma.get(nEnergies-1);
// else
// if (nEdges == 0 || photonEnergy > this.edgeEnergies.get(0)) {
// // An energy above the K-edge is just log-log spline interpolated
// List<Double> logE = logEnergies, logSigma = photoelectricSigma;
//
// if (nEdges != 0) {
// logE = logEnergies.subList(edgeIndices.get(0), logEnergies.size());
// logSigma = photoelectricSigma.subList(edgeIndices.get(0), logEnergies.size());
// }
// double tresult = Math.exp((new SplineInterpolator()).interpolate(
// ArrayUtils.toPrimitive(logE.toArray(new Double[logE.size()])),
// ArrayUtils.toPrimitive(logSigma.toArray(new Double[logSigma.size()]))).value(logPhotonEnergy));
// return tresult;
//
// } else {
// // In amongst the edges
// //
// List<Double> reverseEdgeEnergies = new ArrayList<Double>(edgeEnergies);
// Collections.reverse(reverseEdgeEnergies);
// int iEdge = Collections.binarySearch(reverseEdgeEnergies, photonEnergy);
// // Select the edge data to use. on the edge (exactly) is taken as being below the edge.
// iEdge = (iEdge < 0) ? -iEdge-1 : iEdge;
// double tresult = Math.exp((new LinearInterpolator()).interpolate(
// ArrayUtils.toPrimitive(edgeData1.get(iEdge).toArray(new Double[edgeMulitplicity.get(iEdge)])),
// ArrayUtils.toPrimitive(edgeData2.get(iEdge).toArray(new Double[edgeMulitplicity.get(iEdge)]))).value(logPhotonEnergy));
// return tresult;
// }
// }
//
// /**
// * Calculates an elemental cross section.
// * <p>
// * Calculates one of the available attenuation coefficients for the element. The possible coefficients are:
// * <ul>
// * <li>"coherent"
// * <li>"incoherent"
// * <li>"photoelectric"
// * <li>"nuclear pair production"
// * <li>"electronic pair production"
// * <li>"total"
// * <li>"total without coherent"
// * </ul>
// * @param photonEnergy
// * energy of the incident photon in keV.
// * @param AttenuationType
// * String description of the attenuation coefficient.
// * @return the calculated attenuation coefficient in cm²/g
// */
// public double getAttenuation(double photonEnergy, String AttenuationType) {
// final double nAvogadro = 6.022140857e23;
// final double cm2perbarn = 1e-24;
//
// return getCrossSection(photonEnergy, AttenuationType) *
// nAvogadro /
// this.atomicMass *
// cm2perbarn;
// }
//
//}