Author: [log in to unmask]
Date: Tue Nov 25 20:26:14 2014
New Revision: 1596
Log:
Add optional output file for generated calibration data. Make fit optional and if disabled use the histogram's mean and sigma instead. Minor refactoring of code into separate methods.
Modified:
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalCalibrationsDriver.java
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalCalibrationsDriver.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalCalibrationsDriver.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalCalibrationsDriver.java Tue Nov 25 20:26:14 2014
@@ -7,10 +7,12 @@
import hep.aida.IFunctionFactory;
import hep.aida.IHistogram1D;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -34,6 +36,10 @@
* This Driver will generate a {@link org.hps.conditions.EcalCalibration} collection
* from the ADC value distributions of raw ECAL data. It may optionally insert this
* information into the conditions database using the file's run number.
+ *
+ * Currently, it uses every ADC value for the distribution, but filtering should probably
+ * be added to exclude hits above a certain threshold.
+ *
* @author Jeremy McCormick <[log in to unmask]>
*/
public class EcalCalibrationsDriver extends Driver {
@@ -41,21 +47,58 @@
EcalConditions ecalConditions = null;
DatabaseConditionsManager conditionsManager = null;
AIDA aida = AIDA.defaultInstance();
+ IFunctionFactory functionFactory = aida.analysisFactory().createFunctionFactory(null);
+ IFitFactory fitFactory = aida.analysisFactory().createFitFactory();
boolean loadCalibrations = false;
+ boolean performFit = true;
+ File outputFile = null;
Set<Integer> runs = new HashSet<Integer>();
+ /**
+ * Set whether to automatically load the conditions into the database.
+ * @param loadCalibrations True to load conditions into the database.
+ */
public void setLoadCalibrations(boolean loadCalibrations) {
this.loadCalibrations = loadCalibrations;
}
- public void detectorChanged(Detector detector) {
+ /**
+ * Set whether to perform a function fit to get the mean and sigma values.
+ * @param performFit True to perform a function fit of the histogram.
+ */
+ public void setPerformFit(boolean performFit) {
+ this.performFit = performFit;
+ }
+
+ /**
+ * Set an output file path for writing the calibration data.
+ * @param outputFileName The path to the output file.
+ */
+ public void setOutputFileName(String outputFileName) {
+ if (outputFileName == null) {
+ throw new IllegalArgumentException("The outputFileName argument is null.");
+ }
+ outputFile = new File(outputFileName);
+ }
+
+ /**
+ * Initialize this Driver when conditions change is triggered.
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
conditionsManager = DatabaseConditionsManager.getInstance();
ecalConditions = conditionsManager.getCachedConditions(EcalConditions.class, TableConstants.ECAL_CONDITIONS).getCachedData();
+
+ // Create a histogram for every ECAL channel.
for (EcalChannel channel : ecalConditions.getChannelCollection().getObjects()) {
aida.histogram1D("ECAL Channel " + channel.getChannelId(), 300, 0, 300.);
}
}
+ /**
+ * Process the event data, filling the channel histograms from the ADC values.
+ */
+ @Override
public void process(EventHeader event) {
runs.add(event.getRunNumber());
if (event.hasCollection(RawTrackerHit.class, "EcalReadoutHits")) {
@@ -72,6 +115,11 @@
}
}
+ /**
+ * End of data hook, which will get the mean and sigma for the ADC distributions.
+ * It may optionally write these to a file and push the values into the database.
+ */
+ @Override
public void endOfData() {
if (runs.size() == 0) {
@@ -79,29 +127,35 @@
}
List<Integer> runList = new ArrayList<Integer>(runs);
Collections.sort(runList);
-
- IFunctionFactory functionFactory = aida.analysisFactory().createFunctionFactory(null);
- IFitFactory fitFactory = aida.analysisFactory().createFitFactory();
-
+
EcalCalibrationCollection calibrations = new EcalCalibrationCollection();
TableMetaData tableMetaData = conditionsManager.findTableMetaData(TableConstants.ECAL_CALIBRATIONS);
calibrations.setTableMetaData(tableMetaData);
+ // Loop over all ECAL channels.
for (EcalChannel channel : ecalConditions.getChannelCollection().getObjects()) {
+
+ // Get the histogram with ADC distribution for this channel.
IHistogram1D histogram = aida.histogram1D("ECAL Channel " + channel.getChannelId());
- IFunction function = functionFactory.createFunctionByName("Gaussian", "G");
- IFitter fitter = fitFactory.createFitter("chi2", "jminuit");
- double[] parameters = new double[3];
- parameters[0] = histogram.maxBinHeight();
- parameters[1] = histogram.mean();
- parameters[2] = histogram.rms();
- function.setParameters(parameters);
- IFitResult fitResult = fitter.fit(histogram, function);
int channelId = channel.getChannelId();
-
- double mean = fitResult.fittedParameter("mean");
- double sigma = fitResult.fittedParameter("sigma");
+
+ double mean = 0;
+ double sigma = 0;
+
+ if (performFit) {
+ // Perform a Gaussian fit and use its mean and sigma.
+ IFitResult fitResult = doGaussianFit(histogram);
+ mean = fitResult.fittedParameter("mean");
+ sigma = fitResult.fittedParameter("sigma");
+ } else {
+ // Use the histogram's statistics for mean and sigma.
+ mean = histogram.mean();
+ sigma = histogram.rms();
+ }
+
+ // Create a new calibration object and add it to the collection, using mean for pedestal
+ // and sigma for noise.
EcalCalibration calibration = new EcalCalibration(channelId, mean, sigma);
try {
calibrations.add(calibration);
@@ -109,27 +163,96 @@
throw new RuntimeException(e);
}
}
- System.out.println(calibrations.toString());
+
+ // Get the list of field names for the header.
+ StringBuffer buffer = new StringBuffer();
+ for (String fieldName : tableMetaData.getFieldNames()) {
+ buffer.append(fieldName + " ");
+ }
+ buffer.setLength(buffer.length() - 1);
+ String fieldNames = buffer.toString();
+
+ // Is there an output file for the calibration data?
+ if (outputFile != null) {
+ // Write the calibration data to an output text file.
+ writeToFile(calibrations, fieldNames);
+ } else {
+ // Just print out the information to the console.
+ System.out.println(fieldNames);
+ System.out.println(calibrations.toString());
+ }
+
+ // Load the calibrations into the conditions database?
if (loadCalibrations) {
- int collectionId = conditionsManager.getNextCollectionID(TableConstants.ECAL_CALIBRATIONS);
- try {
- calibrations.setCollectionId(collectionId);
- calibrations.insert();
- int runStart = runList.get(0);
- int runEnd = runList.get(runList.size() - 1);
- ConditionsRecord conditionsRecord = new ConditionsRecord(
- calibrations.getCollectionId(),
- runStart,
- runEnd,
- TableConstants.ECAL_CALIBRATIONS,
- TableConstants.ECAL_CALIBRATIONS,
- "Auto generated by EcalCalibrationsDriver.",
- "eng_run");
- conditionsRecord.setTableMetaData(conditionsManager.findTableMetaData(TableConstants.CONDITIONS_RECORD));
- conditionsRecord.insert();
- } catch (ConditionsObjectException | SQLException e) {
- throw new RuntimeException(e);
- }
- }
+ loadCalibrations(runList, calibrations);
+ }
+ }
+
+ /**
+ * Write the calibration data to an output file.
+ * @param calibrations The calibration data which is record delimited by new lines.
+ * @param fieldNames The list of field names as a single string.
+ */
+ private void writeToFile(EcalCalibrationCollection calibrations, String fieldNames) {
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(outputFile);
+ writer.write(fieldNames);
+ writer.write(calibrations.toString());
+ } catch (IOException e) {
+ throw new RuntimeException("There was a problem writing to the output file.", e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Load the calibration data into the conditions database.
+ * @param runList The list of runs processed in the job.
+ * @param calibrations The collection of calibration objects.
+ */
+ private void loadCalibrations(List<Integer> runList, EcalCalibrationCollection calibrations) {
+ int collectionId = conditionsManager.getNextCollectionID(TableConstants.ECAL_CALIBRATIONS);
+ try {
+ calibrations.setCollectionId(collectionId);
+ calibrations.insert();
+ int runStart = runList.get(0);
+ int runEnd = runList.get(runList.size() - 1);
+ ConditionsRecord conditionsRecord = new ConditionsRecord(
+ calibrations.getCollectionId(),
+ runStart,
+ runEnd,
+ TableConstants.ECAL_CALIBRATIONS,
+ TableConstants.ECAL_CALIBRATIONS,
+ "Auto generated by EcalCalibrationsDriver.",
+ "eng_run");
+ conditionsRecord.setTableMetaData(conditionsManager.findTableMetaData(TableConstants.CONDITIONS_RECORD));
+ conditionsRecord.insert();
+ } catch (ConditionsObjectException | SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Do a Gaussian fit to calculate the mean and sigma of a histogram.
+ * @param histogram The histogram for the ECAL channel.
+ * @return The fit result.
+ */
+ private IFitResult doGaussianFit(IHistogram1D histogram) {
+ IFunction function = functionFactory.createFunctionByName("Gaussian", "G");
+ IFitter fitter = fitFactory.createFitter("chi2", "jminuit");
+ double[] parameters = new double[3];
+ parameters[0] = histogram.maxBinHeight();
+ parameters[1] = histogram.mean();
+ parameters[2] = histogram.rms();
+ function.setParameters(parameters);
+ IFitResult fitResult = fitter.fit(histogram, function);
+ return fitResult;
}
}
|