CFEL - ASG Software Suite  2.5.0
CASS
delayline_detector_analyzer_simple.cpp
Go to the documentation of this file.
1 //Copyright (C) 2003-2010 Lutz Foucar
2 
3 /**
4  * @file delayline_detector_analyzer_simple.cpp file contains the definition of
5  * classes and functions that
6  * analyzses a delayline detector.
7  *
8  * @author Lutz Foucar
9  */
10 
11 #include <iostream>
12 #include <limits>
13 #include <cmath>
14 #include <stdexcept>
15 #include <algorithm>
16 
18 #include "delayline_detector.h"
19 #include "channel.hpp"
20 #include "signal_producer.h"
21 #include "cass_settings.h"
22 #include "poscalculator.hpp"
23 #include "convenience_functions.h"
24 
25 using namespace cass;
26 using namespace cass::ACQIRIS;
27 using namespace std;
28 using namespace std::tr1;
29 
30 namespace cass
31 {
32 namespace ACQIRIS
33 {
34 //@{
35 /** typedefs for shorter code */
38 typedef signals_t::iterator sigIt_t;
39 typedef std::pair<sigIt_t,sigIt_t> range_t;
40 //@}
41 
42 /** check whether anode end wire signal is correleated to mcp signal
43  *
44  * see getSignalRange() for details
45  *
46  * @author Lutz Foucar
47  */
48 struct isInRange : std::unary_function<signal_t,bool>
49 {
50  /** constructor
51  *
52  * @param mcp the time of the mcp signal
53  * @param timesum the timesum of the anode layer
54  * @param maxruntime the time it takes a signal to run across the whole anode
55  */
56  isInRange(double mcp, double timesum, double maxruntime)
57  :_mcp(mcp),_timesum(timesum),_maxruntime(maxruntime)
58  {}
59 
60  /** check correlation
61  *
62  * check whether signal can be correlated with the mcp signal time
63  *
64  * @return true when signal can be correlated
65  * @param sig the signal which needs to be checked for correlation
66  */
67  bool operator()(const signal_t &sig) const
68  {
69  return fabs(2.*sig[time] - 2.*_mcp - _timesum) <= _maxruntime;
70  }
71 
72 private:
73  double _mcp; //!< the time of the mcp signal
74  double _timesum; //!< the timesum of the anode layer
75  double _maxruntime; //!< the time it takes the signal to run across the anode
76 };
77 
78 /** return range of possible anode wire signal candidates
79  *
80  * For a given Mcp time there are only a few signal on the wire ends that
81  * can come with the Mcp Signal. This function will find the indexs of the
82  * list of signals which might come together with the mcp signal.
83  * This is because we know two things (ie. for the x-layer):
84  * \f$|x_1-x_2|<rTime_x\f$
85  * and
86  * \f$x_1+x_2-2*mcp = ts_x\f$
87  * with this knowledge we can calculate the boundries for the anode given
88  * the Timesum and the Runtime.
89  *
90  * @return pair of iterator that define the range
91  * @param sigs the vector of signals of the anode wire end
92  * @param mcp the Mcp Signal for which to find the right wire end signals
93  * @param ts The timesum of the Anode
94  * @param rTime The runtime of a Signal over the whole wire of the anode
95  *
96  * @author Lutz Foucar
97  */
98 pair<sigIt_t,sigIt_t> getSignalRange(signals_t &sigs, const double mcp, const double ts, const double rTime)
99 {
100  sigIt_t begin (find_if(sigs.begin(),sigs.end(),isInRange(mcp,ts,rTime)));
101  sigIt_t end (find_if(begin, sigs.end(),not1(isInRange(mcp,ts,rTime))));
102  return (make_pair(begin,end));
103 }
104 
105 }//end namepsace acqiris
106 }//end namespace cass
107 
108 
110 {
111 // typedef SignalProducer::signal_t signal_t;
113  typedef signals_t::iterator sigIt_t;
114  typedef std::pair<sigIt_t,sigIt_t> range_t;
115 
116  SignalProducer::signals_t &mcpsignals (_mcp->output());
117  SignalProducer::signals_t &f1signals (_layerCombination.first.first->output());
118  SignalProducer::signals_t &f2signals (_layerCombination.first.second->output());
119  SignalProducer::signals_t &s1signals (_layerCombination.second.first->output());
120  SignalProducer::signals_t &s2signals (_layerCombination.second.second->output());
121 
122  for (sigIt_t iMcp (mcpsignals.begin());iMcp != mcpsignals.end() ;++iMcp)
123  {
124  if (!fuzzyIsNull((*iMcp)[isUsed]))
125  continue;
126  const double mcp ((*iMcp)[time]);
127  range_t f1range(getSignalRange(f1signals,mcp,_ts.first,_runtime));
128  range_t f2range(getSignalRange(f2signals,mcp,_ts.first,_runtime));
129  range_t s1range(getSignalRange(s1signals,mcp,_ts.second,_runtime));
130  range_t s2range(getSignalRange(s2signals,mcp,_ts.second,_runtime));
131  for (sigIt_t iF1 (f1range.first);iF1!=f1range.second;++iF1)
132  {
133  if (!fuzzyIsNull((*iF1)[isUsed]))
134  continue;
135  for (sigIt_t iF2 (f2range.first);iF2!=f2range.second;++iF2)
136  {
137  if (!fuzzyIsNull((*iF2)[isUsed]))
138  continue;
139  for (sigIt_t iS1 (s1range.first);iS1!=s1range.second;++iS1)
140  {
141  if (!fuzzyIsNull((*iS1)[isUsed]))
142  continue;
143  for (sigIt_t iS2 (s2range.first);iS2!=s2range.second;++iS2)
144  {
145  if (!fuzzyIsNull((*iS2)[isUsed]))
146  continue;
147 
148  const double mcp ((*iMcp)[time]);
149 
150  const double f1 ((*iF1)[time]);
151  const double f2 ((*iF2)[time]);
152  const double s1 ((*iS1)[time]);
153  const double s2 ((*iS2)[time]);
154  const double sumf (f1+f2 - 2.* mcp);
155  const double sums (s1+s2 - 2.* mcp);
156  const double f((f1-f2) * _sf.first);
157  const double s((s1-s2) * _sf.second);
158 
159  const pair<double,double> pos ((*_poscalc)(make_pair(f,s)));
160 
161  const double radius (sqrt(pos.first*pos.first + pos.second*pos.second));
162 
163  if ( (sumf > _tsrange.first.first) && (sumf < _tsrange.first.second) )
164  {
165  if ( (sums > _tsrange.second.first) && (sums < _tsrange.second.second) )
166  {
167  if (radius < _mcpRadius)
168  {
170  hit[x] = pos.first;
171  hit[y] = pos.second;
172  hit[t] = (*iMcp)[time];
173  hits.push_back(hit);
174  (*iMcp)[isUsed] = true;
175  (*iF1)[isUsed] = true;
176  (*iF2)[isUsed] = true;
177  (*iS1)[isUsed] = true;
178  (*iS2)[isUsed] = true;
179  }
180  }
181  }
182  }
183  }
184  }
185  }
186  }
187  return hits;
188 }
189 
191 {
192  enum LayerComb{xy,uv,uw,vw};
193 
194  DelaylineType delaylinetype
195  (static_cast<DelaylineType>(s.value("DelaylineType",Hex).toInt()));
196 
197  s.beginGroup("Simple");
198  LayerComb lc (static_cast<LayerComb>(s.value("LayersToUse",xy).toInt()));
199  if ((lc == xy) && (delaylinetype == Hex))
200  throw invalid_argument("DelaylineDetectorAnalyzerSimple::loadSettings: Error using layers xy for Hex-Detector");
201  if ((delaylinetype == Quad) && (lc == uv || lc == uw || lc == vw))
202  throw invalid_argument("DelaylineDetectorAnalyzerSimple::loadSettings: Error using layers uv, uw or vw for Quad-Detector");
203 
204  switch (lc)
205  {
206  case (xy):
207  _layerCombination = make_pair(make_pair(&d.layers()['X'].wireends()['1'],
208  &d.layers()['X'].wireends()['2']),
209  make_pair(&d.layers()['Y'].wireends()['1'],
210  &d.layers()['Y'].wireends()['2']));
211  _poscalc = std::tr1::shared_ptr<PositionCalculator>(new XYCalc);
212  break;
213  case (uv):
214  _layerCombination = make_pair(make_pair(&d.layers()['U'].wireends()['1'],
215  &d.layers()['U'].wireends()['2']),
216  make_pair(&d.layers()['V'].wireends()['1'],
217  &d.layers()['V'].wireends()['2']));
218  _poscalc = std::tr1::shared_ptr<PositionCalculator>(new UVCalc);
219  break;
220  case (uw):
221  _layerCombination = make_pair(make_pair(&d.layers()['U'].wireends()['1'],
222  &d.layers()['U'].wireends()['2']),
223  make_pair(&d.layers()['W'].wireends()['1'],
224  &d.layers()['W'].wireends()['2']));
225  _poscalc = std::tr1::shared_ptr<PositionCalculator>(new UWCalc);
226  break;
227  case (vw):
228  _layerCombination = make_pair(make_pair(&d.layers()['V'].wireends()['1'],
229  &d.layers()['V'].wireends()['2']),
230  make_pair(&d.layers()['W'].wireends()['1'],
231  &d.layers()['W'].wireends()['2']));
232  _poscalc = std::tr1::shared_ptr<PositionCalculator>(new VWCalc);
233  break;
234  default:
235 // throw invalid_argument("DelaylineDetectorAnalyzerSimple::loadSettings: Layercombination '" +
236 // toString(lc) + "' not available");
237  break;
238  }
239  _mcp = &d.mcp();
240  _tsrange = make_pair(make_pair(s.value("TimesumFirstLayerLow",0).toDouble(),
241  s.value("TimesumFirstLayerHigh",200).toDouble()),
242  make_pair(s.value("TimesumSecondLayerLow",0).toDouble(),
243  s.value("TimesumSecondLayerHigh",200).toDouble()));
244  _ts = make_pair(0.5*(_tsrange.first.first + _tsrange.first.second),
245  0.5*(_tsrange.second.first + _tsrange.second.second));
246  _sf = make_pair(s.value("ScalefactorFirstLayer",0.4).toDouble(),
247  s.value("ScalefactorSecondLayer",0.4).toDouble());
248  _runtime = s.value("Runtime",150).toDouble();
249  _mcpRadius = s.value("McpRadius",88).toDouble();
250  s.endGroup();
251 }
std::vector< double > detectorHit_t
define a detector hit
contains classes for calculating the position in a DLD
SignalProducer::signals_t signals_t
typedefs for shorter code
file contains the classes that describe how to analyze the waveform and stores the result...
std::vector< signal_t > signals_t
isInRange(double mcp, double timesum, double maxruntime)
constructor
position calculator for hex anodes u and v layer
Settings for CASS.
Definition: cass_settings.h:30
pair< sigIt_t, sigIt_t > getSignalRange(signals_t &sigs, const double mcp, const double ts, const double rTime)
return range of possible anode wire signal candidates
file contains the classes that describe an acqiris channel
std::vector< detectorHit_t > detectorHits_t
define container for all detector hits
define which of the hitfinders defined above will be used as hit
STL namespace.
Average out the iShit status to get the avererage hits
position calculator for hex anodes u and v layer
std::pair< sigIt_t, sigIt_t > range_t
typedefs for shorter code
SignalProducer & mcp()
retrieve the mcp
Definition: tof_detector.h:67
file contains the classes that describe a delayline detector.
std::vector< double > signal_t
detectorHits_t & operator()(detectorHits_t &hits)
the function creating the detectorhit list
anodelayers_t & layers()
return the layers
DelaylineType
the types of delayline detectors that are available
file contains the declaration of classes that analyzses a delayline detector.
double _maxruntime
the time it takes the signal to run across the anode
file contains declaration of classes and functions that help other processors to do their job...
check whether anode end wire signal is correleated to mcp signal
bool fuzzyIsNull(const T &val)
fuzzy compare a floating point number to 0
signals_t::iterator sigIt_t
typedefs for shorter code
void loadSettings(CASSSettings &s, DelaylineDetector &d)
load the detector analyzers settings from .ini file
double _timesum
the timesum of the anode layer
value(const QString &key, const QVariant &defaultValue=QVariant()
position calculator for hex anodes u and w layer
bool operator()(const signal_t &sig) const
check correlation
file contains specialized class that do the settings for cass
position calculator for quad anode
beginGroup(const QString &prefix)
double _mcp
the time of the mcp signal
SignalProducer::signal_t signal_t
typedefs for shorter code