3 added + 1 removed + 5 modified, total 9 files
hps-java/src/main/java/org/lcsim/hps/recon/tracking
diff -N DumbShaperFit.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DumbShaperFit.java 25 Apr 2012 15:23:42 -0000 1.1
@@ -0,0 +1,22 @@
+package org.lcsim.hps.recon.tracking;
+
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants.ChannelConstants;
+
+/**
+ *
+ * @author mgraham
+ */
+public class DumbShaperFit implements HPSShaperFitAlgorithm {
+
+ public DumbShaperFit() {
+ }
+
+ @Override
+ public HPSShapeFitParameters fitShape(RawTrackerHit rth, ChannelConstants constants) {
+ HPSShapeFitParameters fitresults = new HPSShapeFitParameters();
+ fitresults.setAmp(1000.666);
+ fitresults.setT0(5.999);
+ return fitresults;
+ }
+}
hps-java/src/main/java/org/lcsim/hps/recon/tracking
diff -u -r1.2 -r1.3
--- HPSStripMaker.java 24 Apr 2012 17:45:44 -0000 1.2
+++ HPSStripMaker.java 25 Apr 2012 15:23:42 -0000 1.3
@@ -175,7 +175,7 @@
TrackerHitType type = new TrackerHitType(TrackerHitType.CoordinateSystem.GLOBAL, TrackerHitType.MeasurementType.STRIP_1D);
List<RawTrackerHit> rth_cluster = new ArrayList<RawTrackerHit>();
for (HPSFittedRawTrackerHit bth : cluster) {
- rth_cluster.add((RawTrackerHit) bth);
+ rth_cluster.add( bth.getRawTrackerHit());
}
SiTrackerHitStrip1D hit = new SiTrackerHitStrip1D(position, covariance, energy, time, rth_cluster, type);
return hit;
hps-java/src/main/java/org/lcsim/hps/recon/tracking
diff -u -r1.4 -r1.5
--- HPSRawTrackerHitFitterDriver.java 24 Apr 2012 23:33:57 -0000 1.4
+++ HPSRawTrackerHitFitterDriver.java 25 Apr 2012 15:23:42 -0000 1.5
@@ -1,7 +1,3 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
package org.lcsim.hps.recon.tracking;
import java.util.ArrayList;
@@ -19,7 +15,7 @@
*/
public class HPSRawTrackerHitFitterDriver extends Driver {
- private HPSShaperFitAlgorithm _shaper = null;
+ private HPSShaperFitAlgorithm _shaper = new DumbShaperFit();
private String rawHitCollectionName = "SVTRawTrackerHits";
private String fitCollectionName = "SVTShapeFitParameters";
private String fittedHitCollectionName = "SVTFittedRawTrackerHits";
@@ -49,6 +45,8 @@
if (rawHitCollectionName == null) {
throw new RuntimeException("The parameter ecalCollectionName was not set!");
}
+ HPSSVTCalibrationConstants calibConstants=new HPSSVTCalibrationConstants();
+ calibConstants.loadCalibrationConstants("Foobar");
}
@Override
@@ -67,9 +65,9 @@
fits.add(fit);
HPSFittedRawTrackerHit hth = new HPSFittedRawTrackerHit(hit, fit);
hits.add(hth);
- hit.getDetectorElement().getReadout().addHit(hth);
- }
+ hit.getDetectorElement().getReadout().addHit(hth);
+ }
event.put(fitCollectionName, fits, HPSShapeFitParameters.class, genericObjectFlags);
event.put(fittedHitCollectionName, hits, HPSFittedRawTrackerHit.class, relationFlags);
- }
+ }
}
hps-java/src/main/java/org/lcsim/hps/recon/tracking
diff -u -r1.2 -r1.3
--- HPSSVTCalibrationConstants.java 24 Apr 2012 23:32:31 -0000 1.2
+++ HPSSVTCalibrationConstants.java 25 Apr 2012 15:23:42 -0000 1.3
@@ -101,10 +101,15 @@
}
}
- public static ChannelConstants getChannelConstants(SiSensor sensor, int channel) {
- Pair<SiSensor, Integer> sensorChannel = new Pair(sensor, channel);
+ public static ChannelConstants getChannelConstants(SiSensor sensor, int channel) {
+ Pair<SiSensor, Integer> sensorChannel = new Pair(sensor, channel);
ChannelConstants constants = new ChannelConstants();
- constants.setNoise(noise.get(sensorChannel));
+// ...don't have a constants file yet!
+ noise.put(sensorChannel,40.0);
+ pedestal.put(sensorChannel,7000.0);
+ tShaping.put(sensorChannel,36.0);
+////
+ constants.setNoise(noise.get(sensorChannel));
constants.setPedestal(pedestal.get(sensorChannel));
constants.setTp(tShaping.get(sensorChannel));
hps-java/src/main/java/org/lcsim/hps/recon/tracking
diff -u -r1.1 -r1.2
--- HPSShaperAnalyticFitAlgorithm.java 24 Apr 2012 23:32:31 -0000 1.1
+++ HPSShaperAnalyticFitAlgorithm.java 25 Apr 2012 15:23:42 -0000 1.2
@@ -6,7 +6,7 @@
/**
* Fast fitter; currently only fits single hits. Uses Tp from ChannelConstants; fits values and errors for T0 and amplitude.
* @author meeg
- * @version $Id: HPSShaperAnalyticFitAlgorithm.java,v 1.1 2012/04/24 23:32:31 meeg Exp $
+ * @version $Id: HPSShaperAnalyticFitAlgorithm.java,v 1.2 2012/04/25 15:23:42 mgraham Exp $
*/
public class HPSShaperAnalyticFitAlgorithm implements HPSShaperFitAlgorithm {
@@ -26,7 +26,7 @@
}
private double fitSection(RawTrackerHit rth, ChannelConstants constants, HPSShapeFitParameters fit, int start) {
- int length = rth.getADCValues().length - start + 1;
+ int length = rth.getADCValues().length - start;
double[] y = new double[length];
double[] t = new double[length];
hps-java/src/main/java/org/lcsim/hps/recon/tracking
diff -N HPSReadoutChip.java
--- HPSReadoutChip.java 22 Apr 2012 19:24:10 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,186 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.lcsim.hps.recon.tracking;
-
-import java.util.List;
-import java.util.SortedMap;
-import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
-import org.lcsim.event.RawTrackerHit;
-import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
-import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
-
-/**
- *
- * @author mgraham
- */
-public class HPSReadoutChip implements ReadoutChip {
-
- private double _noise_threshold = 4;
- private double _neighbor_threshold = 4;
- private HPSChannel _channel = new HPSChannel();// make 128 (128*5) channels instead of 1
- private HPSADC _adc = new HPSADC();
-
- @Override
- public SortedMap<Integer, List<Integer>> readout(SiElectrodeDataCollection data, SiSensorElectrodes electrodes) {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- /**
- * Decode the hit charge stored in the RawTrackerHit
- *
- * @param hit raw hit
- * @return hit charge in units of electrons ...this only gets the "charge"
- * of the first measurement
- */
- public double decodeCharge(RawTrackerHit hit) {
- return getADC().decodeCharge(hit.getADCValues()[0]);
- }
-
- /**
- * Decode the hit time. Currently, the basic readout chip ignores the hit
- * time and returns 0.
- *
- * @param hit raw hit data
- * @return hit time
- */
- public int decodeTime(RawTrackerHit hit) {
- return 0;
- }
-
- public HPSChannel getChannel(int channel_number) {
- return _channel;
- }
-
- private HPSADC getADC() {
- return _adc;
- }
-
- // here, put in call to the Amplitude vs time fitting....
- public double getFittedTime(RawTrackerHit hit, int channel_number) {
- return 0;
- }
- //here, put in call to the Amplitude vs time fitting....
-
- public double getFittedAmplitude(RawTrackerHit hit, int channel_number) {
- return 0;
- }
-
- /**
- * Creates a new instance of BasicReadoutChip
- */
- public HPSReadoutChip() {
- }
-
- private class HPSChannel implements ReadoutChannel {
-
- private double _noise;
- private double _Tp;
- private double _pedestal;
-
- public void setNoise(double Noise) {
- _noise = Noise;
- }
-
- public void setPedestal(double Pedestal) {
- _pedestal = Pedestal;
- }
-
- public void setTp(double Tp) {
- _Tp = Tp;
- }
-
- public double computeNoise(double capacitance) {
- return _noise;
- }
-
- public double getNoise() {
- return _noise;
- }
-
- public double getPedestal() {
- return _pedestal;
- }
-
- public double getTp() {
- return _Tp;
- }
- }
-
- /**
- * ADC class representing analog to digital converter.
- */
- private class HPSADC {
-
- private int _nbits = 8;
- private double _dynamic_range = 20.;
-
- /**
- * Set the ADC resolution in number of bits.
- *
- * @param nbits number of bits
- */
- private void setNbits(int nbits) {
- _nbits = nbits;
- }
-
- /**
- * Set the dynamic range in fC
- *
- * @param dynamic range
- */
- private void setDynamicRange(double dynamic_range) {
- _dynamic_range = dynamic_range;
- }
-
- /**
- * Compute the maximum ADC value
- *
- * @return largest possible ADC value according to # of bits
- */
- private int maxADCValue() {
- return (int) Math.pow(2, _nbits) - 1;
- }
-
- /**
- * Compute the conversion constant in ADC/fC
- *
- * @return conversion constant for ADC
- */
- private double conversionConstant() {
- return maxADCValue() / _dynamic_range;
- }
-
- /**
- * Perform analog to digital conversion
- *
- * @return digital ADC output between 0 and maxADCValue
- */
- public int convert(double charge) {
- if (_nbits != 1) {
- return Math.max(0, Math.min(maxADCValue(), (int) Math.floor(charge * 1.602e-4 * conversionConstant())));
- } else {
- if (charge <= 0.0) {
- return 0;
- } else {
- return 1;
- }
- }
- }
-
- /**
- * Decode charge from ADC value
- *
- * @return charge specified by a given ADC value
- */
- public double decodeCharge(int adc_value) {
- if (_nbits != 1) {
- return (adc_value + 0.5) / (1.602e-4 * conversionConstant());
- } else {
- return adc_value * _dynamic_range;
- }
-
- }
- }
-}
hps-java/src/main/java/org/lcsim/hps/users/mgraham
diff -N TestAnalysisDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TestAnalysisDriver.java 25 Apr 2012 15:23:42 -0000 1.1
@@ -0,0 +1,56 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham;
+
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author mgraham
+ */
+public class TestAnalysisDriver extends Driver{
+ int nevents=0;
+ int naccepted=0;
+
+ public void process(
+ EventHeader event) {
+ nevents++;
+ List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+ if(tracklist.size()<2)
+ return;
+
+ RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+ List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+
+ for (LCRelation relation : mcrelations) {
+ if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+ hittomc.add(relation.getFrom(), relation.getTo());
+ }
+ }
+ int ok=0;
+ for (Track track : tracklist) { //remember, these tracks are in the lcsim tracking frame!
+ TrackAnalysis tkanal = new TrackAnalysis(track, hittomc);
+ if(Math.abs(tkanal.getMCParticle().getPDGID())==611)
+ ok++;
+ //do some stuff to makes sure tracks are great
+ //is there an e+e- from the muonium
+ }
+
+ if(ok==2)
+ naccepted++;
+
+ }
+ public void endOfData() {
+
+ System.out.println("# of muonium events= " + naccepted + "; # of total = " + nevents);
+ }
+}
hps-java/src/main/java/org/lcsim/hps/users/mgraham
diff -N DataTrackerHitDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DataTrackerHitDriver.java 25 Apr 2012 15:23:42 -0000 1.1
@@ -0,0 +1,241 @@
+
+package org.lcsim.hps.users.mgraham;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.recon.tracking.*;
+import org.lcsim.recon.tracking.digitization.sisim.*;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
+import org.lcsim.util.Driver;
+import org.lcsim.util.lcio.LCIOUtil;
+
+/**
+ *
+ * @author mgraham
+ */
+public class DataTrackerHitDriver extends Driver{
+ // Debug switch for development.
+ private boolean debug = false;
+
+ // Collection name.
+ private String readoutCollectionName = "TrackerHits";
+
+ // Subdetector name.
+ private String subdetectorName = "Tracker";
+
+ // Name of RawTrackerHit output collection.
+// private String rawTrackerHitOutputCollectionName = "RawTrackerHitMaker_RawTrackerHits";
+
+ // Name of StripHit1D output collection.
+ private String stripHitOutputCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+ HPSSVTCalibrationConstants calib;
+
+ // Clustering parameters.
+ private double clusterSeedThreshold = 4.0;
+ private double clusterNeighborThreshold = 3.0;
+ private double clusterThreshold = 4.0;
+ private int clusterMaxSize = 10;
+ private int clusterCentralStripAveragingThreshold = 4;
+
+ // Clustering errors by number of TrackerHits.
+ private static final double clusterErrorMultiplier = 1.0;
+ private double oneClusterErr = clusterErrorMultiplier / Math.sqrt(12.);
+ private double twoClusterErr = clusterErrorMultiplier / 5.0;
+ private double threeClusterErr = clusterErrorMultiplier / 3.0;
+ private double fourClusterErr = clusterErrorMultiplier / 2.0;
+ private double fiveClusterErr = clusterErrorMultiplier / 1.0;
+
+ // Various data lists required by digitization.
+ private List<String> processPaths = new ArrayList<String>();
+ private List<IDetectorElement> processDEs = new ArrayList<IDetectorElement>();
+ private Set<SiSensor> processSensors = new HashSet<SiSensor>();
+ private Set<SiTrackerModule> processModules = new HashSet<SiTrackerModule>();
+
+ // Digi class objects.
+// private SiDigitizer stripDigitizer;
+// private HPSFittedRawTrackerHitMaker hitMaker;
+ private HPSStripMaker stripClusterer;
+ // private DumbShaperFit shaperFit;
+
+ public void setDebug(boolean debug) {
+ this.debug = true;
+ }
+
+ public void setReadoutCollectionName(String readoutCollectionName) {
+ this.readoutCollectionName = readoutCollectionName;
+ }
+
+ public void setSubdetectorName(String subdetectorName) {
+ this.subdetectorName = subdetectorName;
+ }
+
+ public void setStripHitOutputCollectionName(String stripHitOutputCollectionName) {
+ this.stripHitOutputCollectionName = stripHitOutputCollectionName;
+ }
+
+
+ public void setClusterSeedThreshold(double clusterSeedThreshold) {
+ this.clusterSeedThreshold = clusterSeedThreshold;
+ }
+
+ public void setClusterNeighborThreshold(double clusterNeighborThreshold) {
+ this.clusterNeighborThreshold = clusterNeighborThreshold;
+ }
+
+ public void setClusterThreshold(double clusterThreshold) {
+ this.clusterThreshold = clusterThreshold;
+ }
+
+ public void setClusterMaxSize(int clusterMaxSize) {
+ this.clusterMaxSize = clusterMaxSize;
+ }
+
+ public void setClusterCentralStripAveragingThreshold(int clusterCentralStripAveragingThreshold) {
+ this.clusterCentralStripAveragingThreshold = clusterCentralStripAveragingThreshold;
+ }
+
+ public void setOneClusterErr(double oneClusterErr) {
+ this.oneClusterErr = oneClusterErr;
+ }
+
+ public void setTwoClusterErr(double twoClusterErr) {
+ this.twoClusterErr = twoClusterErr;
+ }
+
+ public void setThreeClusterErr(double threeClusterErr) {
+ this.threeClusterErr = threeClusterErr;
+ }
+
+ public void setFourClusterErr(double fourClusterErr) {
+ this.fourClusterErr = fourClusterErr;
+ }
+
+ public void setFiveClusterErr(double fiveClusterErr) {
+ this.fiveClusterErr = fiveClusterErr;
+ }
+
+ /**
+ * Creates a new instance of TrackerHitDriver.
+ */
+ public DataTrackerHitDriver() {
+ }
+
+ /**
+ * Initializes this Driver's objects with the job parameters.
+ */
+ private void initialize() {
+
+
+ // Create Strip clustering algorithm.
+ HPSNearestNeighborRMS stripClusteringAlgo = new HPSNearestNeighborRMS();
+ stripClusteringAlgo.setSeedThreshold(clusterSeedThreshold);
+ stripClusteringAlgo.setNeighborThreshold(clusterNeighborThreshold);
+ stripClusteringAlgo.setClusterThreshold(clusterThreshold);
+
+// hitMaker=new HPSFittedRawTrackerHitMaker(shaperFit);
+ // Create the clusterers and set hit-making parameters.
+ stripClusterer = new HPSStripMaker( stripClusteringAlgo);
+
+ stripClusterer.setMaxClusterSize(clusterMaxSize);
+ stripClusterer.setCentralStripAveragingThreshold(clusterCentralStripAveragingThreshold);
+
+ // Set the cluster errors.
+ stripClusterer.SetOneClusterErr(oneClusterErr);
+ stripClusterer.SetTwoClusterErr(twoClusterErr);
+ stripClusterer.SetThreeClusterErr(threeClusterErr);
+ stripClusterer.SetFourClusterErr(fourClusterErr);
+ stripClusterer.SetFiveClusterErr(fiveClusterErr);
+
+ // Set the detector to process.
+ processPaths.add(subdetectorName);
+
+ calib=new HPSSVTCalibrationConstants();
+ calib.loadCalibrationConstants("foobar");
+
+ }
+
+ /**
+ * This is executed before detectorChanged and initialization of
+ * digitization objects is done here.
+ */
+ public void startOfData() {
+
+ // At start of job, setup digitization objects needed by this Driver.
+ initialize();
+
+ }
+
+ /**
+ * Do initialization once we get a Detector.
+ */
+ public void detectorChanged(Detector detector) {
+
+ // Call sub-Driver's detectorChanged methods.
+ super.detectorChanged(detector);
+
+ // Process detectors specified by path, otherwise process entire
+ // detector
+ IDetectorElement deDetector = detector.getDetectorElement();
+
+ for (String path : processPaths) {
+ processDEs.add(deDetector.findDetectorElement(path));
+ }
+
+ if (processDEs.size() == 0) {
+ processDEs.add(deDetector);
+ }
+
+ for (IDetectorElement detectorElement : processDEs) {
+ processSensors.addAll(detectorElement.findDescendants(SiSensor.class));
+ //if (debug)
+ // System.out.println("added " + processSensors.size() + " sensors");
+ processModules.addAll(detectorElement.findDescendants(SiTrackerModule.class));
+ //if (debug)
+ // System.out.println("added " + processModules.size() + " modules");
+ }
+ }
+
+ /**
+ * Perform the digitization.
+ */
+ public void process(EventHeader event) {
+ // Call sub-Driver processing.
+ super.process(event);
+
+ // Make new lists for output.
+// List<HPSFittedRawTrackerHit> rawHits = new ArrayList<HPSFittedRawTrackerHit>();
+ List<SiTrackerHit> stripHits1D = new ArrayList<SiTrackerHit>();
+
+// // Make HPS hits.
+// for (SiSensor sensor : processSensors) {
+// rawHits.addAll(hitMaker.makeHits(sensor));
+// }
+
+ // Make strip hits.
+ for (SiSensor sensor : processSensors) {
+ stripHits1D.addAll(stripClusterer.makeHits(sensor));
+ }
+
+ // Debug prints.
+ if (debug) {
+// List<SimTrackerHit> simHits = event.get(SimTrackerHit.class, this.readoutCollectionName);
+// System.out.println("SimTrackerHit collection " + this.readoutCollectionName + " has " + simHits.size() + " hits.");
+// System.out.println("RawTrackerHit collection " + this.rawTrackerHitOutputCollectionName + " has " + rawHits.size() + " hits.");
+ System.out.println("TrackerHit collection " + this.stripHitOutputCollectionName + " has " + stripHits1D.size() + " hits.");
+ }
+
+ // Put output hits into collection.
+ int flag = LCIOUtil.bitSet(0, 31, true); // Turn on 64-bit cell ID.
+// event.put(this.rawTrackerHitOutputCollectionName, rawHits, RawTrackerHit.class, flag, toString());
+ event.put(this.stripHitOutputCollectionName, stripHits1D, SiTrackerHitStrip1D.class, 0, toString());
+ }
+}
hps-java/src/main/java/org/lcsim/hps/users/mgraham
diff -u -r1.2 -r1.3
--- StandAlone.java 16 Nov 2011 18:00:04 -0000 1.2
+++ StandAlone.java 25 Apr 2012 15:23:42 -0000 1.3
@@ -9,6 +9,9 @@
import java.io.File;
import java.io.IOException;
import org.freehep.record.loop.LoopException;
+import org.lcsim.hps.recon.tracking.HPSRawTrackerHitFitterDriver;
+import org.lcsim.hps.recon.tracking.HPSSVTSensorSetup;
+import org.lcsim.recon.tracking.digitization.sisim.config.RawTrackerHitSensorSetup;
import org.lcsim.util.loop.LCSimLoop;
/**
@@ -23,7 +26,7 @@
// Download example file and set as input file
// File file = new File("/Users/mgraham/HPS/HPSData/HPS-Test-JLAB-v2pt0-ap2.2gev80mevsel_1JLAB_200ux20u_beamspot_gammactau_0cm.slcio");
- File file = new File("/Users/mgraham/HPS/HPSData/HPS-Dedicated-v3.4-ap2.2gev40mevsel_1_20u_beamspot_gammactau_0cm.slcio");
+ File file = new File("/Users/mgraham/HPS/HPSData/TestRunReconNew.slcio");
// File file = new File("/Users/mgraham/HPS/HPSData/HPS-Test-v1.8-ap2.2gev80mevsel_21_20ux200u_beamspot_gammactau_0cm.slcio");
//
loop.setLCIORecordSource(file);
@@ -34,8 +37,10 @@
//loop.setStdhepRecordSource(new File("myFile.stdhep"),"sid01");
// Or to read a list of files
//loop.setLCIORecordSource(new LCIOEventSource(new FileList(new File("myFileList.filelist"),"My File List")));
- loop.add(new HeavyPhotonLLDriver());
- loop.loop(10); // 0 means loop forever
+ loop.add(new HPSSVTSensorSetup());
+ loop.add(new RawTrackerHitSensorSetup());
+ loop.add(new HPSRawTrackerHitFitterDriver());
+ loop.loop(5000); // 0 means loop forever
loop.dispose();
}
}
CVSspam 0.2.12