61{
62 using namespace std;
64
68 typedef JContainer< set<JTransmission_t> > disable_container;
69
70 JMultipleFileScanner<JEvent> inputFile;
71 JFileRecorder<JTYPELIST<JEvt, JEvent, JFitParameters, JMeta, TH1D, TH2D>::typelist> outputFile;
72 string detectorFile;
73 JLimit_t& numberOfEvents = inputFile.getLimit();
79 disable_container disable;
80 JROOTClassSelection selection = getROOTClassSelection<JTYPELIST<JEvent>::typelist>();
81 JRange<double> utc;
82 bool squash;
83 Long64_t autoflush;
84 int debug;
85
86 try {
87
88 JParser<> zap("Application to fit position calibration model to acoustic data.");
89
90 zap['f'] = make_field(inputFile, "output of JAcousticEventBuilder[.sh]");
91 zap['o'] = make_field(outputFile);
92 zap['n'] = make_field(numberOfEvents) = JLimit::max();
93 zap['a'] = make_field(detectorFile);
94 zap['@'] = make_field(parameters) = JPARSER::initialised();
95 zap['V'] = make_field(V, "sound velocity") = JPARSER::initialised();
96 zap['T'] = make_field(tripods, "tripod data");
97 zap['Y'] = make_field(transmitters, "transmitter data") = JPARSER::initialised();
98 zap['H'] = make_field(hydrophones, "hydrophone data") = JPARSER::initialised();
99 zap['M'] = make_field(getMechanics, "mechanics data") = JPARSER::initialised();
100 zap['!'] = make_field(disable, "disable transmission") = JPARSER::initialised();
101 zap['C'] = make_field(selection,
102 "Precede name of data structure by a '+' or '-' "
103 "to add or remove data types in the output, respectively."
104 "\nROOT wildcards are accepted.") = JPARSER::initialised();
105 zap['u'] = make_field(utc, "select UTC time range") = JRange<double>();
106 zap['q'] = make_field(squash, "squash meta data");
107 zap['R'] = make_field(autoflush) = 5000;
108 zap['d'] = make_field(debug) = 1;
109
110 zap(argc, argv);
111 }
112 catch(const exception &error) {
113 FATAL(error.what() << endl);
114 }
115
116
117 JDetector detector;
118
119 try {
120 load(detectorFile, detector);
121 }
122 catch(const JException& error) {
123 FATAL(error);
124 }
125
126 const floor_range range = getRangeOfFloors(detector);
127
128 JHashMap<int, JLocation> receivers;
129 JHashMap<int, JEmitter> emitters;
130
131 for (JDetector::const_iterator i = detector.begin(); i != detector.end(); ++i) {
132 receivers[i->getID()] = i->getLocation();
133 }
134
135 for (tripods_container::const_iterator i = tripods.begin(); i != tripods.end(); ++i) {
136 emitters[i->getID()] =
JEmitter(i->getID(), i->getUTMPosition() - detector.getUTMPosition());
137 }
138
139 for (transmitters_container::const_iterator i = transmitters.begin(); i != transmitters.end(); ++i) {
140 try {
141 emitters[i->getID()] =
JEmitter(i->getID(), i->getPosition() + detector.getModule(i->getLocation()).getPosition());
142 }
143 catch(const exception&) {}
144 }
145
146 V.
set(detector.getUTMZ());
147
148 JGeometry geometry(detector, hydrophones);
150
153
154 DEBUG(geometry);
155
156 typedef vector<JHit> data_type;
157
158 TH1D h0("chi2/NDF", NULL, 50000, 0.0, 1000.0);
159 TH1D h1("h1", NULL, 51, -0.5, 50.5);
160 TH1D hn("hn", NULL, 100, 0.0, 6.0);
161
162 JManager<int, TH2D> HA(new TH2D("ha[%]", NULL,
163 getNumberOfStrings(detector) + 0, -0.5, getNumberOfStrings(detector) - 0.5,
164 range.getLength() + 1, range.getLowerLimit() - 0.5, range.getUpperLimit() + 0.5));
165
166 JManager<int, TH2D> HB(new TH2D("hb[%]", NULL,
167 getNumberOfStrings(detector) + 0, -0.5, getNumberOfStrings(detector) - 0.5,
168 range.getLength() + 1, range.getLowerLimit() - 0.5, range.getUpperLimit() + 0.5));
169
170 for (Int_t i = 1; i <= HA->GetXaxis()->GetNbins(); ++i) {
171 HA->GetXaxis()->SetBinLabel(i, MAKE_CSTRING(geometry.at(i-1).first));
172 HB->GetXaxis()->SetBinLabel(i, MAKE_CSTRING(geometry.at(i-1).first));
173 }
174
175 if (inputFile.size() > 1u) {
176
177 map<double, string> zmap;
178
179 for (const string& file_name : inputFile) {
180
181 STATUS(file_name << '\r'); DEBUG(endl);
182
183 for (JSingleFileScanner<JEvent> in(file_name, 1); in.hasNext(); ) {
184
185 const JEvent* evt = in.next();
186
189 }
190
191 if (!evt->empty()) {
192 zmap[evt->begin()->getToE()] = file_name;
193 }
194 }
195 }
196 STATUS(endl);
197
198 inputFile.clear();
199
200 for (map<double, string>::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
201 inputFile.push_back(i->second);
202 }
203 }
204
205 outputFile.open();
206
207 outputFile.put(JMeta(argc, argv));
208 outputFile.put(parameters);
209
210 try {
211 dynamic_cast<JTreeWriterObjectOutput<JEvent>&>(*outputFile).getTreeWriter().SetAutoFlush(autoflush);
212 dynamic_cast<JTreeWriterObjectOutput<JEvent>&>(*outputFile).getTreeWriter().SetCacheSize();
213 }
214 catch(const exception&) {}
215
216 int counter[] = { 0, 0 };
217
218 typedef deque<JEvent> buffer_type;
219
220 for (buffer_type zbuf; inputFile.hasNext(); ) {
221
222 STATUS(inputFile.getFilename() << '\r'); DEBUG(endl);
223
224
225
226 for (const string file_name = inputFile.getFilename(); inputFile.hasNext() && file_name == inputFile.getFilename(); ) {
227
228 const JEvent* evt = inputFile.next();
229
230 if (!evt->empty() && emitters.has(evt->
getID())) {
231 if (utc(evt->begin()->getToA()) && utc(evt->rbegin()->getToA())) {
232 zbuf.push_back(*evt);
233 }
234 }
235 }
236
237 sort(zbuf.begin(), zbuf.end());
238
239 for (buffer_type::iterator p = zbuf.begin(), q; p != zbuf.end(); p = q) {
240
241 for (q = p; ++q != zbuf.end() && q->begin()->getToE() <= p->rbegin()->getToE() + parameters.
Tmax_s; ) {}
242
243 if (q == zbuf.end()) {
244
245 if (inputFile.hasNext()) {
246
247 zbuf.erase(zbuf.begin(), p);
248
249 break;
250 }
251 }
252
254
256
258
260
261 data_type data;
262
263 for (buffer_type::iterator evt = p; evt != q; ++evt) {
264
266
267 JEvent::iterator __end = unique(evt->begin(), evt->end(), make_comparator(&JTransmission::getID, JComparison::eq()));
268
271
272 for (JEvent::const_iterator i = evt->begin(); i != __end; ++i) {
273
276
277 if (receivers.has(i->getID()) && geometry.hasLocation(receivers[i->getID()]) && i->getQ() >= parameters.
Qmin * (parameters.
Qmin <= 1.0 ? i->getW() : 1.0)) {
278
279 data.push_back(
JHit(emitter,
280 distance(p,evt),
281 receivers[i->getID()],
282 i->getToA(),
284 weight));
285 }
286 }
287 }
288 }
289
291
292 for (data_type::const_iterator hit = data.begin(); hit != data.end(); ++hit) {
293 HA[hit->getID()]->Fill(geometry.getIndex(hit->getString()), hit->getFloor(), 1.0);
294 }
295
296
297
298 const auto result = katoomba(data.begin(), data.end());
299
300 for (data_type::const_iterator hit = result.begin; hit != result.end; ++hit) {
301 HB[hit->getID()]->Fill(geometry.getIndex(hit->getString()), hit->getFloor(), 1.0);
302 }
303
304 if (debug >= debug_t) {
305
306 cout << "result:" << ' '
307 << FIXED(12,3) << result.chi2 << '/' << FIXED(6,1) << result.ndf << endl
308 << result.value << endl;
309
310 for (data_type::const_iterator hit = result.begin; hit != result.end; ++hit) {
311 cout << "hit: " << *hit << ' ' << FIXED(9,3) << katoomba.evaluator(result.value, *hit) << endl;
312 }
313 }
314
315 hn.Fill(log10(katoomba.gandalf.numberOfIterations));
316 h0.Fill(result.chi2 / result.ndf);
317
318
319
322
324 result.getTimeRange(),
325 data .size(),
326 result.size(),
327 result.value.getN(),
328 result.ndf,
329 result.chi2,
330 katoomba.gandalf.numberOfIterations),
331 result.value);
332
333 outputFile.put(evt);
334
335 if (selection.is_valid<
JEvent>()) {
336
337 for (buffer_type::iterator i = p; i != q; ++i) {
338
340
341 const double toe = result.value.emission[
JEKey(i->getID(), distance(p,i))].t1;
342
343 for (JEvent::iterator hit = out.begin(); hit != out.end(); ++hit) {
344 hit->setToE(toe);
345 }
346
347 if (!out.empty()) {
348 outputFile.put(out);
349 }
350 }
351 }
352
353 counter[0] += 1;
354
355 } else {
356
357 WARNING(endl << "Event not written - chi2/NDF " << FIXED(12,3) << result.chi2 << '/' << FIXED(6,1) << result.ndf << endl);
358
359 counter[1] += 1;
360 }
361
362 } else {
363
364 WARNING(endl <<
"Event not accepted - minimum number of emitters " <<
getMinimumNumberOfEmitters(data.begin(), data.end()) << endl);
365
366 counter[1] += 1;
367 }
368 }
369 }
370 }
371 STATUS(endl);
372
373 STATUS("Number of events written / rejected: " << counter[0] << " / " << counter[1] << endl);
374
375 if (!squash) {
376
377 JMultipleFileScanner<JMeta> io(inputFile);
378
379 io >> outputFile;
380 }
381
382 outputFile.put(h0);
383 outputFile.put(h1);
384 outputFile.put(hn);
385
386 for (JManager<int, TH2D>::const_iterator i = HA.begin(); i != HA.end(); ++i) { outputFile.put(*(i->second)); }
387 for (JManager<int, TH2D>::const_iterator i = HB.begin(); i != HB.end(); ++i) { outputFile.put(*(i->second)); }
388
389 outputFile.close();
390}
size_t getMinimumNumberOfEmitters(T __begin, T __end)
Get minimum number of emitters for any string in data.
double getWeight(T __begin, T __end)
Get total weight of data points.
JContainer< std::vector< JTripod > > tripods_container
JContainer< std::vector< JTransmitter > > transmitters_container
JContainer< std::vector< JHydrophone > > hydrophones_container
size_t getNumberOfEmitters(T __begin, T __end)
Get number of emitters.
int getID() const
Get emitter identifier.
const int getDetectorID() const
Get detector identifier.
double Qmin
minimal quality transmission
double deadTime_s
dead time between events [s]
size_t Nmin
minimum number of emitters
double sigma_s
time-of-arrival resolution [s]
double Tmax_s
time window to combine events [s]
double chi2perNDF
maximal chi2/NDF to store event
Global fit of prameterised detector geometry to acoustics data.
Template definition of fit function of acoustic model.
Implementation for depth dependend velocity of sound.
JSoundVelocity & set(const double z0)
Set depth.
Acoustic transmission identifier.
Auxiliary data structure to unify weights of acoustics data according to the number of pings per emit...
Auxiliary data structure to convert model to event.