package edu.stanford.rsl.conrad.physics; import edu.stanford.rsl.conrad.utils.CONRAD; import edu.stanford.rsl.conrad.utils.LinearInterpolatingDoubleArray; import edu.stanford.rsl.jpop.SimpleFunctionOptimizer; import edu.stanford.rsl.jpop.SimpleOptimizableFunction; public class HalfValueLayerFunction implements SimpleOptimizableFunction { private double [] xRayEnergy; private double [] xRaySpectrum; private LinearInterpolatingDoubleArray attenuationCoefficients1; private LinearInterpolatingDoubleArray attenuationCoefficients2; private LinearInterpolatingDoubleArray attenuationCoefficients3; public double optimalX; public HalfValueLayerFunction (double [] energies, double [] spectrum, LinearInterpolatingDoubleArray lida1, LinearInterpolatingDoubleArray lida2, LinearInterpolatingDoubleArray lida3){ this.xRayEnergy = energies; // energy KeV this.xRaySpectrum = spectrum; // photon count # this.attenuationCoefficients1 = lida1; this.attenuationCoefficients2 = lida2; this.attenuationCoefficients3 = lida3; } @Override public double evaluate(double x) { double sumN0 = 0; double sumN1 = 0; double coeff1; // Al double coeff2; // CsI converter double coeff3; // Air absorption double detectorEfficiency = 1; double xRayQuanta = 1; boolean isHVLMeasuredAtDetector = false; boolean isAirAbsorptionCounted = true; try { for (int i = 0; i< xRaySpectrum.length; i++){ coeff1 = attenuationCoefficients1.getValue(xRayEnergy[i]/1000); coeff2 = attenuationCoefficients2.getValue(xRayEnergy[i]/1000); coeff3 = attenuationCoefficients3.getValue(xRayEnergy[i]/1000); if(isHVLMeasuredAtDetector) { // Detector flat panel efficiency, thickness = 200 [g/cm2] detectorEfficiency = 1 - Math.exp(-coeff2 * 200); } if(isAirAbsorptionCounted) { xRayQuanta = XRaySpectrum.xrqpRe(coeff3); } // Exposure (R) of the spectrum specified by the vector phi at energies specified by E (keV). sumN1 += xRaySpectrum[i] * Math.exp(-coeff1 * x) * detectorEfficiency * xRayEnergy[i] / xRayQuanta; sumN0 += xRaySpectrum[i] * detectorEfficiency * xRayEnergy[i] / xRayQuanta; // System.out.println(xRayEnergy[i]+"\t"+coeff1+"\t"+coeff2+"\t"+coeff3); } }catch (Exception e){ e.printStackTrace(); } // System.out.println(x +"\t"+ Math.abs(sumN0/2 - sumN1)); return Math.abs(sumN0/2 - sumN1); } public void runOptimization() { SimpleFunctionOptimizer optimizer = new SimpleFunctionOptimizer(); optimizer.setLeftEndPoint(0); optimizer.setRightEndPoint(10); //optimizer.setInitialGuess(0.44); optimizer.setAbsoluteTolerance(CONRAD.DOUBLE_EPSILON); optimizer.setRelativeTolerance(CONRAD.DOUBLE_EPSILON); //optimizer. optimalX = optimizer.minimize(this); } public double getOptimalX(){ return optimalX; } } /* * Copyright (C) 2010-2014 Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */