GEAR  1.9.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends Pages
VersatileDiskRowLayout.cc
1 #include "gearimpl/VersatileDiskRowLayout.h"
2 
3 #include <cmath>
4 #include <iostream>
5 //#include <stdexcept>
6 #include <sstream>
7 #include <string>
8 //#include <cstdlib>
9 #include <gear/GEAR.h>
10 
11 namespace gear {
12 
14  _nPad(0), _isFrayed(false)
15 {
16 
17  _extent.resize(4) ;
18  _extent[0] = rMin ;
19  _extent[1] = rMin ; // radial size is 0, so rMax = rMin
20  _extent[2] = 0 ;
21  _extent[3] = 0 ;
22 }
23 
25 {
26  copy_and_assign(right);
27 }
28 
30 {
31  _isFrayed = right._isFrayed;
32  _nPad = right._nPad;
33  _rows = right._rows;
34  _extent = right._extent;
35 
36  // just set the _padIndices to an vector of empty entries.
37  // In every instance, also the copied ones, it is filled only at first
38  // usage to save memory
39  // just like in the constructor
40  _padIndices.resize( _rows.size() ) ;
41  for (std::vector< std::vector<int>* >::iterator rowIter = _padIndices.begin() ;
42  rowIter < _padIndices.end(); rowIter++)
43  {
44  *rowIter=0;
45  }
46 }
47 
49 {
50  return new VersatileDiskRowLayout(*this);
51 }
52 
53 void VersatileDiskRowLayout::addRow( int nPads , double padPitch , double rowHeight ,
54  double offset, double padWidth, double padHeight,
55  int repeat )
56 {
57  std::string routineName("gear::VersatileDiskRowLayout::addRow(): ");
58 
59  // a few sanity checks:
60  if ( nPads <= 0 )
61  throw Exception(routineName+"Error, number of pads must be larger than 0!");
62  if ( padPitch < 0. )
63  throw Exception(routineName+"Error, pad pitch must be positive!");
64  if ( padWidth < 0. )
65  throw Exception(routineName+"Error, pad width must be positive!");
66  if ( padWidth > padPitch )
67  throw Exception(routineName+"Error, pad width must be smaller or equal pad pitch!");
68  if ( rowHeight <= 0. )
69  throw Exception(routineName+"Error, row height must be larger than 0!");
70  if ( repeat <= 0)
71  throw Exception(routineName+"Error, number of repitions must be positive!");
72 
73  if (padWidth == 0.)
74  padWidth = padPitch;
75  if (padHeight == 0.)
76  padHeight = rowHeight;
77 
78  double rCentre = _extent[1] + rowHeight*0.5;
79 
80  _nPad += repeat*nPads ;
81 
82  for (int i = 0; i < repeat; i++)
83  {
84  _rows.push_back( Row(_rows.size(), nPads, rCentre, padPitch , rowHeight ,
85  padWidth, padHeight, offset ) );
86  _padIndices.push_back( 0 );
87  rCentre += rowHeight;
88  }
89 
90  // calculate correct plane extent
91  _extent[1]+= repeat * rowHeight;
92  if ( (_rows.size() ==1) || (_rows.back().getPhiMin() < _extent[2] ) )
93  _extent[2] = _rows.back().getPhiMin();
94  if ( (_rows.size() ==1) || (_rows.back().getPhiMax() > _extent[3] ) )
95  _extent[3] = _rows.back().getPhiMax();
96 
97  if ( (_extent[3] - _extent[2]) > 2*M_PI )
98  {
99  _extent[2] = 0.;
100  _extent[3] = 2*M_PI;
101  }
102  }
103 
105  return _rows.size() ;
106  }
107 
108  double VersatileDiskRowLayout::getRowHeight(int rowNumber) const
109  {
110  return _rows.at(rowNumber).getRowHeight() ;
111  }
112 
113  double VersatileDiskRowLayout::getPadHeight(int padIndex) const
114  {
115  int rowNum = getRowNumber( padIndex ) ;
116  return _rows[rowNum].getPadHeight( ) ;
117  }
118 
119 
120  double VersatileDiskRowLayout::getPadWidth(int padIndex) const {
121 
122  int rowNum = getRowNumber( padIndex ) ;
123 
124 // return _rows[rowNum].getPadWidth() ;
125  return _rows[rowNum].getPadWidth() ;
126  }
127 
128  double VersatileDiskRowLayout::getPadPitch(int padIndex) const {
129 
130  int rowNum = getRowNumber( padIndex ) ;
131 
132 // return _rows[rowNum].getPadWidth() ;
133  return _rows[rowNum].getPadPitch() ;
134  }
135 
136 
138 
139  int rowNum = getRowNumber( padIndex ) ;
140  int padNum = getPadNumber( padIndex ) ;
141 
142  const Row& row = _rows[ rowNum ] ;
143 
144  double phi = row.getOffset() + (static_cast<double>(padNum) + 0.5) * row.getPadPitch();
145 
146  double r = row.getRCentre() ;
147 
148  return Vector2D( r , phi ) ;
149  }
150 
152  {
153 // std::cerr << "FixedDiskLayoutBase::getPadLayoutType() : Warning: " <<std::endl
154 // << " This is deprecated (ambiguous for polar coordinate systems)"<< std::endl
155 // << " Please use getCoordinateType() or getPadLayoutImplType() "<< std::endl;
156  return getCoordinateType();
157  }
158 
160  {
161  cleanup();
162  }
163 
165  {
166  cleanup();
167  copy_and_assign(right);
168  return *this;
169  }
170 
172  {
173  for( unsigned i=0; i<_padIndices.size(); ++i ){
174  delete _padIndices[i] ;
175  }
176  }
177 
178  const std::vector<int>& VersatileDiskRowLayout::getPadsInRow(int rowNumber) const {
179 
180  static std::vector<int> empty ;
181 
182  try {
183 
184  if( _padIndices.at(rowNumber ) == 0 ) {
185 
186  int nPad = _rows.at(rowNumber).getNPads() ;
187 
188  _padIndices[ rowNumber ] = new std::vector<int>( nPad ) ;
189 
190  for(int i = 0 ; i < nPad ; i++){
191 
192  _padIndices[rowNumber]->operator[](i) = getPadIndex( rowNumber , i ) ;
193  }
194 
195  }
196  } catch( std::out_of_range& r) {
197 
198  // std::cout << " VersatileDiskRowLayout::getPadsInRow : no row " << rowNumber << std::endl ;
199  return empty ;
200 
201  }
202 
203  return *_padIndices[ rowNumber ] ;
204  }
205 
206 
207  int VersatileDiskRowLayout::getRowNumber(int padIndex) const {
208 
209  int rn = ( 0xffff0000 & padIndex ) >> 16 ;
210 
211  if( rn < 0 || rn > int(_rows.size() - 1) ){
212 
213  std::stringstream sstr ;
214 
215  sstr << "VersatileDiskRowLayout::getRowNumber: illegal rownumber: "
216  << rn << " for padIndex 0x" << std::hex << padIndex << " nRows: " << _rows.size() << std::dec ;
217 
218  throw Exception( sstr.str() ) ;
219  }
220 
221  return rn ;
222  }
223 
224 
225  int VersatileDiskRowLayout::getPadIndex(int rowNum, int padNum) const {
226 
227 
228  if( (unsigned) rowNum > _rows.size() - 1 ) {
229 
230  throw std::out_of_range(" VersatileDiskRowLayout::getPadIndex row number too large !");
231  }
232 
233  if( padNum > _rows[rowNum].getNPads() - 1 ) {
234 
235  std::stringstream sstr ;
236 
237  sstr << "VersatileDiskRowLayout::getPadIndex: pad number too large: "
238  << padNum << " only " << _rows[rowNum].getNPads() << " pads in row " << rowNum ;
239 
240  throw std::out_of_range( sstr.str() );
241  }
242 
243  return (rowNum << 16 ) | ( 0x0000ffff & padNum ) ;
244 
245  }
246 
247 
249 
250  int pn = getPadNumber( padIndex ) - 1 ;
251  int rn = getRowNumber( padIndex) ;
252 
253  // anything larger than _nPadsInRow would have caused an out_of_range exception in
254  // getPadNumber
255  if(pn == -1)
256  {
257  // take into account wrap arround in case of full circle (incl. rounding errors)
258  if (fabs(_extent[3] - _extent[2] - 2*M_PI) < 1e-6 )
259  pn = _rows[rn].getNPads() -1 ;
260  else
261  throw Exception("VersatileDiskRowLayout::getRightNeighbour: no right neighbour pad !");
262  }
263 
264  return getPadIndex( rn , pn ) ;
265  }
266 
268 
269  int pn = getPadNumber( padIndex ) + 1 ;
270  int rn = getRowNumber( padIndex) ;
271 
272  // anything larger than _nPadsInRow would have caused an out_of_range exception in
273  // getPadNumber
274  if (pn == _rows[rn].getNPads())
275  {
276  // take into account wrap arround in case of full circle (incl. rounding errors)
277  if (fabs(_extent[3] - _extent[2] - 2*M_PI) < 1e-6 )
278  pn = 0 ;
279  else
280  throw Exception("VersatileDiskRowLayout::getLeftNeighbour: no left neighbour pad !");
281  }
282 
283  return getPadIndex( rn , pn ) ;
284  }
285 
286  int VersatileDiskRowLayout::getNearestPad(double r, double phi) const
287  {
288  // the brute force method: scan all rows
289  int nearestPad = -1 ;
290  double distance=0;
291  for (std::vector<Row>::const_iterator rowIter = _rows.begin()++;
292  rowIter < _rows.end(); rowIter++)
293  {
294 // int nearestPad = rowIter->getNearestPad(r, phi);
295  double newDistance = rowIter->getDistanceToRow(r, phi);
296 
297  if ( (newDistance < distance) || ( rowIter == _rows.begin() ) )
298  {
299  nearestPad = rowIter->getNearestPad(r, phi);
300  distance = newDistance;
301  }
302  }
303 
304  if (nearestPad == -1)
305  throw Exception(std::string("VersatileDiskRowLayout::getNearestPad(): no pad rows defined."));
306 
307  return nearestPad;
308  }
309 
310  bool VersatileDiskRowLayout::isInsidePad(double r, double phi, int padIndex) const {
311 
312  int pn = getPadNumber( padIndex ) ;
313  int rn = getRowNumber( padIndex) ;
314 
315  const Row& row = _rows[rn] ;
316 
317  double rMin = row.getRCentre() - row.getRowHeight()*0.5;
318  double rMax = row.getRCentre() + row.getRowHeight()*0.5;
319 
320  // the right edge of the pad
321  double phiMin = row.getOffset() + row.getPadPitch()*pn;
322 
323  // wrap phi to phiMin .. phiMin + 2*pi
324  if (phi < phiMin)
325  phi += 2. * M_PI;
326 
327  if (phi >= phiMin + 2*M_PI)
328  phi -= 2. * M_PI;
329 
330  double phiMax = phiMin + row.getPadPitch();
331 
332  return ( r >= rMin && r <= rMax &&
333  phi <= phiMax ) ; // no need to check for phiMin because of wrap around
334  }
335 
336  bool VersatileDiskRowLayout::isInsidePad(double r, double phi) const {
337 
338  // outside of pad plane
339  if( r < _extent[0] || r > _extent[1] ||
340  phi < _extent[2] || phi > _extent[3] )
341 
342  return false ;
343 
344  return isInsidePad( r , phi , getNearestPad( r, phi ) ) ;
345  }
346 
347 VersatileDiskRowLayout::Row::Row(int rowNumber, int nPads, double rCentre, double padPitch_mm,
348  double rowHeight,
349  double padWidth_mm, double padHeight, double offset_mm) :
350  _rowNumber(rowNumber), _nPads(nPads), _padPitch_mm(padPitch_mm), _padWidth_mm(padWidth_mm),
351  _rowHeight(rowHeight), _padHeight(padHeight), _offset_mm(offset_mm),
352  _rCentre(rCentre), _rMax(0.)
353 {
354  _offset = _offset_mm / rCentre;
355 
356  // wrap offset to +- 2*pi
357  if (_offset < - 2. * M_PI)
358  {
359  _offset += 2. * M_PI;
360  _offset_mm += rCentre*2. * M_PI;
361  }
362 
363  if (_offset >= 2. * M_PI)
364  {
365  _offset -= 2. * M_PI;
366  _offset_mm += rCentre*2. * M_PI;
367  }
368 
369  _padPitch = _padPitch_mm / rCentre;
370  if (_padPitch * nPads > 2*M_PI)
371  {
372  std::stringstream sstr;
373  sstr << "gear::VersatileDiskRowLayout::addRow(): "
374  << "Error: Too many pads ("<<nPads<<" in row "<<rowNumber<<"!";
375  throw Exception( sstr.str() );
376  }
377 
378  _padWidth = _padWidth_mm / rCentre;
379  _offset = _offset_mm / rCentre;
380 
381  _phiMax = _offset + _padPitch*_nPads;
382  _rMin = _rCentre - rowHeight*0.5;
383  _rMin = _rCentre + rowHeight*0.5;
384 }
385 
386 int VersatileDiskRowLayout::Row::getNearestPad(double r, double phi) const
387 {
388  // wrap phi to 0 < phi < 2*M_PI
389 
390  while( phi < 0 ) { phi += 2. * M_PI ; }
391  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
392 
393  //
394 
395  // if the angle is in the active angle one can easily calculate the pad number
396  //if (phi < _offset + _nPads * _padPitch )
397  if (phi < _offset + _nPads * _padPitch)
398  {
399  int padNumber = static_cast<int>(floor( (phi - _offset)/ _padPitch ));
400 
401  return ( (_rowNumber<< 16) | (0x000ffff & padNumber) );
402  }
403  else //outside the active angle
404  { // it can only be one of the edge pad
405  double distance1 = distanceToPhiMin( r , phi);
406  double distance2 = distanceToPhiMax( r , phi);
407 
408  if ( distance1 < distance2)
409  return (_rowNumber << 16); // pad 0 in the row
410  else
411  return ( (_rowNumber<< 16) | (0x000ffff & (_nPads-1)) );
412  }
413 }
414 
415 double VersatileDiskRowLayout::Row::getDistanceToRow(double r, double phi) const
416 {
417  // wrap phi to 0 < phi < 2*M_PI
418 
419  while( phi < 0 ) { phi += 2. * M_PI ; }
420  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
421 
422  // copy the code from getDistanceToPad....
423 
424  double r_min = _rCentre - _rowHeight*0.5;
425  double r_max = _rCentre + _rowHeight*0.5;
426  double phi_min = _offset;
427  double phi_max = _offset + _nPads * _padPitch;
428 
429 // if( (r < padCenter[0] - _rowHeight/2.) || (r > padCenter[0] + _rowHeight/2.) ||
430 // (phi < padCenter[1]- _padAngle/2.) || (phi < padCenter[1]+_padAngle/2. ) )
431  if ( (phi >= phi_min) && (phi <= phi_max ) )
432  {
433  // this is the easy part, it's just distances in r
434  if( (r >= r_min) && (r <= r_max) )
435  // we are inside the pad
436  return 0.;
437  else
438  {
439  if (r < r_min)
440  return r_min - r;
441  else
442  return r - r_max;
443  }
444  }
445  else // this is more complicated (code has been transferred for reusability)
446  {
447  double distance_phiMin = distanceToPhiMin(r, phi);
448  double distance_phiMax = distanceToPhiMax(r, phi);
449 
450  return (distance_phiMin < distance_phiMax ? distance_phiMin : distance_phiMax);
451 
452  } //else within phi range
453 }
454 
455 
456 double VersatileDiskRowLayout::Row::distanceToPhiMin(double r, double phi) const
457 {
458  // wrap phi to 0 < phi < 2*M_PI
459 
460  while( phi < 0 ) { phi += 2. * M_PI ; }
461  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
462 
463  //
464 
465  double r_min = _rCentre - _rowHeight*0.5;
466  double r_max = _rCentre + _rowHeight*0.5;
467  double phi_min = _offset;
468 
469  double distanceToCorner[2];
470 
471  distanceToCorner[0] = r_min*r_min + r*r - 2*r_min*r*cos(phi_min - phi);
472  distanceToCorner[1] = r_max*r_max + r*r - 2*r_max*r*cos(phi_min - phi);
473 
474  return sqrt(
475  distanceToCorner[0] > distanceToCorner[1] ?
476  distanceToCorner[1] : distanceToCorner[0]
477  );
478 }
479 
480 double VersatileDiskRowLayout::Row::distanceToPhiMax(double r, double phi) const
481 {
482  // wrap phi to 0 < phi < 2*M_PI
483 
484  while( phi < 0 ) { phi += 2. * M_PI ; }
485  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
486 
487  //
488 
489  double r_min = _rCentre - _rowHeight*0.5;
490  double r_max = _rCentre + _rowHeight*0.5;
491  double phi_max = _offset + _nPads * _padPitch;
492 
493  double distanceToCorner[2];
494 
495  distanceToCorner[0] = r_min*r_min + r*r - 2*r_min*r*cos(phi_max - phi);
496  distanceToCorner[1] = r_max*r_max + r*r - 2*r_max*r*cos(phi_max - phi);
497 
498  return sqrt(
499  distanceToCorner[0] > distanceToCorner[1] ?
500  distanceToCorner[1] : distanceToCorner[0]
501  );
502 }
503 
504 
505 } // namespace
506 
507 
double getDistanceToRow(double r, double phi) const
Function to calculate closest distance to the row.
bool _isFrayed
Flag that describes if the geometry is frayed.
Abstract description of a planar subdetector with pads (cells) that are positioned in rows (circular ...
virtual int getNearestPad(double c0, double c1) const
The index of the pad nearest to the given point in 2d coordinates (x,y,) or (r,phi).
int _nPad
number of pads, keep for performance reasons
virtual bool isInsidePad(double c0, double c1, int padIndex) const
True if coordinate (c0,c1) is within the given pad.
Base exception class for GEAR - all other exceptions extend this.
Definition: GEAR.h:41
PadRowLayout2D * clone() const
Returns a copy (clone) of this class.
int getNearestPad(double r, double phi) const
Function to determine the nearest pad in the row.
VersatileDiskRowLayout(double rMin)
Construct the VersatileDiskRowLayout.
virtual const std::vector< int > & getPadsInRow(int rowNumber) const
Indices of all pads in row rowNumber (row indices start from 0 at the bottom (CARTESIAN) or at the ce...
virtual int getPadIndex(int rowNum, int padNum) const
Create a padIndex for the given row and pad ( column ) number.
VersatileDiskRowLayout & operator=(const VersatileDiskRowLayout &)
The assignment operator.
virtual int getNPads() const
The total number of pads in the TPC.
virtual void addRow(int nPads, double padPitch, double rowHeight, double offset=0., double padWidth=0., double padHeight=0., int repeat=1)
Add &#39;repeat&#39; rows with the given parameters.
virtual int getRowNumber(int padIndex) const
The number of the row that contains the pad at padIndex - numbering starts at r/y==0.
virtual int getPadNumber(int padIndex) const
The pad number (column) within the row - numbering starts at phi/x =.
virtual int getNRows() const
The number of rows.
virtual Vector2D getPadCenter(int padIndex) const
The center of the pad in 2d coordinates, (x,y) or (r,phi).
double _padPitch
the pad pitch in radians
void cleanup()
function to delete all the objects pointed to and owned by the VersatileDiskRowLayout.
virtual int getCoordinateType() const
The type of the row layouts coordinate system: PadRowLayout2D.POLAR.
Internal helper class for VersatileDiskRowLayout, describing one row.
std::vector< std::vector< int > * > _padIndices
vector for getPadsInRow
void copy_and_assign(const VersatileDiskRowLayout &)
function to copy all internal variables, incl.
virtual double getPadHeight(int padIndex) const
The height of the pad in mm.
virtual double getRowHeight(int rowNumber) const
The row height in mm.
virtual double getPadPitch(int padIndex) const
The pitch of the pad in radians.
virtual ~VersatileDiskRowLayout()
Destructor.
virtual double getPadWidth(int padIndex) const
The width of the pad in radians.
std::vector< Row > _rows
vector with all the rows of the pad plane
std::vector< double > _extent
the plane extent
double _offset
the offset (staggering) with respect to phi=0 in radians, aka phiMin
Implementation of PadRowLayout2D for a wedge shaped module.
virtual int getLeftNeighbour(int padIndex) const
The index of the left neighbour pad.
virtual int getRightNeighbour(int padIndex) const
The index of the right neighbour pad.
int _nPads
number of pads in the row