Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaVDCPlane.cxx
Go to the documentation of this file.
1
2// //
3// THaVDCPlane //
4// //
6// //
7// Here: //
8// Units of measurements: //
9// For cluster position (center) and size - wires; //
10// For X, Y, and Z coordinates of track - meters; //
11// For Theta and Phi angles of track - in tangents. //
12// //
14
15//#define CLUST_RAWDATA_HACK
16
17#include "THaVDC.h"
18#include "THaVDCPlane.h"
19#include "THaVDCWire.h"
20#include "THaVDCChamber.h"
21#include "THaVDCCluster.h"
22#include "THaVDCHit.h"
23#include "THaDetMap.h"
25#include "THaEvData.h"
26#include "TString.h"
27#include "TClass.h"
28#include "TMath.h"
29#include "VarDef.h"
30#include "THaApparatus.h"
31#include "Helper.h"
32
33#include <cstring>
34#include <vector>
35#include <iostream>
36#include <cassert>
37#include <stdexcept>
38#include <set>
39#include <iomanip>
40
41#ifdef CLUST_RAWDATA_HACK
42#include <fstream>
43#endif
44
45using namespace std;
46
47//_____________________________________________________________________________
48THaVDCPlane::THaVDCPlane( const char* name, const char* description,
49 THaDetectorBase* parent ) :
50 THaSubDetector(name, description, parent),
51 // Since TCloneArrays can resize, the size here is fairly unimportant
52 fWires{new TClonesArray("THaVDCWire", 368)},
53 fHits{new TClonesArray("THaVDCHit", 20)},
54 fClusters{new TClonesArray("THaVDCCluster", 5)},
55 fNHits(0), fNWiresHit(0), fNpass(0), fMinClustSize(0),
56 fMaxClustSpan(kMaxInt), fNMaxGap(0), fMinTime(0), fMaxTime(kMaxInt),
57 fMaxThits(0), fMinTdiff(0), fMaxTdiff(kBig), fTDCRes(0), fDriftVel(0),
58 fT0Resolution(0), fOnlyFastestHit(false), fNoNegativeTime(false),
59 fWBeg(0), fWSpac(0), fWAngle(0), fSinWAngle(0),
60 fCosWAngle(1), /*fTable(0),*/ fTTDConv(nullptr),
61 fVDC{dynamic_cast<THaVDC*>( GetMainDetector() )},
62 fMaxData(kMaxUInt), fNextHit(0), fPrevWire(nullptr)
63{
64 // Constructor
65}
66
67//_____________________________________________________________________________
69{
70 // Destructor.
71
73 delete fWires;
74 delete fHits;
75 delete fClusters;
76 delete fTTDConv;
77// delete [] fTable;
78}
79
80//_____________________________________________________________________________
82{
83 // Special treatment of the prefix for VDC planes: We don't want variable
84 // names such as "R.vdc.uv1.u.x", but rather "R.vdc.u1.x".
85
86 TString basename;
87 THaDetectorBase* uv_plane = GetParent();
88
89 if( fVDC )
90 basename = fVDC->GetPrefix();
91 if( fName.Contains("u") )
92 basename.Append("u");
93 else if ( fName.Contains("v") )
94 basename.Append("v");
95 if( uv_plane && strstr( uv_plane->GetName(), "uv1" ))
96 basename.Append("1.");
97 else if( uv_plane && strstr( uv_plane->GetName(), "uv2" ))
98 basename.Append("2.");
99 if( basename.Length() == 0 )
100 basename = fName + ".";
101
102 delete [] fPrefix;
103 fPrefix = new char[ basename.Length()+1 ];
104 strcpy( fPrefix, basename.Data() );
105}
106
107//_____________________________________________________________________________
109{
110 // Load VDCPlane parameters from database
111
112 const char* const here = "ReadDatabase";
113
114 FILE* file = OpenFile(date);
115 if( !file ) return kFileError;
116
117 // Read fCenter and fSize
118 Int_t err = ReadGeometry(file, date);
119 if( err ) {
120 fclose(file);
121 return err;
122 }
123
124 // Read configuration parameters
125 vector<Int_t> detmap, bad_wirelist;
126 vector<Double_t> ttd_param;
127 vector<Float_t> tdc_offsets;
128 TString ttd_conv = "AnalyticTTDConv";
129 // Default values for optional parameters
130 fTDCRes = 5.0e-10; // 0.5 ns/chan = 5e-10 s /chan
131 fT0Resolution = 6e-8; // 60 ns --- crude guess
132 fMinClustSize = 3;
133 fMaxClustSpan = 7;
134 fNMaxGap = 1;
135 fMinTime = 800;
136 fMaxTime = 2200;
137 fMinTdiff = 3e-8; // 30ns -> ~20 deg track angle
138 fMaxTdiff = 2.0e-7; // 200ns -> ~67 deg track angle
139 fMaxThits = 6; // current TDC setting is to record only the last 6 hits
140 DBRequest request[] = {
141 { "detmap", &detmap, kIntV },
142 { "nwires", &fNelem, kInt, 0, false, -1 },
143 { "wire.start", &fWBeg, kDouble },
144 { "wire.spacing", &fWSpac, kDouble, 0, false, -1 },
145 { "wire.angle", &fWAngle, kDouble },
146 { "wire.badlist", &bad_wirelist, kIntV, 0, true },
147 { "driftvel", &fDriftVel, kDouble, 0, false, -1 },
148 { "tdc.min", &fMinTime, kInt, 0, true, -1 },
149 { "tdc.max", &fMaxTime, kInt, 0, true, -1 },
150 { "tdc.hits" , &fMaxThits, kUInt, 0, true, -1 },
151 { "tdc.res", &fTDCRes, kDouble, 0, false, -1 },
152 { "tdc.offsets", &tdc_offsets, kFloatV },
153 { "ttd.converter", &ttd_conv, kTString, 0, true, -1 },
154 { "ttd.param", &ttd_param, kDoubleV, 0, false, -1 },
155 { "t0.res", &fT0Resolution, kDouble, 0, true, -1 },
156 { "clust.minsize", &fMinClustSize, kInt, 0, true, -1 },
157 { "clust.maxspan", &fMaxClustSpan, kInt, 0, true, -1 },
158 { "maxgap", &fNMaxGap, kInt, 0, true, -1 },
159 { "tdiff.min", &fMinTdiff, kDouble, 0, true, -1 },
160 { "tdiff.max", &fMaxTdiff, kDouble, 0, true, -1 },
161 { "description", &fTitle, kTString, 0, true },
162 { nullptr }
163 };
164
165 err = LoadDB(file, date, request, fPrefix);
166 fclose(file);
167 if( err )
168 return err;
169
171 return kInitError; // Error already printed by FillDetMap
172
173 // All our frontend modules are common stop TDCs
174 UInt_t nmodules = fDetMap->GetSize();
175 for( UInt_t i = 0; i < nmodules; i++ ) {
177 d->MakeTDC();
178 d->SetTDCMode(false);
179 }
180
181 err = ReadDatabaseErrcheck(tdc_offsets, here);
182 if( err )
183 return err;
184
185 // Derived geometry quantities
189
190 if( fVDC ) {
191 // The parent VDC should be initialized at this point
192 assert(fVDC->Status() == kOK);
193
195
196 // If true, add only the first (earliest) hit for each wire
198 // If true, ignore negative drift times completely
200 } else
201 DefineAxes(0);
202
203 // Searchable list of bad wire numbers, if any (usually none :-) )
204 set<Int_t> bad_wires(ALL(bad_wirelist));
205 bad_wirelist.clear();
206 bad_wirelist.shrink_to_fit();
207
208 // Create time-to-distance converter
209 if( !ttd_conv.Contains("::") )
210 ttd_conv.Prepend("VDC::");
211 err = CreateTTDConv(ttd_conv, ttd_param, here);
212 if( err )
213 return err;
214
215 // Initialize wires
216 for( int i = 0; i < fNelem; i++ ) {
217 auto* wire = new((*fWires)[i])
218 THaVDCWire(i, fWBeg + i * fWSpac, tdc_offsets[i], fTTDConv);
219 if( bad_wires.find(i) != bad_wires.end() )
220 wire->SetFlag(1);
221 }
222
223#ifdef WITH_DEBUG
224 if( fDebug > 2 ) {
226 Double_t pos[3]; fCenter.GetXYZ(pos);
228 DBRequest list[] = {
229 { "Number of wires", &fNelem, kInt },
230 { "Detector origin", org, kDouble, 3 },
231 { "Detector pos VDC coord", pos, kDouble, 3 },
232 { "Detector size", fSize, kDouble, 3 },
233 { "Wire angle (deg)", &angle },
234 { "Wire start pos (m)", &fWBeg },
235 { "Wire spacing (m)", &fWSpac },
236 { "TDC resolution (s/chan)", &fTDCRes },
237 { "Drift Velocity (m/s) ", &fDriftVel },
238 { "Min TDC raw time", &fMinTime, kInt },
239 { "Max TDC raw time", &fMaxTime, kInt },
240 { "Min adj wire tdiff (s)", &fMinTdiff },
241 { "Max adj wire tdiff (s)", &fMaxTdiff },
242 { "Time-to-dist conv param", &ttd_param, kDoubleV },
243 { "Max gap in cluster", &fNMaxGap, kInt },
244 { "Min cluster size", &fMinClustSize, kInt },
245 { "Max cluster span", &fMaxClustSpan, kInt },
246 { "t0 resolution (s)", &fT0Resolution },
247 { nullptr }
248 };
249 DebugPrint( list );
250 }
251#endif
252
253 fIsInit = true;
254 return kOK;
255}
256
257//_____________________________________________________________________________
259{
260 // Custom geometry reader for VDC planes.
261 //
262 // Reads:
263 // "position": Plane center in VDC coordinate system (m) -> fCenter
264 // This parameter is required because we need Z
265 // "size": full x/y/z size of active area (m) -> fSize
266 // This parameter is optional, but recommended
267 // If not given, defaults for the HRS VDCs are used
268
269 const char* const here = "ReadGeometry";
270
271 vector<Double_t> position, size;
272 DBRequest request[] = {
273 { "position", &position, kDoubleV, 0, false, 0, "\"position\" (detector position [m])" },
274 { "size", &size, kDoubleV, 0, true, 0, "\"size\" (detector size [m])" },
275 { nullptr }
276 };
277 Int_t err = LoadDB( file, date, request );
278 if( err )
279 return kInitError;
280
281 assert( !position.empty() ); // else LoadDB didn't honor "required" flag
282 err = ReadGeometryErrcheck(position, size, here);
283 if( err )
284 return err;
285
286 fCenter.SetXYZ( position[0], position[1], position[2] );
287
288 if( !size.empty() ) {
289 fSize[0] = 0.5 * TMath::Abs(size[0]);
290 fSize[1] = 0.5 * TMath::Abs(size[1]);
291 fSize[2] = TMath::Abs(size[2]);
292 }
293 else {
294 // Conservative defaults for HRS VDCs
295 // NB: these are used by the IsInActiveArea cut in THaVDCChamber::
296 // MatchUVClusters. Too small values lead to loss of acceptance.
297 fSize[0] = 1.2; // half size
298 fSize[1] = 0.2; // half size
299 fSize[2] = 0.026;
300 }
301
302 return 0;
303}
304
305//_____________________________________________________________________________
306Int_t THaVDCPlane::ReadDatabaseErrcheck( const vector<Float_t>& tdc_offsets,
307 const char* here ) {
308 // Sanity checks
309 if( fNelem <= 0 ) {
310 Error(Here(here), "Invalid number of wires: %d", fNelem);
311 return kInitError;
312 }
313 UInt_t nwires = fNelem;
314 UInt_t nchan = fDetMap->GetTotNumChan();
315 if( nchan != nwires ) {
316 Error(Here(here),
317 "Number of detector map channels (%u) disagrees with "
318 "number of wires (%u)", nchan, nwires);
319 return kInitError;
320 }
321 nchan = tdc_offsets.size();
322 if( nchan != nwires ) {
323 Error(Here(here),
324 "Number of TDC offset values (%u) disagrees with "
325 "number of wires (%u)", nchan, nwires);
326 return kInitError;
327 }
328
329 if( fMinClustSize < 1 || fMinClustSize > 6 ) {
330 Error(Here(here),
331 "Invalid min_clust_size = %d, must be between 1 and 6. "
332 "Fix database.", fMinClustSize);
333 return kInitError;
334 }
335 if( fMaxClustSpan < 2 || fMaxClustSpan > 12 ) {
336 Error(Here(here),
337 "Invalid max_clust_span = %d, must be between 1 and 12. "
338 "Fix database.", fMaxClustSpan);
339 return kInitError;
340 }
341 if( fNMaxGap < 0 || fNMaxGap > 2 ) {
342 Error(Here(here),
343 "Invalid max_gap = %d, must be between 0 and 2. Fix database.",
344 fNMaxGap);
345 return kInitError;
346 }
347 if( fMinTime < 0 || fMinTime > 4095 ) {
348 Error(Here(here),
349 "Invalid min_time = %d, must be between 0 and 4095. Fix database.",
350 fMinTime);
351 return kInitError;
352 }
353 if( fMaxTime < 1 || fMaxTime > 4096 || fMinTime >= fMaxTime ) {
354 Error(Here(here),
355 "Invalid max_time = %d. Must be between 1 and 4096 "
356 "and >= min_time = %d. Fix database.", fMaxTime, fMinTime);
357 return kInitError;
358 }
359 return kOK;
360}
361
362//_____________________________________________________________________________
363Int_t THaVDCPlane::ReadGeometryErrcheck( const vector<Double_t>& position,
364 const vector<Double_t>& size,
365 const char* const here )
366{
367 if( position.size() != 3 ) {
368 Error( Here(here), "Incorrect number of values = %u for "
369 "detector position. Must be exactly 3. Fix database.",
370 static_cast<unsigned int>(position.size()) );
371 return kInitError;
372 }
373 if( !size.empty() ) {
374 if( size.size() != 3 ) {
375 Error(Here(here), "Incorrect number of values = %u for "
376 "detector size. Must be exactly 3. Fix database.",
377 static_cast<unsigned int>(size.size()));
378 return kInitError;
379 }
380 if( size[0] == 0 || size[1] == 0 || size[2] == 0 ) {
381 Error(Here(here), "Illegal zero detector dimension. Fix database.");
382 return kInitError;
383 }
384 if( size[0] < 0 || size[1] < 0 || size[2] < 0 ) {
385 Warning(Here(here), "Illegal negative value for detector dimension. "
386 "Taking absolute. Check database.");
387 }
388 }
389 return kOK;
390}
391
392//_____________________________________________________________________________
393Int_t THaVDCPlane::CreateTTDConv( const char* classname,
394 const vector<Double_t>& ttd_param,
395 const char* here )
396{
397 TClass* cl = TClass::GetClass(classname);
398 if( !cl ) {
399 Error(Here(here),
400 "Drift time-to-distance converter \"%s\" not available. "
401 "Load library or fix database.", classname ? classname : "");
402 return kInitError;
403 }
404 if( !cl->InheritsFrom(VDC::TimeToDistConv::Class()) ) {
405 Error(Here(here),
406 "Class \"%s\" is not a drift time-to-distance "
407 "converter. Fix database.", classname);
408 return kInitError;
409 }
410 fTTDConv = static_cast<VDC::TimeToDistConv*>( cl->New() );
411 if( !fTTDConv ) {
412 Error(Here(here),
413 "Unexpected error creating drift time-to-distance converter "
414 "object \"%s\". Call expert.", classname);
415 return kInitError;
416 }
417 // Set the converters parameters
419 if( fTTDConv->SetParameters(ttd_param) != 0 ) {
420 Error(Here(here),
421 "Error initializing drift time-to-distance converter "
422 "\"%s\". Check ttd.param in database.", classname);
423 return kInitError;
424 }
425 return kOK;
426}
427
428//_____________________________________________________________________________
430{
431 // Set the xy coordinates of this plane's center unless already set.
432 // Then set fOrigin to fCenter of this plane, rotated by the VDC angle
433
434 if( force ||
435 (TMath::Abs(fCenter.X()) < 1e-6 && TMath::Abs(fCenter.Y()) < 1e-6) ) {
436 fCenter.SetX(x);
437 fCenter.SetY(y);
438 }
439 if( fVDC )
441}
442
443//_____________________________________________________________________________
445{
446 // initialize global variables
447
448 // Register variables in global list
449
450 RVarDef vars[] = {
451 { "nhit", "Number of hits", "GetNHits()" },
452 { "wire", "Active wire numbers", "fHits.THaVDCHit.GetWireNum()" },
453 { "rawtime","Raw TDC values of wires", "fHits.THaVDCHit.fRawTime" },
454 { "time", "TDC values of active wires", "fHits.THaVDCHit.fTime" },
455 { "nthit", "tdc hits per channel", "fHits.THaVDCHit.fNthit" },
456 { "dist", "Drift distances", "fHits.THaVDCHit.fDist" },
457 { "ddist", "Drft dist uncertainty", "fHits.THaVDCHit.fdDist" },
458 { "trdist", "Dist. from track", "fHits.THaVDCHit.ftrDist" },
459 { "ltrdist","Dist. from local track", "fHits.THaVDCHit.fltrDist" },
460 { "trknum", "Track number (0=unused)", "fHits.THaVDCHit.fTrkNum" },
461 { "clsnum", "Cluster number (-1=unused)", "fHits.THaVDCHit.fClsNum" },
462 { "nclust", "Number of clusters", "GetNClusters()" },
463 { "clsiz", "Cluster sizes", "fClusters.THaVDCCluster.GetSize()" },
464 { "clpivot","Cluster pivot wire num", "fClusters.THaVDCCluster.GetPivotWireNum()" },
465 { "clpos", "Cluster intercepts (m)", "fClusters.THaVDCCluster.fInt" },
466 { "slope", "Cluster best slope", "fClusters.THaVDCCluster.fSlope" },
467 { "lslope", "Cluster local (fitted) slope","fClusters.THaVDCCluster.fLocalSlope" },
468 { "t0", "Timing offset (s)", "fClusters.THaVDCCluster.fT0" },
469 { "sigsl", "Cluster slope error", "fClusters.THaVDCCluster.fSigmaSlope" },
470 { "sigpos", "Cluster position error (m)", "fClusters.THaVDCCluster.fSigmaInt" },
471 { "sigt0", "Timing offset error (s)", "fClusters.THaVDCCluster.fSigmaT0" },
472 { "clchi2", "Cluster chi2", "fClusters.THaVDCCluster.fChi2" },
473 { "clndof", "Cluster NDoF", "fClusters.THaVDCCluster.fNDoF" },
474 { "cltcor", "Cluster Time correction", "fClusters.THaVDCCluster.fTimeCorrection" },
475 { "cltridx","Idx of track assoc w/cluster", "fClusters.THaVDCCluster.GetTrackIndex()" },
476 { "cltrknum", "Cluster track number (0=unused)", "fClusters.THaVDCCluster.fTrkNum" },
477 { "clbeg", "Cluster start wire", "fClusters.THaVDCCluster.fClsBeg" },
478 { "clend", "Cluster end wire", "fClusters.THaVDCCluster.fClsEnd" },
479 { "npass", "Number of hit passes for cluster", "fNpass" },
480 { nullptr }
481 };
482 return DefineVarsFromList( vars, mode );
483
484}
485
486//_____________________________________________________________________________
488{
489 // Clears the contents of the and hits and clusters
491 fNHits = fNWiresHit = 0;
492 fHits->Clear();
493 fClusters->Delete();
494}
495
496//_____________________________________________________________________________
498{
499
500 assert( hitinfo.nhit > 0 );
501
502 Int_t wireNum = hitinfo.lchan;
503 auto* wire = GetWire(wireNum);
504 if( !wire || wire->GetFlag() != 0 )
505 // Wire is disabled (maybe noisy)
506 return -1;
507
508 // Count hits
509 ++fNHits;
510 if( wire != fPrevWire ) {
512 ++fNWiresHit;
513 }
514 // Bugcheck: identical wires -> multihit
515 assert(wire != fPrevWire || hitinfo.nhit > 1);
516 fPrevWire = wire;
517
518 // Keep maximum data value seen for this series of hits
519 if( data > fMaxData || fMaxData == kMaxUInt )
520 fMaxData = data;
521
522 // Convert the TDC value to the drift time.
523 // Being perfectionist, we apply a 1/2 channel correction to the raw
524 // TDC data to compensate for the fact that the TDC truncates, not
525 // rounds, the data.
526 Double_t toff = wire->GetTOffset();
527 Double_t xdata = static_cast<Double_t>(data) + 0.5;
528 Double_t time = fTDCRes * (toff - xdata);
529
530 // If requested, ignore hits with negative drift times
531 // (due to noise or miscalibration). Use with care.
532 if( fNoNegativeTime && time <= 0.0 )
533 return -2;
534
535 // If there are multiple hits on this channel and only the fastest hit is
536 // requested, find maximum TDC value and record the corresponding hit at
537 // the end of the hit loop.
538 if( hitinfo.nhit > 1 && fOnlyFastestHit ) {
539 if( hitinfo.hit + 1 < hitinfo.nhit || fMaxData == kMaxUInt )
540 // Keep going. More hits to come (or nothing valid found)
541 return 0;
542
543 // Got all the hits on this channel. Record the max TDC value.
544 if( data != fMaxData ) {
545 assert(data < fMaxData);
546 data = fMaxData;
547 xdata = static_cast<Double_t>(data) + 0.5;
548 time = fTDCRes * (toff - xdata);
549 }
550 }
551
552 // Record hit on this wire
553 new((*fHits)[fNextHit++]) THaVDCHit(wire, data, time, hitinfo.nhit);
554
555 return 0;
556}
557
558//_____________________________________________________________________________
560{
561 // Converts the raw data into hit information
562 // Logical wire numbers a defined by the detector map. Wire number 0
563 // corresponds to the first defined channel, etc.
564
565 if (!evData.IsPhysicsTrigger()) return -1;
566
567 const char* const here = "Decode";
568 bool has_warning = false;
569
570 fNextHit = 0;
571 fMaxData = -1;
572 fPrevWire = nullptr;
573
574 auto hitIter = fDetMap->MakeMultiHitIterator(evData);
575 while( hitIter ) {
576 const auto& hitinfo = *hitIter;
577
578 // Get the TDC data for this hit
579 OptUInt_t data = LoadData(evData, hitinfo);
580 if( !data ) {
581 // Data could not be retrieved (probably decoder bug)
582 DataLoadWarning(hitinfo, here);
583 has_warning = true;
584 continue;
585 }
586
587 // Store hit data in fHits
588 StoreHit(hitinfo, data.value());
589
590 // Next active hit or channel
591 ++hitIter;
592 }
593
594 // Sort the hits in order of increasing wire number and (for the same wire
595 // number) increasing time (NOT rawtime)
596 fHits->Sort();
597
598 if( has_warning )
600
601#ifdef WITH_DEBUG
602 if ( fDebug > 3 )
603 PrintDecodedData(evData);
604#endif
605
606 return GetNHits();
607}
608
609//_____________________________________________________________________________
610void THaVDCPlane::PrintDecodedData( const THaEvData& /*evdata*/ ) const
611{
612#ifdef WITH_DEBUG
613 if( fDebug > 3 ) {
614 Int_t nhits = GetNHits();
615 cout << endl
616 << "VDC plane " << GetPrefixName() << ": " << nhits << " hits" << endl;
617 const int ncol = 6;
618 for( int i = 0; i < TMath::Min(ncol, nhits); i++ )
619 cout << " Wire TDC ";
620 cout << endl;
621
622 for( int i = 0; i < (nhits+ncol-1)/ncol; i++ ) {
623 for( int c = ncol*i; c < ncol*(i+1); c++ ) {
624 if( c < nhits ) {
625 auto* hit = dynamic_cast<THaVDCHit*>(fHits->At(c));
626 if( hit )
627 cout << right
628 << " " << setw(3) << hit->GetWireNum()
629 << " " << setw(5) << hit->GetRawTime()
630 << left;
631 else {
632 assert(false); // else bug in Decode()
633 cout << right << setw(12) << "<null>" << left;
634 }
635 } else {
636 break;
637 }
638 }
639 cout << endl;
640 }
641 }
642#endif
643}
644
645//_____________________________________________________________________________
647{
648 // Correct drift times of all hits by GetTimeCorrection() from the VDC
649 // parent detector
650
651 if( fVDC ) {
652 auto r = fVDC->GetTimeCorrection();
653 if( r.second ) {
654 Double_t evtT0 = r.first;
655 Int_t nHits = GetNHits();
656 for( Int_t i = 0; i < nHits; ++i ) {
657 auto* hit = GetHit(i);
658 hit->SetTime(hit->GetTime() - evtT0);
659 }
660 }
661 }
662 return 0;
663}
664
665//_____________________________________________________________________________
666class TimeCut {
667public:
668 TimeCut( THaVDC* vdc, THaVDCPlane* _plane )
669 : hard_cut(false), soft_cut(false), maxdist(0.0), plane(_plane)
670 {
671 assert(vdc);
672 assert(plane);
673 if( vdc ) {
676 }
677 if( soft_cut ) {
678 const auto* chamber = dynamic_cast<THaVDCChamber*>(plane->GetParent());
679 if( chamber )
680 maxdist = 0.5 * chamber->GetSpacing();
681 if( maxdist == 0.0 )
682 soft_cut = false;
683 }
684 }
685 bool operator() ( const THaVDCHit* hit )
686 {
687 // Only keep hits whose drift times are within sanity cuts
688 if( hard_cut ) {
689 Double_t rawtime = hit->GetRawTime();
690 if( rawtime < plane->GetMinTime() || rawtime > plane->GetMaxTime())
691 return false;
692 }
693 if( soft_cut ) {
694 Double_t ratio = hit->GetTime() * plane->GetDriftVel() / maxdist;
695 if( ratio < -0.5 || ratio > 1.5 )
696 return false;
697 }
698 return true;
699 }
700private:
703 double maxdist;
705};
706
707//_____________________________________________________________________________
709{
710 // Reconstruct clusters in a VDC plane
711 // Assumes that the wires are numbered such that increasing wire numbers
712 // correspond to decreasing physical position.
713 // Ignores possibility of overlapping clusters
714
715 TimeCut timecut(fVDC, this);
716
717 Int_t nHits = GetNHits(); // Number of hits in the plane
718 Int_t nUsed = 0; // Number of wires used in clustering
719 Int_t nLastUsed = -1;
720 Int_t nextClust = 0; // Current cluster number
721 assert(GetNClusters() == 0);
722
723 vector<THaVDCHit*> clushits;
724 clushits.reserve(nHits);
725
726 fNpass = 0;
727
728 // Loop while we're making new clusters
729 while( nLastUsed != nUsed ) {
730 fNpass++;
731 nLastUsed = nUsed;
732 //Loop through all TDC hits
733 for( Int_t i = 0; i < nHits; ) {
734 clushits.clear();
735 Bool_t falling = true;
736
737 THaVDCHit* hit = GetHit(i);
738 assert(hit);
739
740 if( !timecut(hit) ) {
741 ++i;
742 continue;
743 }
744 if( hit->GetClsNum() != -1 ) {
745 ++i;
746 continue;
747 }
748 // Ensures we don't use this to try and start a new
749 // cluster
750 hit->SetClsNum(-3);
751
752 // use this to skip bad signal (but do not want to break a possible cluster)
753 Int_t nskip = 0;
754
755 // Consider this hit the beginning of a potential new cluster.
756 // Find the end of the cluster.
757 Int_t span = 0;
758 Int_t nwires = 1;
759 while( ++i < nHits ) {
760
761 THaVDCHit* nextHit = GetHit(i);
762 assert(nextHit); // should never happen, else bug in Decode
763 if( !timecut(nextHit))
764 continue;
765 if( nextHit->GetClsNum() != -1 && // -1 is virgin
766 nextHit->GetClsNum() != -3 ) // -3 was considered to start a cluster but is not in cluster
767 continue;
768
769 // if the hits per wire is more than the TDC set limit, it's just noise. Skip this wire but
770 // continue the cluster searching
771 if( nextHit->GetNthit() >= fMaxThits ) {
772 nskip++;
773 continue;
774 }
775 Int_t ndif = nextHit->GetWireNum() - hit->GetWireNum();
776 // Do not consider adding hits from a wire that was already
777 // added
778 if( ndif == 0 )
779 continue;
780 assert(ndif >= 0);
781 // The cluster ends when we encounter a gap in wire numbers.
782 // TODO: cluster should also end if
783 // DONE (a) it is too big
784 // DONE (b) drift times decrease again after initial fall/rise (V-shape)
785 // DONE (c) Enforce reasonable changes in wire-to-wire V-shape
786
787 // Times are sorted by earliest first when on same wire
788 Double_t deltat = nextHit->GetTime() - hit->GetTime();
789
790 span += ndif;
791 if( ndif > fNMaxGap + 1 + nskip || span > fMaxClustSpan )
792 break;
793
794 // Make sure the time structure is sensible
795 // If this cluster is rising, wire with falling time
796 // should not be associated in the cluster
797 if( !falling ) {
798 if( deltat < fMinTdiff * ndif ||
799 deltat > fMaxTdiff * ndif )
800 continue;
801 }
802
803 if( falling ) {
804 // Step is too big, can't be associated
805 if( deltat < -fMaxTdiff * ndif )
806 continue;
807 if( deltat > 0.0 ) {
808 // if rise is reasonable and we don't
809 // have a monotonically increasing cluster
810 if( deltat < fMaxTdiff * ndif && span > 1 ) {
811 // now we're rising
812 falling = false;
813 } else {
814 continue;
815 }
816 }
817 }
818
819 nwires++;
820 if( clushits.empty() ) {
821 clushits.push_back(hit);
822 hit->SetClsNum(-2);
823 nUsed++;
824 }
825 clushits.push_back(nextHit);
826 nextHit->SetClsNum(-2);
827 nUsed++;
828 hit = nextHit;
829 }
830 assert(i <= nHits);
831 // Make a new cluster if it is big enough
832 // If not, the hits of this i-iteration are ignored
833 // Also, make sure that we did indeed see the time
834 // spectrum turn around at some point
835 if( nwires >= fMinClustSize && !falling ) {
836 auto* clust = new((*fClusters)[nextClust++]) THaVDCCluster(this);
837 for( auto* clushit : clushits ) {
838 clushit->SetClsNum(nextClust - 1);
839 clust->AddHit(clushit);
840 }
841
842 assert(clust->GetSize() > 0 && clust->GetSize() >= nwires);
843 // This is a good cluster candidate. Estimate its position/slope
844 clust->EstTrackParameters();
845 } //end new cluster
846
847 } //end loop over hits
848
849 } // end passes over hits
850
851 assert(GetNClusters() == nextClust);
852
853 return nextClust; // return the number of clusters found
854}
855
856//_____________________________________________________________________________
858{
859 // Fit tracks to cluster positions and drift distances.
860
861 Int_t nClust = GetNClusters();
862 for (int i = 0; i < nClust; i++) {
863 auto* clust = static_cast<THaVDCCluster*>( (*fClusters)[i] );
864 if( !clust ) continue;
865
866 // Convert drift times to distances.
867 // The conversion algorithm is determined at wire initialization time,
868 // i.e. currently in the ReadDatabase() function of this class.
869 // The conversion is done with the current value of fSlope in the
870 // clusters, i.e. either the rough guess from
871 // THaVDCCluster::EstTrackParameters or the global slope from
872 // THaVDC::ConstructTracks
873 clust->ConvertTimeToDist();
874
875 // Fit drift distances to get intercept, slope.
876 clust->FitTrack();
877
878#ifdef CLUST_RAWDATA_HACK
879 // HACK: write out cluster info for small-t0 clusters in u1
880 if( fName == "u" && !strcmp(GetParent()->GetName(),"uv1") &&
881 TMath::Abs(clust->GetT0()) < fT0Resolution/3. &&
882 clust->GetSize() <= 6 ) {
883 ofstream outp;
884 outp.open("u1_cluster_data.out",ios_base::app);
885 outp << clust->GetSize() << endl;
886 for( int i=clust->GetSize()-1; i>=0; i-- ) {
887 outp << clust->GetHit(i)->GetPos() << " "
888 << clust->GetHit(i)->GetDist()
889 << endl;
890 }
891 outp << 1./clust->GetSlope() << " "
892 << clust->GetIntercept()
893 << endl;
894 outp.close();
895 }
896#endif
897 }
898
899 return 0;
900}
901
902//_____________________________________________________________________________
904{
905 // Check if given (x,y) coordinates are inside this plane's active area
906 // (defined by fCenter and fSize).
907 // x and y must be given in the VDC coordinate system.
908
909 return ( TMath::Abs(x-fCenter.X()) <= fSize[0] &&
910 TMath::Abs(y-fCenter.Y()) <= fSize[1] );
911}
912
int Int_t
unsigned int UInt_t
const Data_t kBig
Definition DataType.h:15
uint32_t time
ROOT::R::TRInterface & r
#define d(i)
#define c(i)
#define e(i)
size_t size(const MatrixT &matrix)
bool Bool_t
const Int_t kMaxInt
const UInt_t kMaxUInt
double Double_t
const char Option_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t org
char name[80]
static const char *const here
Definition THaVar.cxx:64
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Bool_t InheritsFrom(const char *cl) const override
void Clear(Option_t *option="") override
void Delete(Option_t *option="") override
void Sort(Int_t upto=kMaxInt) override
static Int_t LoadDB(FILE *file, const TDatime &date, const DBRequest *request, const char *prefix, Int_t search=0, const char *here="THaAnalysisObject::LoadDB")
static Int_t DefineVarsFromList(const void *list, EType type, EMode mode, const char *def_prefix, const TObject *obj, const char *prefix, const char *here, const char *comment_subst="")
virtual const char * Here(const char *) const
const char * GetPrefix() const
TString GetPrefixName() const
EStatus Status() const
virtual FILE * OpenFile(const TDatime &date)
UInt_t GetSize() const
Definition THaDetMap.h:125
@ kFillLogicalChannel
Definition THaDetMap.h:96
THaDetMap::MultiHitIterator MakeMultiHitIterator(const THaEvData &evdata)
Module * GetModule(UInt_t i) const
Definition THaDetMap.h:248
UInt_t GetTotNumChan() const
Int_t FillDetMap(const std::vector< Int_t > &values, UInt_t flags=0, const char *here="FillDetMap")
THaDetMap * fDetMap
void DataLoadWarning(const DigitizerHitInfo_t &hitinfo, const char *here)
Double_t fSize[3]
virtual void DefineAxes(Double_t rotation_angle)
TVector3 DetToTrackCoord(const TVector3 &point) const
virtual OptUInt_t LoadData(const THaEvData &evdata, const DigitizerHitInfo_t &hitinfo)
Bool_t IsPhysicsTrigger() const
Definition THaEvData.h:348
THaDetectorBase * GetParent() const
Double_t GetSpacing() const
virtual void ConvertTimeToDist()
virtual void AddHit(THaVDCHit *hit)
UInt_t GetRawTime() const
Definition THaVDCHit.h:34
Double_t GetTime() const
Definition THaVDCHit.h:35
UInt_t GetNthit() const
Definition THaVDCHit.h:41
Int_t GetWireNum() const
Definition THaVDCHit.h:33
void SetClsNum(Int_t num)
Definition THaVDCHit.h:51
Int_t GetClsNum() const
Definition THaVDCHit.h:40
Int_t CreateTTDConv(const char *classname, const std::vector< Double_t > &ttd_param, const char *here)
Double_t fTDCRes
Double_t fWAngle
virtual Int_t FitTracks()
Double_t GetMaxTime() const
Definition THaVDCPlane.h:70
Int_t ReadDatabaseErrcheck(const std::vector< Float_t > &tdc_offsets, const char *here)
THaVDCWire * GetWire(Int_t i) const
Definition THaVDCPlane.h:48
Bool_t fNoNegativeTime
Int_t fMaxClustSpan
Definition THaVDCPlane.h:98
THaVDCHit * GetHit(Int_t i) const
Definition THaVDCPlane.h:54
TClonesArray * fWires
Definition THaVDCPlane.h:88
Double_t fSinWAngle
Int_t fNWiresHit
Definition THaVDCPlane.h:93
virtual void Clear(Option_t *opt="")
Int_t fNMaxGap
Definition THaVDCPlane.h:99
Double_t fWSpac
THaVDC * fVDC
virtual Int_t ReadDatabase(const TDatime &date)
TClonesArray * fHits
Definition THaVDCPlane.h:89
TClonesArray * fClusters
Definition THaVDCPlane.h:90
Int_t fMinClustSize
Definition THaVDCPlane.h:97
Double_t fMaxTdiff
THaVDCWire * fPrevWire
Double_t fWBeg
virtual Int_t FindClusters()
Int_t GetNClusters() const
Definition THaVDCPlane.h:40
UInt_t fMaxData
virtual Int_t Decode(const THaEvData &)
virtual Bool_t IsInActiveArea(Double_t x, Double_t y) const
virtual Int_t ApplyTimeCorrection()
void UpdateGeometry(Double_t x, Double_t y, bool force=false)
virtual Int_t StoreHit(const DigitizerHitInfo_t &hitinfo, UInt_t data)
virtual ~THaVDCPlane()
THaVDCPlane(const char *name="", const char *description="", THaDetectorBase *parent=nullptr)
Double_t fMinTdiff
Double_t fCosWAngle
Double_t fT0Resolution
virtual void MakePrefix()
VDC::TimeToDistConv * fTTDConv
Bool_t fOnlyFastestHit
virtual Int_t DefineVariables(EMode mode=kDefine)
TVector3 fCenter
Double_t fDriftVel
UInt_t fMaxThits
Int_t ReadGeometryErrcheck(const std::vector< Double_t > &position, const std::vector< Double_t > &size, const char *here)
virtual void PrintDecodedData(const THaEvData &evdata) const
Int_t GetNHits() const
Definition THaVDCPlane.h:52
virtual Int_t ReadGeometry(FILE *file, const TDatime &date, Bool_t required=false)
Double_t GetDriftVel() const
Definition THaVDCPlane.h:68
void SetFlag(Int_t flag)
Definition THaVDCWire.h:32
std::pair< Double_t, bool > GetTimeCorrection() const
Definition THaVDC.cxx:1224
@ kOnlyFastest
Definition THaVDC.h:68
@ kSoftTDCcut
Definition THaVDC.h:71
@ kIgnoreNegDrift
Definition THaVDC.h:72
@ kHardTDCcut
Definition THaVDC.h:70
Double_t GetVDCAngle() const
Definition THaVDC.h:47
const char * GetName() const override
TString fTitle
TString fName
void Clear(Option_t *option="") override
TObject * At(Int_t idx) const override
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
virtual void Warning(const char *method, const char *msgfmt,...) const
virtual void Error(const char *method, const char *msgfmt,...) const
Ssiz_t Length() const
const char * Data() const
TString & Append(char c, Ssiz_t rep=1)
TString & Prepend(char c, Ssiz_t rep=1)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
void SetY(Double_t)
void SetXYZ(Double_t x, Double_t y, Double_t z)
Double_t Y() const
Double_t X() const
void GetXYZ(Double_t *carray) const
void SetX(Double_t)
double maxdist
bool soft_cut
THaVDCPlane * plane
TimeCut(THaVDC *vdc, THaVDCPlane *_plane)
bool hard_cut
bool operator()(const THaVDCHit *hit)
virtual Int_t SetParameters(const std::vector< double > &)
void SetDriftVel(Double_t v)
Double_t y[n]
Double_t x[n]
Double_t Min(Double_t a, Double_t b)
constexpr Double_t DegToRad()
Double_t Cos(Double_t)
Double_t Abs(Double_t d)
Double_t Sin(Double_t)
constexpr Double_t RadToDeg()
STL namespace.
ClassImp(TPyArg)