Skip to content

Commit 67820ed

Browse files
authored
Merge branch 'Application' into MonitorTank
2 parents 32d4981 + cd09794 commit 67820ed

20 files changed

+557
-59
lines changed

UserTools/Factory/Factory.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ if (tool=="TrackCombiner") ret=new TrackCombiner;
9191
if (tool=="SimulatedWaveformDemo") ret=new SimulatedWaveformDemo;
9292
if (tool=="MonitorTankLive") ret=new MonitorTankLive;
9393
if (tool=="MonitorTankTime") ret=new MonitorTankTime;
94-
94+
if (tool=="PhaseIIADCCalibrator") ret=new PhaseIIADCCalibrator;
95+
if (tool=="MCHitToHitComparer") ret=new MCHitToHitComparer;
9596
return ret;
9697
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "MCHitToHitComparer.h"
2+
3+
MCHitToHitComparer::MCHitToHitComparer():Tool(){}
4+
5+
6+
bool MCHitToHitComparer::Initialise(std::string configfile, DataModel &data){
7+
8+
/////////////////// Useful header ///////////////////////
9+
if(configfile!="") m_variables.Initialise(configfile); // loading config file
10+
//m_variables.Print();
11+
12+
m_data= &data; //assigning transient data pointer
13+
/////////////////////////////////////////////////////////////////
14+
m_variables.Get("verbosity",verbosity);
15+
16+
return true;
17+
}
18+
19+
20+
bool MCHitToHitComparer::Execute(){
21+
// Get a pointer to the ANNIEEvent Store
22+
auto* annie_event = m_data->Stores["ANNIEEvent"];
23+
if (!annie_event) {
24+
Log("Error: The MCHitToHitComparer tool could not find the ANNIEEvent Store", v_error,
25+
verbosity);
26+
return false;
27+
}
28+
29+
// Load the map containing WCSim's MCHits
30+
bool got_mchitmap = annie_event->Get("MCHits", mchit_map);
31+
32+
// Check for problems
33+
if ( !got_mchitmap ) {
34+
Log("Error: The MCHitToHitComparer tool could not find a mchits map", v_error,
35+
verbosity);
36+
return false;
37+
}
38+
else if ( mchit_map->empty() ) {
39+
Log("Error: The MCHitToHitComparer tool found an empty mchits map", v_error,
40+
verbosity);
41+
return false;
42+
}
43+
44+
45+
// Load the map containing the ADC raw waveform data
46+
bool got_hitmap = annie_event->Get("Hits", hit_map);
47+
48+
// Check for problems
49+
if ( !got_hitmap ) {
50+
Log("Error: The MCHitToHitComparer tool could not find a hits map", v_error,
51+
verbosity);
52+
return false;
53+
}
54+
else if ( hit_map->empty() ) {
55+
Log("Error: The MCHitToHitComparer tool found an empty hits map", v_error,
56+
verbosity);
57+
return false;
58+
}
59+
//Now, we loop through all the MCHits and Hits for each PMT. Print out stuff to compare
60+
for(std::pair<unsigned long,std::vector<MCHit>>&& temp_pair : *mchit_map){
61+
unsigned long channel_key = temp_pair.first;
62+
std::vector<MCHit>& mchits_vector = temp_pair.second;
63+
for(MCHit& anmchit : mchits_vector){
64+
std::cout << "MCHIT'S ID,TIME, CHARGE: " << anmchit.GetTubeId() << "," <<
65+
anmchit.GetTime() << "," << anmchit.GetCharge() << std::endl;
66+
}
67+
}
68+
for(std::pair<unsigned long,std::vector<Hit>>&& temp_pair : *hit_map){
69+
unsigned long channel_key = temp_pair.first;
70+
std::vector<Hit>& hits_vector = temp_pair.second;
71+
for(Hit& ahit : hits_vector){
72+
std::cout << "HIT'S ID,TIME, CHARGE: " << ahit.GetTubeId() << "," <<
73+
ahit.GetTime() << "," << ahit.GetCharge() << std::endl;
74+
}
75+
}
76+
//TODO: Add some additional checks,
77+
return true;
78+
}
79+
80+
81+
bool MCHitToHitComparer::Finalise(){
82+
83+
return true;
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#ifndef MCHitToHitComparer_H
2+
#define MCHitToHitComparer_H
3+
4+
#include <string>
5+
#include <iostream>
6+
7+
#include "Tool.h"
8+
#include "Hit.h"
9+
10+
/**
11+
* \class MCHitToHitComparer
12+
*
13+
* This tool is used to print time and charge information from the Hits and MCHits maps in the
14+
* ANNIEEvent store. Additional functionality could be added to add hits and MCHits into
15+
* Histograms and show the time/charge distributions in the Finalise loop.
16+
*
17+
* $Author: B.Richards $
18+
* $Date: 2019/05/28 10:44:00 $
19+
20+
*/
21+
class MCHitToHitComparer: public Tool {
22+
23+
24+
public:
25+
26+
MCHitToHitComparer(); ///< Simple constructor
27+
bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools.
28+
bool Execute(); ///< Execute function used to perform Tool purpose.
29+
bool Finalise(); ///< Finalise function used to clean up resources.
30+
31+
32+
private:
33+
std::map<unsigned long,std::vector<Hit>>* hit_map=nullptr;
34+
std::map<unsigned long,std::vector<MCHit>>* mchit_map=nullptr;
35+
36+
/// \brief verbosity levels: if 'verbosity' < this level, the message type will be logged.
37+
int verbosity=1;
38+
int v_error=0;
39+
int v_warning=1;
40+
int v_message=2;
41+
int v_debug=3;
42+
};
43+
44+
45+
#endif
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# MCHitToHitComparer
2+
3+
MCHitToHitComparer
4+
5+
## Data
6+
7+
Describe any data formats MCHitToHitComparer creates, destroys, changes, or analyzes. E.G.
8+
9+
**RawLAPPDData** `map<Geometry, vector<Waveform<double>>>`
10+
* Takes this data from the `ANNIEEvent` store and finds the number of peaks
11+
12+
13+
## Configuration
14+
15+
The MCHitToHitComparer tool is a tool meant for comparing time/charge information in
16+
the MCHits and Hits maps found within the ANNIEEvent store. Currently, this tool
17+
only prints out the time/charge information in each store; however, the tool will
18+
eventually be expanded to display more sophisticated checks, such as time and
19+
charge distributions.
20+
21+
22+
```
23+
verbosity bool
24+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#include <string>
2+
3+
// ToolAnalysis includes
4+
#include "PhaseIIADCCalibrator.h"
5+
6+
PhaseIIADCCalibrator::PhaseIIADCCalibrator() : Tool() {}
7+
8+
bool PhaseIIADCCalibrator::Initialise(std::string config_filename, DataModel& data)
9+
{
10+
// Load configuration file variables
11+
if ( !config_filename.empty() ) m_variables.Initialise(config_filename);
12+
13+
// Assign a transient data pointer
14+
m_data = &data;
15+
16+
return true;
17+
}
18+
19+
bool PhaseIIADCCalibrator::Execute() {
20+
21+
if(verbosity) std::cout<<"Initializing Tool PhaseIIADCCalibrator"<<std::endl;
22+
23+
m_variables.Get("verbosity", verbosity);
24+
m_variables.Get("PCritical", p_critical);
25+
m_variables.Get("NumBaselineSamples", num_baseline_samples);
26+
27+
// Get a pointer to the ANNIEEvent Store
28+
auto* annie_event = m_data->Stores["ANNIEEvent"];
29+
30+
if (!annie_event) {
31+
Log("Error: The PhaseIIADCCalibrator tool could not find the ANNIEEvent Store", 0,
32+
verbosity);
33+
return false;
34+
}
35+
36+
// Load the map containing the ADC raw waveform data
37+
std::map<unsigned long, std::vector<Waveform<unsigned short> > >
38+
raw_waveform_map;
39+
40+
bool got_raw_data = annie_event->Get("RawADCData", raw_waveform_map);
41+
42+
// Check for problems
43+
if ( !got_raw_data ) {
44+
Log("Error: The PhaseIIADCCalibrator tool could not find the RawADCData entry", 0,
45+
verbosity);
46+
return false;
47+
}
48+
else if ( raw_waveform_map.empty() ) {
49+
Log("Error: The PhaseIIADCCalibrator tool found an empty RawADCData entry", 0,
50+
verbosity);
51+
return false;
52+
}
53+
54+
// Build the calibrated waveforms
55+
std::map<unsigned long, std::vector<CalibratedADCWaveform<double> > >
56+
calibrated_waveform_map;
57+
58+
for (const auto& temp_pair : raw_waveform_map) {
59+
const auto& channel_key = temp_pair.first;
60+
const auto& raw_waveforms = temp_pair.second;
61+
62+
Log("Making calibrated waveforms for ADC channel " +
63+
std::to_string(channel_key), 3, verbosity);
64+
65+
calibrated_waveform_map[channel_key] = make_calibrated_waveforms(
66+
raw_waveforms);
67+
}
68+
69+
annie_event->Set("CalibratedADCData", calibrated_waveform_map);
70+
71+
return true;
72+
}
73+
74+
75+
bool PhaseIIADCCalibrator::Finalise() {
76+
return true;
77+
}
78+
79+
void PhaseIIADCCalibrator::ze3ra_baseline(
80+
const std::vector< Waveform<unsigned short> >& raw_data,
81+
double& baseline, double& sigma_baseline, size_t num_baseline_samples)
82+
{
83+
84+
// Signal ADC means, variances, and F-distribution probability values
85+
// ("P") for the first num_baseline_samples from each minibuffer
86+
// (in Hefty mode) or from each sub-minibuffer (in non-Hefty mode)
87+
std::vector<double> means;
88+
std::vector<double> variances;
89+
std::vector<double> Ps;
90+
91+
// Compute the signal ADC mean and variance for each raw data minibuffer
92+
for (size_t mb = 0; mb < raw_data.size(); ++mb) {
93+
const auto& mb_data = raw_data.at(mb).Samples();
94+
95+
double mean, var;
96+
ComputeMeanAndVariance(mb_data, mean, var, num_baseline_samples);
97+
98+
means.push_back(mean);
99+
variances.push_back(var);
100+
}
101+
102+
// Compute probabilities for the F-distribution test for each minibuffer
103+
for (size_t j = 0; j < variances.size() - 1; ++j) {
104+
double sigma2_j = variances.at(j);
105+
double sigma2_jp1 = variances.at(j + 1);
106+
double F;
107+
if (sigma2_j > sigma2_jp1) F = sigma2_j / sigma2_jp1;
108+
else F = sigma2_jp1 / sigma2_j;
109+
110+
double nu = (num_baseline_samples - 1) / 2.;
111+
double P = annie_math::Regularized_Beta_Function(1. / (1. + F), nu, nu);
112+
113+
// Two-tailed hypothesis test (we need to exclude unusually small values
114+
// as well as unusually large ones). The tails have equal sizes, so we
115+
// may use symmetry and simply multiply our earlier result by 2.
116+
P *= 2.;
117+
118+
// I've never seen this problem (the numerical values for the regularized
119+
// beta function that I've checked all fall within [0,1]), but the book
120+
// Numerical Recipes includes this check in a similar block of code,
121+
// so I'll add it just in case.
122+
if (P > 1.) P = 2. - P;
123+
124+
Ps.push_back(P);
125+
}
126+
127+
// Compute the mean and standard deviation of the baseline signal
128+
// for this RawChannel using the mean and standard deviation from
129+
// each minibuffer whose F-distribution probability falls below
130+
// the critical value.
131+
baseline = 0.;
132+
sigma_baseline = 0.;
133+
double variance_baseline = 0.;
134+
size_t num_passing = 0;
135+
for (size_t k = 0; k < Ps.size(); ++k) {
136+
if (Ps.at(k) > p_critical) {
137+
++num_passing;
138+
baseline += means.at(k);
139+
variance_baseline += variances.at(k);
140+
}
141+
}
142+
143+
if (num_passing > 1) {
144+
baseline /= num_passing;
145+
146+
variance_baseline *= static_cast<double>(num_baseline_samples - 1)
147+
/ (num_passing*num_baseline_samples - 1);
148+
// Now that we've combined the sample variances correctly, take the
149+
// square root to get the standard deviation
150+
sigma_baseline = std::sqrt( variance_baseline );
151+
}
152+
else if (num_passing == 1) {
153+
// We only have one set of sample statistics, so all we need to
154+
// do is take the square root of the variance to get the standard
155+
// deviation.
156+
sigma_baseline = std::sqrt( variance_baseline );
157+
}
158+
else {
159+
// If none of the minibuffers passed the F-distribution test,
160+
// choose the one closest to passing (i.e., the one with the largest
161+
// P-value) and adopt its baseline statistics. For a sufficiently large
162+
// number of minibuffers (e.g., 40), such a situation should be very rare.
163+
// TODO: consider changing this approach
164+
auto max_iter = std::max_element(Ps.cbegin(), Ps.cend());
165+
int max_index = std::distance(Ps.cbegin(), max_iter);
166+
167+
baseline = means.at(max_index);
168+
sigma_baseline = std::sqrt( variances.at(max_index) );
169+
}
170+
171+
std::string mb_temp_string = "minibuffer";
172+
173+
if (verbosity >= 4) {
174+
for ( size_t x = 0; x < Ps.size(); ++x ) {
175+
Log(" " + mb_temp_string + " " + std::to_string(x) + ", mean = "
176+
+ std::to_string(means.at(x)) + ", var = "
177+
+ std::to_string(variances.at(x)) + ", p-value = "
178+
+ std::to_string(Ps.at(x)), 4, verbosity);
179+
}
180+
}
181+
182+
Log(std::to_string(num_passing) + " " + mb_temp_string + " pairs passed the"
183+
" F-test", 3, verbosity);
184+
Log("Baseline estimate: " + std::to_string(baseline) + " ± "
185+
+ std::to_string(sigma_baseline) + " ADC counts", 3, verbosity);
186+
187+
}
188+
189+
std::vector< CalibratedADCWaveform<double> >
190+
PhaseIIADCCalibrator::make_calibrated_waveforms(
191+
const std::vector< Waveform<unsigned short> >& raw_waveforms)
192+
{
193+
194+
// Determine the baseline for the set of raw waveforms (assumed to all
195+
// come from the same readout for the same channel)
196+
double baseline, sigma_baseline;
197+
ze3ra_baseline(raw_waveforms, baseline, sigma_baseline,
198+
num_baseline_samples);
199+
200+
std::vector< CalibratedADCWaveform<double> > calibrated_waveforms;
201+
for (const auto& raw_waveform : raw_waveforms) {
202+
203+
std::vector<double> cal_data;
204+
const std::vector<unsigned short>& raw_data = raw_waveform.Samples();
205+
206+
for (const auto& sample : raw_data) {
207+
cal_data.push_back((static_cast<double>(sample) - baseline)
208+
* ADC_TO_VOLT);
209+
}
210+
211+
calibrated_waveforms.emplace_back(raw_waveform.GetStartTime(),
212+
cal_data, baseline, sigma_baseline);
213+
}
214+
215+
return calibrated_waveforms;
216+
}

0 commit comments

Comments
 (0)