/* * Copyright (C) 2014 - Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.tutorial.physics; import ij.gui.Plot; import java.util.ArrayList; import edu.stanford.rsl.conrad.geometry.shapes.simple.Edge; import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND; import edu.stanford.rsl.conrad.geometry.trajectories.Trajectory; import edu.stanford.rsl.conrad.physics.PhysicalObject; import edu.stanford.rsl.conrad.physics.PolychromaticXRaySpectrum; import edu.stanford.rsl.conrad.physics.absorption.PolychromaticAbsorptionModel; import edu.stanford.rsl.conrad.physics.absorption.SelectableEnergyMonochromaticAbsorptionModel; import edu.stanford.rsl.conrad.physics.materials.database.MaterialsDB; import edu.stanford.rsl.conrad.utils.Configuration; /** * Example class to play and test spectral absorption. Here we generate a spectrum and plot it. * Next, we create a monochromatic and a polychromatic absorption model. We investigate both in terms of their absorption behavior and create a plot for the mono- and the polychromatic case. * The difference can be looked at, both both are plotted in the same coordinate system. This code is also featured on the CONRAD tutorial website in more detail. * @author Andreas Maier * */ public class SpectralAbsorption { public static void main(String [] args){ // Enable access to the global configuration Configuration.loadConfiguration(); // Fetch some geometry information from the global configuration Trajectory trajectory = Configuration.getGlobalConfiguration().getGeometry(); double detectorArea = trajectory.getPixelDimensionX() * trajectory.getDetectorWidth() * trajectory.getDetectorHeight() * trajectory.getPixelDimensionY(); double pixelArea = trajectory.getPixelDimensionX() * trajectory.getPixelDimensionY(); // set spectral parameters double min = 10; double max = 60; double delta = 0.5; double peakVoltage = 40; double timeCurrentProduct = 1; // create spectrum PolychromaticXRaySpectrum spectrum = new PolychromaticXRaySpectrum(min, max, delta, peakVoltage, timeCurrentProduct); // get total photon flux in [photons/mm^-2] double totalPhotonFlux = spectrum.getTotalPhotonFlux(); /* input energy in J */ double inputEnergy = peakVoltage * timeCurrentProduct; /* convert to keV */ inputEnergy *= 6.24150934E15; /* output energy in keV */ double outputEnergy = detectorArea * totalPhotonFlux * spectrum.getAveragePhotonEnergy(); /* compute source efficiency, i.e. the amount of energy that is detected compared to the amount of energy that is used for creation of the spectrum */ double ratio = outputEnergy / inputEnergy; // create spectral plot Plot plot = new Plot("C-Arm Spectrum with " + detectorArea * totalPhotonFlux + " total photons and " + pixelArea * totalPhotonFlux + " photons per pixel, avg energy "+ spectrum.getAveragePhotonEnergy() + " [keV] and " +ratio*100+ " % energy efficiency", "Energy [keV]", "Photon Flux [photons/mm^2]", spectrum.getPhotonEnergies(), spectrum.getPhotonFlux()); plot.show(); // create absorption / length plots // initialize arrays int vals = 20; double lengths [] = new double [vals]; double monoAttenuation []= new double[vals]; double polyAttenuation []= new double[vals]; // create monochromatic absorption model SelectableEnergyMonochromaticAbsorptionModel monochromaticAbsorptionModel = new SelectableEnergyMonochromaticAbsorptionModel(); monochromaticAbsorptionModel.configure(spectrum.getAveragePhotonEnergy()); // create polychromatic absorption model PolychromaticAbsorptionModel polychromaticAbsorptionModel = new PolychromaticAbsorptionModel(); polychromaticAbsorptionModel.setInputSpectrum(spectrum); try { polychromaticAbsorptionModel.configure(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // create list of line intersections. // Here we have a line with only one intersection // of water PhysicalObject segment = new PhysicalObject(); segment.setMaterial(MaterialsDB.getMaterial("water")); segment.setNameString("Water Path"); ArrayList<PhysicalObject> segments = new ArrayList<PhysicalObject>(); segments.add(segment); // Iterate over the different intersection lengths for (int i = 0; i < vals; i++){ lengths[i] = i*20; // create intersection path Edge edge = new Edge(new PointND(0), new PointND(lengths[i])); segment.setShape(edge); // evaluate attenuation models monoAttenuation[i]= monochromaticAbsorptionModel.evaluateLineIntegral(segments); polyAttenuation[i]= polychromaticAbsorptionModel.evaluateLineIntegral(segments); } // create plots Plot plot2 = new Plot("Monochromatic absorption q, avg energy "+ spectrum.getAveragePhotonEnergy() + " [keV]", "path length in water", "q_mono", lengths, monoAttenuation); plot2.show(); Plot plot3 = new Plot("Polychromatic absorption q, avg energy "+ spectrum.getAveragePhotonEnergy() + " [keV]", "path length in water", "q_poly", lengths, polyAttenuation); plot3.show(); } }