content:  /*
    * 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.materialsTest;
  
  
  
  import junit.framework.Assert;
  
  import org.junit.Test;
  
  import edu.stanford.rsl.conrad.physics.materials.Material;
  import edu.stanford.rsl.conrad.physics.materials.database.FormulaToNameMap;
  import edu.stanford.rsl.conrad.physics.materials.database.MaterialsDB;
  import edu.stanford.rsl.conrad.physics.materials.database.OnlineMassAttenuationDB;
  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>Class for comparing the results from local mass attenuation calculator with online mass attenuation calculation from XCOM</p>
   * <p>Class asserts that Max Error < 3%, in reality maximum error is significantly less than this value in most materials.
   * @author Rotimi X Ojo
   * @author Andreas Maier
   * 
   */ 
  
  public class TestMassAttenuationData {
  	
  	@Test
  	public void reportPredefinedMaterials(){
  		String [] materials = MaterialsDB.getPredefinedMaterials();
  		System.out.println("Number of predefined materials:" + materials.length);
  		for (String material:materials) System.out.println(material);
  		// Standard configuration of CONRAD comes with at least 105 known materials.
  		Assert.assertTrue(materials.length > 104);
  	}
  	
  	@Test
  	public void reportKnownMaterials(){
  		String [] materials = MaterialsDB.getMaterials();
  		System.out.println("Number of known materials:" + materials.length);
  		for (String material:materials) System.out.println(material);
  		// Standard configuration of CONRAD comes with at least 105 known materials.
  		Assert.assertTrue(materials.length > 104);
  	}
  	
  	@Test
  	public void testMaterialMassAttenutationCalculator(){
  		System.out.println("Testing LocalMassAttenuationCalculator Accuracy: " );
  		String [] identifiers = FormulaToNameMap.map.keySet().toArray(new String[FormulaToNameMap.map.size()]);
  		int numEnergies = 1000;
  		int maxEnergy = 100000;
  		for(int i =0; i < 1/*identifiers.length*/; i++){
  			String iden = identifiers[i];
  			System.out.println("\tTesting " + iden);
  			Material mat = MaterialsDB.getMaterial(iden);	
  			
  			//double [] results1 = testKnownMaterials(mat,AttenuationType.TOTAL_WITHOUT_COHERENT_ATTENUATION,numEnergies, maxEnergy);
  			testKnownMaterials(mat,AttenuationType.TOTAL_WITH_COHERENT_ATTENUATION,numEnergies, maxEnergy );
  			//double [] results3 = testKnownMaterials(mat,AttenuationType.COHERENT_ATTENUATION,numEnergies, maxEnergy);
  			//double [] results4 = testKnownMaterials(mat,AttenuationType.INCOHERENT_ATTENUATION,numEnergies, maxEnergy);
  			//double [] results5 = testKnownMaterials(mat,AttenuationType.NUCLEAR_FIELD_PAIRPRODUCTION,numEnergies, maxEnergy);
  			//double [] results6 = testKnownMaterials(mat,AttenuationType.PHOTOELECTRIC_ABSORPTION,numEnergies, maxEnergy);
  
  		
  		}
  		System.out.println("Testing Completed" );
  	}	
  	/**
  	 * Compare local and online mass attenuation values of know materials
  	 * @param mat is material of interest
  	 * @param att is attenuation of interest
  	 * @param numEnergies is energies to be tested
  	 */
  	public static double [] testKnownMaterials(Material mat,AttenuationType att, int numEnergies, int maxEnergy) {
  		return testArbitraryMaterial(mat.getWeightedAtomicComposition(), att, numEnergies, maxEnergy);
  	}
  	
  	/**
  	 * CompareCompare local and online mass attenuation values of arbitrarily defined material
  	 * @param formula is chemical formula of material
  	 * @param att is attenuation of interest
  	 * @param numEnergies
  	 */
  	public static double [] testArbitraryMaterial(String formula, AttenuationType att, int numEnergies, int maxEnergy){
  		return testArbitraryMaterial(new WeightedAtomicComposition(formula), att, numEnergies, maxEnergy);
  	}
  	
  	
  	/**
  	 * CompareCompare local and online mass attenuation values of arbitrarily defined material
  	 * @param comp is weighted atomic composition
  	 * @param att is attenuation of interest
  	 * @param numEnergies
  	 */
  	public static double [] testArbitraryMaterial(WeightedAtomicComposition comp, AttenuationType att, int numEnergies, int maxEnergy){
  		System.out.println("\t\tTesting " + att);
  		double [] energies = new double[numEnergies];
  		
  		
  		for(int i = 0;i < energies.length;i++){
  			energies[i] = (Math.random()*maxEnergy) + 1;
  		}
  		
  		double maxError = 0;
  		double minError = Double.MAX_VALUE;
  		double errorSum = 0;
  		int nonZeroErrorCount = 0;
  		
  		for(double energy:energies){
  		
  			double val = OnlineMassAttenuationDB.getMassAttenuationData(comp, energy/1000, att);
  			double val2 = LocalMassAttenuationCalculator.getMassAttenuationData(comp, energy/1000, att);
  			double error = Math.abs(val-val2)/val;
  			
  			if(error > maxError ){
  				maxError = error;
  			}
  			
  			if(error < minError){
  				minError = error;
  			}
  			
  			if(error > 0){
  				nonZeroErrorCount++;
  				errorSum+= error;
  			}
  			
  		}
  		
  		double meanErr = errorSum/nonZeroErrorCount;
  		assert(maxError < 3);
  		double [] results = {minError,maxError,meanErr};
  		
  		System.out.println("Min Error is:  " + minError + "%");
  		System.out.println("Max Error is:  " + maxError+ "%");
  		System.out.println("Mean Error is: " + meanErr+ "%");
  		return results;
  	}
  
  }
  