GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TGriffinAngles.cxx
Go to the documentation of this file.
1#include "TGriffinAngles.h"
2#include "TGriffin.h"
3#include "TGRSIOptions.h"
4
5double TGriffinAngles::fRounding = 0.001;
6
7TGriffinAngles::TGriffinAngles(double distance, bool folding, bool grouping, bool addback)
8 : fDistance(distance), fFolding(folding), fGrouping(grouping), fAddback(addback)
9{
10 SetName("GriffinAngles");
11 // get user settings for excluded detectors/crystals, and custom grouping
12 if(TGRSIOptions::Get() != nullptr) {
13 auto* settings = TGRSIOptions::UserSettings();
14 if(settings != nullptr) {
15 // try quietly to get the vectors of excluded crystals and detectors, catching (and disregarding) any exceptions
16 try {
17 fExcludedCrystals = settings->GetIntVector("ExcludedCrystal", true);
18 } catch(std::out_of_range&) {}
19 try {
20 fExcludedDetectors = settings->GetIntVector("ExcludedDetector", true);
21 } catch(std::out_of_range&) {}
22 try {
23 fCustomGrouping = settings->GetIntVector("CustomGrouping", true);
24 std::sort(fCustomGrouping.begin(), fCustomGrouping.end());
25 } catch(std::out_of_range&) {}
26 } else {
27 std::cout << "Failed to find user settings in TGRSIOptions, can't get user settings for excluded detectors/crystals" << std::endl;
28 }
29 } else {
30 std::cout << "Failed to find TGRSIOptions, can't get user settings for excluded detectors/crystals" << std::endl;
31 }
32
33 // check that we only use grouping if folding is also enabled, and we do not have any custom grouping information
34 if(fGrouping && !fFolding && fCustomGrouping.empty()) {
35 std::cout << DRED << "Warning, grouping is only possible if folding is also active. Setting folding to true!" << RESET_COLOR << std::endl;
36 fFolding = true;
37 }
38
39 std::cout << "Creating angles for detectors " << fDistance << " mm from center of array, " << (fAddback ? "" : "not ") << "using addback, " << (fFolding ? "" : "not ") << "using folding, and " << (fGrouping ? "" : "not ") << "using grouping. Any angles less than " << fRounding << " degrees apart will be considered the same." << std::endl;
40
41 // loop over all possible detector/crystal combinations
42 for(int firstDet = 1; firstDet <= 16; ++firstDet) {
43 if(ExcludeDetector(firstDet)) { continue; }
44 for(int firstCry = 0; firstCry < 4; ++firstCry) {
45 if(ExcludeCrystal(firstDet, firstCry)) { continue; }
46 for(int secondDet = 1; secondDet <= 16; ++secondDet) {
47 if(ExcludeDetector(secondDet)) { continue; }
48 for(int secondCry = 0; secondCry < 4; ++secondCry) {
49 if(ExcludeCrystal(secondDet, secondCry)) { continue; }
50 // exclude hits in the same crystal or, if addback is enabled, in the same detector
51 if(firstDet == secondDet && (firstCry == secondCry || fAddback)) { continue; }
52 double angle = TGriffin::GetPosition(firstDet, firstCry, fDistance).Angle(TGriffin::GetPosition(secondDet, secondCry, fDistance)) * 180. / TMath::Pi();
53 // if folding is enable we fold the distribution at 90 degree and only use angles between 0 and 90 degree
54 if(fFolding && angle > 90.) {
55 angle = 180. - angle;
56 }
57 // round down to zero (mainly here for nicer looks)
58 if(angle < fRounding) {
59 angle = 0.;
60 }
61 // if the lower bound and the upper bound are the same we have a new angle
62 if(fAngles.lower_bound(angle - fRounding) == fAngles.upper_bound(angle + fRounding)) {
63 fAngles.insert(angle);
64 }
65 // this should always work, either this is a new angle, in which case it gets initialized to zero and then incremented to one,
66 // or we increment the existing counter
67 // the key is integer, so by dividing by rounding and then casting to integer we can avoid duplicates close to each other
68 // factor 2 to include that the "normal" rounding is +- fRounding
69 fAngleCount[static_cast<int>(std::round(angle / fRounding))]++;
70 } // second crystal loop
71 } //second detector loop
72 } // first crystal loop
73 } // first detector loop
74
75 // create map of indices before we group so that we have an index for each (folded) angle
76 for(auto it = fAngles.begin(); it != fAngles.end(); ++it) {
77 fAngleMap.insert(std::make_pair(*it, std::distance(fAngles.begin(), it)));
78 }
79
80 if(fGrouping) {
81 // If grouping is enable we group angles that are close to each other together.
82 // Which angles are grouped is somewhat arbitrary, this grouping was chosen to get similar numbers of detector combinations and thus statistics for each angle group.
83 // Due to the way lower_bound works, we use the highest angle of each group as the angle of that group.
84 // This is just for the purpose of this algorithm, when plotting the correct average angle of the group should be used!
85
86 // check if we have custom grouping supplied and its format
87 if(!fCustomGrouping.empty()) {
88 if(fCustomGrouping.size() != fAngles.size()) {
89 std::ostringstream str;
90 str << DRED << "Custom grouping with " << fCustomGrouping.size() << " entries supplied, but we have " << fAngles.size() << " angles!" << RESET_COLOR;
91 throw std::runtime_error(str.str());
92 }
93 if(fCustomGrouping[0] != 0) {
94 std::ostringstream str;
95 str << DRED << "Custom grouping with " << fCustomGrouping.size() << " entries supplied, but the first entry is " << fCustomGrouping[0] << ", not 0!" << RESET_COLOR;
96 throw std::runtime_error(str.str());
97 }
98 if(!std::is_sorted(fCustomGrouping.begin(), fCustomGrouping.end())) {
99 std::ostringstream str;
100 str << DRED << "Custom grouping with " << fCustomGrouping.size() << " entries is not sorted!" << RESET_COLOR;
101 throw std::runtime_error(str.str());
102 }
103 auto tmp = fCustomGrouping;
104 auto end = std::unique(tmp.begin(), tmp.end());
105 if(fCustomGrouping.back() != end - tmp.begin() - 1) {
106 std::ostringstream str;
107 str << DRED << "Custom grouping with " << fCustomGrouping.size() << " entries supplied, but the last entry is " << fCustomGrouping[0] << " which does not match the number of unique groups minus one (" << end - tmp.begin() - 1 << ")!" << RESET_COLOR;
108 throw std::runtime_error(str.str());
109 }
110 } else if(fDistance == 110.) {
111 fCustomGrouping = {0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
112 } else if(fDistance == 145.) {
113 fCustomGrouping = {0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11};
114 } else {
115 std::ostringstream str;
116 str << DRED << "No custom grouping supplied and distance is not 110 mm or 145 mm, but " << fDistance << "!" << RESET_COLOR;
117 throw std::runtime_error(str.str());
118 }
119
120 // now we can loop over the grouping vector and the angles and store the largest angle per group in the new groupedAngles vector
121 // we also update our angle map with the new indices
122 std::set<double> groupedAngles;
123 auto angle = fAngles.begin();
124 double previousAngle = *angle;
125 for(size_t i = 0; i < fCustomGrouping.size(); ++i, ++angle) {
126 if(i != 0 && fCustomGrouping[i] != fCustomGrouping[i - 1]) { // we found a new group so we insert the previous angle
127 groupedAngles.insert(previousAngle);
128 }
129 fAngleMap[*angle] = fCustomGrouping[i];
130 previousAngle = *angle;
131 }
132 // add the last angle since we never get to the next group after the last
133 groupedAngles.insert(previousAngle);
134
135 // update the angles to the new grouped angles
136 fAngles = groupedAngles;
137 }
138}
139
140int TGriffinAngles::Index(double angle)
141{
142 auto matches = [angle, this](std::pair<double, int> val) { return std::abs(val.first - angle) < fRounding; };
143 auto it = std::find_if(fAngleMap.begin(), fAngleMap.end(), matches);
144
145 if(it == fAngleMap.end()) {
146 std::cout << "Failed to find angle " << angle << " in map!" << std::endl;
147 return -1;
148 }
149 if(it->second >= static_cast<int>(fAngles.size())) {
150 std::cout << "Found index " << it->second << " for angle " << angle << " which is outside range (" << fAngles.size() << ")" << std::endl;
151 return -1;
152 }
153 return it->second;
154}
155
156double TGriffinAngles::AverageAngle(int index) const
157{
158 double result = 0.;
159 int nofMatches = 0;
160 for(const auto& val : fAngleMap) {
161 if(val.second == index) {
162 result += val.first;
163 ++nofMatches;
164 }
165 }
166 return result / nofMatches;
167}
168
169void TGriffinAngles::FoldOrGroup(TGraphErrors* z0, TGraphErrors* z2, TGraphErrors* z4, bool verbose) const
170{
171 /// Apply folding and/or grouping to the theory graphs.
172 /// This assumes that the theory graphs all have the exact same length of 49 or 51 for singles or addback, respectively.
173
174 // these are simulated data, so if we add points together we take their average as the new value and change the uncertainties accordingly
175#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
176 if(verbose) {
177 std::cout << "-------------------- original --------------------" << std::endl;
178 for(int i = 0; i < z0->GetN(); ++i) {
179 std::cout << std::setw(8) << z0->GetPointX(i) << ": " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
180 }
181 std::cout << "--------------------------------------------------" << std::endl;
182 }
183#endif
184
185 // folding first
186 if(fFolding) {
187 // we first change the angles of the data points, then we re-sort the graphs, and finally we combine points for the same angle into one
188 auto* angle0 = z0->GetX();
189 auto* angle2 = z2->GetX();
190 auto* angle4 = z4->GetX();
191 for(int i = 0; i < z0->GetN(); ++i) {
192 if(angle0[i] > 90.) {
193#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
194 if(verbose) {
195 std::cout << i << ": Folding from " << std::setw(8) << z0->GetPointX(i) << " " << std::setw(8) << z2->GetPointX(i) << " " << std::setw(8) << z4->GetPointX(i);
196 }
197#endif
198 angle0[i] = 180. - angle0[i];
199 angle2[i] = angle0[i];
200 angle4[i] = angle0[i];
201#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
202 if(verbose) {
203 std::cout << " to " << std::setw(8) << z0->GetPointX(i) << " " << std::setw(8) << z2->GetPointX(i) << " " << std::setw(8) << z4->GetPointX(i) << std::endl;
204 }
205#endif
206 }
207 }
208 z0->Sort();
209 z2->Sort();
210 z4->Sort();
211#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
212 if(verbose) {
213 std::cout << "-------------------- sorted --------------------" << std::endl;
214 for(int i = 0; i < z0->GetN(); ++i) {
215 std::cout << std::setw(8) << z0->GetPointX(i) << ": " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
216 }
217 std::cout << "------------------------------------------------" << std::endl;
218 }
219#endif
220 angle0 = z0->GetX();
221 auto* counts0 = z0->GetY();
222 auto* errors0 = z0->GetEY();
223 auto* counts2 = z2->GetY();
224 auto* errors2 = z2->GetEY();
225 auto* counts4 = z4->GetY();
226 auto* errors4 = z4->GetEY();
227 for(int i = 1; i < z0->GetN(); ++i) {
228 if(std::abs(angle0[i] - angle0[i - 1]) < fRounding) {
229 if(verbose) {
230 std::cout << i << ": Adding angles " << angle0[i - 1] << " and " << angle0[i] << std::endl;
231 }
232 // add counts from this point to the previous point, then delete this point, and update our pointers to the data
233 counts0[i - 1] += counts0[i];
234 counts0[i - 1] /= 2.;
235 errors0[i - 1] = TMath::Sqrt(TMath::Power(errors0[i - 1], 2) + TMath::Power(errors0[i], 2)) / 2.;
236 counts2[i - 1] += counts2[i];
237 counts2[i - 1] /= 2.;
238 errors2[i - 1] = TMath::Sqrt(TMath::Power(errors2[i - 1], 2) + TMath::Power(errors2[i], 2)) / 2.;
239 counts4[i - 1] += counts4[i];
240 counts4[i - 1] /= 2.;
241 errors4[i - 1] = TMath::Sqrt(TMath::Power(errors4[i - 1], 2) + TMath::Power(errors4[i], 2)) / 2.;
242 z0->RemovePoint(i);
243 z2->RemovePoint(i);
244 z4->RemovePoint(i);
245 angle0 = z0->GetX();
246 counts0 = z0->GetY();
247 errors0 = z0->GetEY();
248 counts2 = z2->GetY();
249 errors2 = z2->GetEY();
250 counts4 = z4->GetY();
251 errors4 = z4->GetEY();
252 --i; // decrement to re-check the new ith point
253 } else {
254 if(verbose) {
255 std::cout << i << ": Not adding angles " << angle0[i - 1] << " and " << angle0[i] << std::endl;
256 }
257 }
258 }
259 }
260#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
261 if(verbose) {
262 std::cout << "-------------------- after folding --------------------" << std::endl;
263 for(int i = 0; i < z0->GetN(); ++i) {
264 std::cout << std::setw(8) << z0->GetPointX(i) << ": " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
265 }
266 std::cout << "-------------------------------------------------------" << std::endl;
267 }
268#endif
269
270 // grouping
271 if(fGrouping) {
272 // Due to the way lower_bound works, we use the highest angle of each group as the angle of that group.
273 // This is just for the purpose of this algorithm, when plotting the correct average angle of the group should be used!
274 auto* counts0 = z0->GetY();
275 auto* errors0 = z0->GetEY();
276 auto* counts2 = z2->GetY();
277 auto* errors2 = z2->GetEY();
278 auto* counts4 = z4->GetY();
279 auto* errors4 = z4->GetEY();
280 for(int i = 0; i < z0->GetN(); ++i) {
281 switch(i) {
282 case 0:
283 case 1: // first and second angle are not grouped
284#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
285 if(verbose) {
286 std::cout << i << ": Leaving as is " << z0->GetPointX(i) << ": " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
287 }
288#endif
289 break;
290 case 2:
291 case 3:
292 case 4:
293 // three groups of two angles each, so we add the this point to the next one, delete it, and update the pointers
294 // because we delete the point, we don't skip cases here like when we create the angles above
295#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
296 if(verbose) {
297 std::cout << i << ": Grouping " << z0->GetPointX(i) << " and " << z0->GetPointX(i + 1) << " from " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i);
298 }
299#endif
300 counts0[i + 1] += counts0[i];
301 counts0[i + 1] /= 2.;
302 errors0[i + 1] = TMath::Sqrt(TMath::Power(errors0[i], 2) + TMath::Power(errors0[i + 1], 2)) / 2.;
303 counts2[i + 1] += counts2[i];
304 counts2[i + 1] /= 2.;
305 errors2[i + 1] = TMath::Sqrt(TMath::Power(errors2[i], 2) + TMath::Power(errors2[i + 1], 2)) / 2.;
306 counts4[i + 1] += counts4[i];
307 counts4[i + 1] /= 2.;
308 errors4[i + 1] = TMath::Sqrt(TMath::Power(errors4[i], 2) + TMath::Power(errors4[i + 1], 2)) / 2.;
309 z0->RemovePoint(i);
310 z2->RemovePoint(i);
311 z4->RemovePoint(i);
312 counts0 = z0->GetY();
313 errors0 = z0->GetEY();
314 counts2 = z2->GetY();
315 errors2 = z2->GetEY();
316 counts4 = z4->GetY();
317 errors4 = z4->GetEY();
318#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
319 if(verbose) {
320 std::cout << " to " << z0->GetPointX(i) << " with " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
321 }
322#endif
323 // no need to decrement the index, by removing one point the old i+1 became i and we don't want to process that one (we just added to it)
324 break;
325 default:
326 // all others are groups of three, so we add this point and the next one to the one two ahead, delete them, and update the pointers
327#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
328 if(verbose) {
329 std::cout << i << ": Grouping " << z0->GetPointX(i) << ", " << z0->GetPointX(i + 1) << ", and " << z0->GetPointX(i + 2) << " from " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i);
330 }
331#endif
332 counts0[i + 2] += counts0[i] + counts0[i + 1];
333 counts0[i + 2] /= 3.;
334 errors0[i + 2] = TMath::Sqrt(TMath::Power(errors0[i], 2) + TMath::Power(errors0[i + 1], 2) + TMath::Power(errors0[i + 2], 2)) / 3.;
335 counts2[i + 2] += counts2[i] + counts2[i + 1];
336 counts2[i + 2] /= 3.;
337 errors2[i + 2] = TMath::Sqrt(TMath::Power(errors2[i], 2) + TMath::Power(errors2[i + 1], 2) + TMath::Power(errors0[i + 2], 2)) / 3.;
338 counts4[i + 2] += counts4[i] + counts4[i + 1];
339 counts4[i + 2] /= 3.;
340 errors4[i + 2] = TMath::Sqrt(TMath::Power(errors4[i], 2) + TMath::Power(errors4[i + 1], 2) + TMath::Power(errors0[i + 2], 2)) / 3.;
341 z0->RemovePoint(i);
342 z2->RemovePoint(i);
343 z4->RemovePoint(i);
344 z0->RemovePoint(i + 1);
345 z2->RemovePoint(i + 1);
346 z4->RemovePoint(i + 1);
347 counts0 = z0->GetY();
348 errors0 = z0->GetEY();
349 counts2 = z2->GetY();
350 errors2 = z2->GetEY();
351 counts4 = z4->GetY();
352 errors4 = z4->GetEY();
353#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
354 if(verbose) {
355 std::cout << " to " << z0->GetPointX(i) << " with " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
356 }
357#endif
358 // no need to decrement the index, by removing two points the old i+2 became i and we don't want to processs that one since we just added to it
359 break;
360 }
361 }
362 }
363#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 20, 0)
364 if(verbose) {
365 std::cout << "-------------------- after folding and grouping --------------------" << std::endl;
366 for(int i = 0; i < z0->GetN(); ++i) {
367 std::cout << std::setw(8) << z0->GetPointX(i) << ": " << std::setw(8) << z0->GetPointY(i) << " " << std::setw(8) << z2->GetPointY(i) << " " << std::setw(8) << z4->GetPointY(i) << std::endl;
368 }
369 std::cout << "--------------------------------------------------------------------" << std::endl;
370 }
371#endif
372}
373
374bool TGriffinAngles::ExcludeDetector(int detector) const
375{
376 /// Returns true if any of the detectors in fExcludedDetectors matches the given detector.
377 return std::any_of(fExcludedDetectors.begin(), fExcludedDetectors.end(), [&detector](auto exclude) { return detector == exclude; });
378}
379
380bool TGriffinAngles::ExcludeCrystal(int detector, int crystal) const
381{
382 /// Returns true if any of the crystals in fExcludedCrystals matches the given detector and crystal (using 4*(detector-1)+crystal+1).
383 return std::any_of(fExcludedCrystals.begin(), fExcludedCrystals.end(), [&detector, &crystal](auto exclude) { return 4 * (detector - 1) + crystal + 1 == exclude; });
384}
385
386void TGriffinAngles::Print(Option_t*) const
387{
388 std::cout << "List of unique angles " << std::setw(2) << fAngles.size() << " Map from angles to indices " << std::setw(2) << fAngleMap.size() << " # of combinations " << std::setw(2) << fAngleCount.size() << std::endl;
389 //List of unique angles aa Map from angles to indices mm # of combinations cc"<<std::endl;
390 std::cout << "index angle angle index average angle angle counts" << std::endl;
391 //ii: aa.aaaa aa.aaaa ii aa.aaaa aa.aaaa ccc
392 auto it = fAngles.begin();
393 auto it2 = fAngleMap.begin();
394 auto it3 = fAngleCount.begin();
395 while(it != fAngles.end() || it2 != fAngleMap.end() || it3 != fAngleCount.end()) {
396 if(it != fAngles.end()) {
397 std::cout << std::setw(2) << std::distance(fAngles.begin(), it) << ": " << std::setw(7) << *it << " ";
398 ++it;
399 } else {
400 //ii: aa.aaaa aa.aaaa ii aa.aaaa aa.aaaa ccc
401 std::cout << " ";
402 }
403 if(it2 != fAngleMap.end()) {
404 std::cout << std::setw(7) << it2->first << " " << std::setw(2) << it2->second << " " << std::setw(7) << AverageAngle(it2->second) << " ";
405 ++it2;
406 } else {
407 //aa.aaaa ii aa.aaaa aa.aaaa ccc
408 std::cout << " ";
409 }
410 if(it3 != fAngleCount.end()) {
411 std::cout << std::setw(7) << it3->first * fRounding << " " << std::setw(3) << it3->second;
412 ++it3;
413 }
414 std::cout << std::endl;
415 }
416}
#define DRED
Definition Globals.h:18
#define RESET_COLOR
Definition Globals.h:5
static TGRSIOptions * Get(int argc=0, char **argv=nullptr)
Do not use!
static TUserSettings * UserSettings()
std::set< double > fAngles
set of unique angles, when grouping is used, the largest angle of the group is used!
static double fRounding
we consider any angles whose difference is less than this to be equal
void FoldOrGroup(TGraphErrors *z0, TGraphErrors *z2, TGraphErrors *z4, bool verbose=false) const
bool ExcludeDetector(int detector) const
bool fGrouping
flag indicating whether we group close angles together
std::set< double >::iterator end() const
std::vector< int > fCustomGrouping
list of custom groups
void Print(Option_t *="") const override
double fDistance
distance of detector from center of array in mmm
bool fFolding
flag indicating whether we fold our distribution around 90 degree
bool fAddback
flag indicating whether we use addback
TGriffinAngles(double distance=145., bool folding=false, bool grouping=false, bool addback=true)
int Index(double angle)
std::map< int, int > fAngleCount
Maps angles (divided by rounding and cast to integers) to number of combinations contributing to it.
std::vector< int > fExcludedDetectors
list of detectors that are excluded in calculating the angles
std::map< double, int > fAngleMap
Maps angles to indices. This is fairly straight forward without grouping, but if grouping is used mul...
std::vector< int > fExcludedCrystals
list of crystals that are excluded in calculating the angles, the crystals are numbered as 4*(det-1)+...
bool ExcludeCrystal(int detector, int crystal) const
double AverageAngle(int index) const
static TVector3 GetPosition(int DetNbr, int CryNbr=5, double dist=110.0)
!
Definition TGriffin.cxx:501