ATLAS Offline Software
Loading...
Searching...
No Matches
TRT_DetElementsRoadMaker_xk.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// Implementation file for class InDet::TRT_DetElementsRoadMaker_xk
8// (c) ATLAS Detector software
11// Version 1.0 21/04/2004 I.Gavrilenko
13
14
15
17
21
26
30
31#include <cmath>
32#include <iostream>
33#include <iomanip>
34#include <utility>
35
36
38// Constructor
40
42(const std::string& t,const std::string& n,const IInterface* p)
43 : AthAlgTool(t,n,p)
44{
45 declareInterface<ITRT_DetElementsRoadMaker>(this);
46}
47
49// Destructor
51
53= default;
54
56// Initialisation
58
60{
61 StatusCode sc = AlgTool::initialize();
62 if(m_fieldmode == "NoField") m_fieldModeEnum = Trk::NoField;
63 else if(m_fieldmode == "MapSolenoid") m_fieldModeEnum = Trk::FastField;
65 // Get propagator tool
66 ATH_CHECK (m_proptool.retrieve());
67 ATH_MSG_DEBUG("Retrieved tool " << m_proptool);
68 ATH_CHECK(m_roadDataKey.initialize());
70
71 return sc;
72}
73
75// Finalize
77
79{
80 StatusCode sc = AlgTool::finalize(); return sc;
81}
82
84// Dumps relevant information into the MsgStream
86
87MsgStream& InDet::TRT_DetElementsRoadMaker_xk::dump( MsgStream& out ) const
88{
89 return dumpConditions(out);
90}
91
93// Dumps conditions information into the MsgStream
95
97{
98 auto precision = out.precision();
99 int n = 62-m_proptool.type().size();
100 std::string s1; for(int i=0; i<n; ++i) s1.append(" "); s1.append("|");
101
102 std::string fieldmode[9] ={"NoField" ,"ConstantField","SolenoidalField",
103 "ToroidalField" ,"Grid3DField" ,"RealisticField" ,
104 "UndefinedField","AthenaField" , "?????" };
105
108 const AtlasFieldCacheCondObj* fieldCondObj{*fieldHandle};
109 if (fieldCondObj) {
110 MagField::AtlasFieldCache fieldCache;
111 fieldCondObj->getInitializedCache (fieldCache);
112 if(!fieldCache.solenoidOn()) fieldModeEnum = Trk::NoField;
113 }
114 Trk::MagneticFieldProperties fieldprop(fieldModeEnum);
115 int mode = fieldprop.magneticFieldMode();
116 if(mode<0 || mode>8 ) mode = 8;
117
118 n = 62-fieldmode[mode].size();
119 std::string s3; for(int i=0; i<n; ++i) s3.append(" "); s3.append("|");
120
121 const TRT_DetElementsLayerVectors_xk &layer = *getLayers(Gaudi::Hive::currentContext());
122
123 int maps = 0;
124 if(!layer[0].empty()) ++maps;
125 if(!layer[1].empty()) ++maps;
126 if(!layer[2].empty()) ++maps;
127
128 out<<"|----------------------------------------------------------------------"
129 <<"-------------------|"
130 <<std::endl;
131 out<<"| Tool for propagation | "<<m_proptool.type()<<s1<<std::endl;
132 out<<"| Magnetic field mode | "<<fieldmode[mode]<<s3<<std::endl;
133 out<<"| Width of the road (mm) | "
134 <<std::setw(12)<<std::setprecision(5)<<m_width
135 <<" |"<<std::endl;
136 out<<"|----------------------------------------------------------------------"
137 <<"-------------------|"
138 <<std::endl;
139
140 if(!maps || !msgLvl(MSG::VERBOSE)) return out;
141
142 if(!layer[1].empty()) {
143 int nl = layer[1].size();
144 int nc = 0;
145 for(const auto & i : layer[1]) nc+=i.nElements();
146 out<<"|----------------------------------------------------------------|"
147 <<std::endl;
148 out<<"| Barrel map containt "
149 <<std::setw(4)<<nl<<" layers and "
150 <<std::setw(6)<<nc<<" elements |"
151 <<std::endl;
152 out<<"|------|-----------|------------|------------|------------|------|"
153 <<std::endl;
154 out<<"| n | R | Z min | Z max | max dF | nEl |"
155 <<std::endl;
156 out<<"|------|-----------|------------|------------|------------|------|"
157 <<std::endl;
158 for(unsigned int i=0; i!=layer[1].size(); ++i) {
159 float zmin = layer[1][i].z()-layer[1][i].dz();
160 float zmax = layer[1][i].z()+layer[1][i].dz();
161 out<<"| "
162 <<std::setw(4)<<i<<" |"
163 <<std::setw(10)<<std::setprecision(4)<< layer[1][i].r ()<<" | "
164 <<std::setw(10)<<std::setprecision(4)<< zmin<<" | "
165 <<std::setw(10)<<std::setprecision(4)<< zmax<<" | "
166 <<std::setw(10)<<std::setprecision(4)<< layer[1][i].dfe()<<" | "
167 <<std::setw(4)<<layer[1][i].nElements()<<" | "
168 <<std::endl;
169 }
170 out<<"|------|-----------|------------|------------|------------|------|"
171 <<std::endl;
172
173 }
174 if(!layer[0].empty()) {
175
176 int nl = layer[0].size();
177 int nc = 0;
178 for(const auto & i : layer[0]) nc+=i.nElements();
179 out<<"|----------------------------------------------------------------|"
180 <<std::endl;
181 out<<"| L.Endcap map containt "
182 <<std::setw(4)<<nl<<" layers and "
183 <<std::setw(6)<<nc<<" elements |"
184 <<std::endl;
185
186 out<<"|------|-----------|------------|------------|------------|------|"
187 <<std::endl;
188 out<<"| n | Z | R min | R max | max dF | nEl |"
189 <<std::endl;
190 out<<"|------|-----------|------------|------------|------------|------|"
191 <<std::endl;
192 for(unsigned int i=0; i!=layer[0].size(); ++i) {
193 float rmin = layer[0][i].r()-layer[0][i].dr();
194 float rmax = layer[0][i].r()+layer[0][i].dr();
195 out<<"| "
196 <<std::setw(4)<<i<<" |"
197 <<std::setw(10)<<std::setprecision(4)<< layer[0][i].z()<<" | "
198 <<std::setw(10)<<std::setprecision(4)<< rmin<<" | "
199 <<std::setw(10)<<std::setprecision(4)<< rmax<<" | "
200 <<std::setw(10)<<std::setprecision(4)<<layer[0][i].dfe()<<" | "
201 <<std::setw(4)<<layer[0][i].nElements()<<" | "
202 <<std::endl;
203 }
204 out<<"|------|-----------|------------|------------|------------|------|"
205 <<std::endl;
206 }
207 if(!layer[2].empty()) {
208 int nl = layer[2].size();
209 int nc = 0;
210 for(const auto & i : layer[2]) nc+=i.nElements();
211 out<<"|----------------------------------------------------------------|"
212 <<std::endl;
213 out<<"| R.Endcap map containt "
214 <<std::setw(4)<<nl<<" layers and "
215 <<std::setw(6)<<nc<<" elements |"
216 <<std::endl;
217 out<<"|------|-----------|------------|------------|------------|------|"
218 <<std::endl;
219 out<<"| n | Z | R min | R max | max dF | nEl |"
220 <<std::endl;
221 out<<"|------|-----------|------------|------------|------------|------|"
222 <<std::endl;
223 for(unsigned int i=0; i!=layer[2].size(); ++i) {
224 float rmin = layer[2][i].r()-layer[0][i].dr();
225 float rmax = layer[2][i].r()+layer[0][i].dr();
226 out<<"| "
227 <<std::setw(4)<<i<<" |"
228 <<std::setw(10)<<std::setprecision(4)<< layer[2][i].z()<<" | "
229 <<std::setw(10)<<std::setprecision(4)<< rmin<<" | "
230 <<std::setw(10)<<std::setprecision(4)<< rmax<<" | "
231 <<std::setw(10)<<std::setprecision(4)<<layer[2][i].dfe()<<" | "
232 <<std::setw(4)<<layer[2][i].nElements()<<" | "
233 <<std::endl;
234 }
235 out<<"|------|-----------|------------|------------|------------|------|"
236 <<std::endl;
237 }
238 out.precision(precision);
239 return out;
240}
241
243// Dumps event information into the MsgStream
245
246MsgStream& InDet::TRT_DetElementsRoadMaker_xk::dumpEvent( MsgStream& out, int size_road)
247{
248 out<<"|--------------------------------------------------------------------|"
249 <<std::endl;
250 out<<"| Road size | "<<std::setw(12)<<size_road
251 <<" |"<<std::endl;
252 out<<"|--------------------------------------------------------------------|"
253 <<std::endl;
254
255 return out;
256}
257
259// Dumps relevant information into the ostream
261
262std::ostream& InDet::TRT_DetElementsRoadMaker_xk::dump( std::ostream& out ) const
263{
264 return out;
265}
266
268// Main methods for road builder
270
271std::vector<const InDetDD::TRT_BaseElement*>
273(const EventContext& ctx,
274 MagField::AtlasFieldCache& fieldCache,
277{
278 double qp = std::abs(500.*Tp.parameters()[4]) ;
279 if( qp < 1.e-10 ) qp = 1.e-10;
280 double S = m_step/qp ;
281 if( S > 200. ) S = 200. ;
282 if(D<0) S=-S;
283 Trk::CylinderBounds CB = getBound(fieldCache, Tp, ctx);
284 double rminTRT = getTRTMinR(ctx);
285 std::vector<const InDetDD::TRT_BaseElement*> result;
286 if( CB.r() > rminTRT) {
288 if(!fieldCache.solenoidOn()) fieldModeEnum = Trk::NoField;
289 Trk::MagneticFieldProperties fieldprop(fieldModeEnum);
290 std::deque<Amg::Vector3D> G;
291 m_proptool->globalPositions(ctx, G,Tp,fieldprop,CB,S,Trk::pion);
292 if(G.size() > 1 ) {
293 detElementsRoadATL(G,result,used,ctx);
294 }
295 }
296 return result;
297}
298
299
301// Main methods for road builder using input list global positions
302// for Atlas geometry
304
306(std::deque<Amg::Vector3D>& GP,
307 std::vector<const InDetDD::TRT_BaseElement*>& Road,
309 const EventContext& ctx) const
310{
311 int n0 = 0;
312 int n1 = 0;
313 int n2 = 0;
314 std::deque<Amg::Vector3D>::iterator g=GP.begin(),ge=GP.end();
315
316 const TRT_DetElementsLayerVectors_xk &layer = *getLayers(ctx);
317
318 float Po[6] = {float((*g).x()),float((*g).y()),float((*g).z()),
319 float(std::sqrt((*g).x()*(*g).x()+(*g).y()*(*g).y())),m_width,0.};
320
321 for(; n0!=(int)layer[0].size(); ++n0) {if(Po[2] > layer[0][n0].z()) break;}
322 for(; n1!=(int)layer[1].size(); ++n1) {if(Po[3] < layer[1][n1].r()) break;}
323 for(; n2!=(int)layer[2].size(); ++n2) {if(Po[2] < layer[2][n2].z()) break;}
324
325 std::vector<std::pair<const InDet::TRT_DetElementLink_xk*,float> > lDE;
326 for (unsigned int module_i = 0; module_i < 3; ++module_i) {
327 size_t layersSize = layer[module_i].size();
328 //Add more vectors if we need more
329 used[module_i].resize(layersSize);
330 for (unsigned int layer_i = 0; layer_i < layersSize; ++layer_i) {
331 // Although we clear/resize , we retain capacity
332 // clear what was there before
333 used[module_i][layer_i].clear();
334 //default init to false
335 used[module_i][layer_i].resize(layer[module_i][layer_i].nElements());
336 }
337 }
338
339 for(++g; g!=ge; ++g) {
340
341 float Pn[4] = {float((*g).x()),float((*g).y()),float((*g).z()),
342 float(std::sqrt((*g).x()*(*g).x()+(*g).y()*(*g).y()))};
343
344 float dx = Pn[0]-Po[0];
345 float dy = Pn[1]-Po[1];
346 float dz = Pn[2]-Po[2];
347 float st = std::sqrt(dx*dx+dy*dy+dz*dz);
348 if(st <=0.) continue;
349 float ds = 1./st;
350 float A[3]= {dx*ds,dy*ds,dz*ds};
351
352 // Barrel
353 //
354 if (Pn[3] > Po[3]) {
355 for (; n1 < (int)layer[1].size(); ++n1) {
356
357 if (Pn[3] < layer[1][n1].r())
358 break;
359 assert(used.at(1).size() > static_cast<unsigned int>(n1));
360 layer[1][n1].getBarrelDetElementsATL(Po, A, lDE, used[1][n1]);
361 }
362 } else {
363 for (--n1; n1 >= 0; --n1) {
364 if (Pn[3] > layer[1][n1].r())
365 break;
366 assert(used.at(1).size() > static_cast<unsigned int>(n1));
367 layer[1][n1].getBarrelDetElementsATL(Po, A, lDE, used[1][n1]);
368 }
369 ++n1;
370 }
371
372 // Positive endcap
373 //
374 if(Pn[2]>Po[2]) {
375
376 for (; n2 < (int)layer[2].size(); ++n2) {
377 if (Pn[2] < layer[2][n2].z())
378 break;
379 assert(used.at(2).size() > static_cast<unsigned int>(n2));
380 layer[2][n2].getEndcapDetElements(Po, A, lDE, used[2][n2]);
381 }
382 } else {
383 for (--n2; n2 >= 0; --n2) {
384 if (Pn[2] > layer[2][n2].z())
385 break;
386 assert(used.at(2).size() > static_cast<unsigned int>(n2));
387 layer[2][n2].getEndcapDetElements(Po, A, lDE, used[2][n2]);
388 }
389 ++n2;
390 }
391
392 // Negative endcap
393 //
394 if(Pn[2]<Po[2]) {
395
396 for (; n0 < (int)layer[0].size(); ++n0) {
397 if (Pn[2] > layer[0][n0].z())
398 break;
399 assert(used.at(0).size() > static_cast<unsigned int>(n0));
400 layer[0][n0].getEndcapDetElements(Po, A, lDE, used[0][n0]);
401 }
402 } else {
403 for (--n0; n0 >= 0; --n0) {
404 if (Pn[2] < layer[0][n0].z())
405 break;
406 assert(used.at(0).size() > static_cast<unsigned int>(n0));
407 layer[0][n0].getEndcapDetElements(Po, A, lDE, used[0][n0]);
408 }
409 ++n0;
410 }
411 Po[0] = Pn[0];
412 Po[1] = Pn[1];
413 Po[2] = Pn[2];
414 Po[3] = Pn[3];
415 Po[5]+= st;
416 }
417
418 // Sort list in propogation order
419 //
420 std::vector<std::pair<const InDet::TRT_DetElementLink_xk*,float> >::iterator l=lDE.begin(),le=lDE.end(),n,m;
421 if(l==le) return;
422
423 bool nc =true;
424 while(nc) {
425
426 nc =false; m=l; n=l;
427 for(++n; n!=le; ++n) {
428
429 if( (*m).second > (*n).second ) {
430 std::pair<const InDet::TRT_DetElementLink_xk*,float> d=(*m); (*m)=(*n); (*n)=d; nc=true;
431 }
432 ++m;
433 }
434 }
435
436 // Fill list pointers to detector elements
437 //
438 for(l=lDE.begin(); l!=le; ++l) {
439 Road.push_back((*l).first->detElement());
440 }
441}
442
444// Main methods for road builder using input list global positions
445// for CTB geometry
447
449(std::deque<Amg::Vector3D>& GP,
450 std::vector<const InDetDD::TRT_BaseElement*>& Road,
452 const EventContext& ctx) const
453{
454 int n1 = 0;
455 std::deque<Amg::Vector3D>::iterator g=GP.begin(),ge=GP.end();
456
457 const TRT_DetElementsLayerVectors_xk &layer = *getLayers(ctx);
458
459 float Po[6] = {float((*g).x()),float((*g).y()),float((*g).z()),
460 float(std::sqrt((*g).x()*(*g).x()+(*g).y()*(*g).y())),m_width,0.};
461
462 for(; n1!=(int)layer[1].size(); ++n1) {if(Po[3] < layer[1][n1].r()) break;}
463
464 std::vector<std::pair<const InDet::TRT_DetElementLink_xk*,float> > lDE;
465 for (unsigned int module_i = 0; module_i < 3; ++module_i) {
466 size_t layersSize = layer[module_i].size();
467 //Add more vectors if we need more
468 used[module_i].resize(layersSize);
469 for (unsigned int layer_i = 0; layer_i < layersSize; ++layer_i) {
470 // Although we clear/resize , we retain capacity
471 // clear what was there before
472 used[module_i][layer_i].clear();
473 //default init to false
474 used[module_i][layer_i].resize(layer[module_i][layer_i].nElements());
475 }
476 }
477
478 for(++g; g!=ge; ++g) {
479
480 float Pn[4] = {float((*g).x()),float((*g).y()),float((*g).z()),
481 float(std::sqrt((*g).x()*(*g).x()+(*g).y()*(*g).y()))};
482
483 float dx = Pn[0]-Po[0];
484 float dy = Pn[1]-Po[1];
485 float dz = Pn[2]-Po[2];
486 float st = std::sqrt(dx*dx+dy*dy+dz*dz);
487 float ds = 1./st;
488 float A[3]= {dx*ds,dy*ds,dz*ds};
489
490 // Barrel
491 //
492 if(Pn[3]>Po[3]) {
493 for(; n1<(int)layer[1].size(); ++n1) {
494 if(Pn[3] < layer[1][n1].r()) break;
495 assert( used.at(1).size() > static_cast<unsigned int>(n1) );
496 layer[1][n1].getBarrelDetElementsCTB(Po,A,lDE,used[1][n1]);
497 }
498 }
499 else {
500 for(--n1; n1>=0; --n1) {
501 if(Pn[3] > layer[1][n1].r()) break;
502 layer[1][n1].getBarrelDetElementsCTB(Po,A,lDE,used[1][n1]);
503 }
504 ++n1;
505 }
506 }
507
508 // Sort list in propogation order
509 //
510 std::vector<std::pair<const InDet::TRT_DetElementLink_xk*, float> >::iterator l=lDE.begin(),le=lDE.end(),n;
511 if(l==le) return;
512
513 bool nc =true;
514 while(nc) {
515
516 nc =false; n=l;
517 for(++n; n!=le; ++n) {
518
519 if( (*l).second > (*n).second ) {
520 std::pair<const InDet::TRT_DetElementLink_xk*,float> d = (*l); (*l) = (*n); (*n) = d;
521 nc = true;
522 }
523 ++l;
524 }
525 }
526
527 // Fill list pointers to detector elements
528 //
529 for(l=lDE.begin(); l!=le; ++l) {
530 Road.push_back((*l).first->detElement());
531 }
532}
533
535// Distance to detector element according stright line model
537
540{
541 Amg::Vector3D R = de->center();
542 Amg::Vector3D A = de->normal();
543 double D = a.x()*A.x()+a.y()*A.y()+a.z()*A.z(); if(D==0.) return D;
544 return ((A.x()*(R.x()-r.x())+A.y()*(R.y()-r.y())+A.z()*(R.z()-r.z()))/D);
545}
546
548// Cylinder bounds parameters estimation
550
552(MagField::AtlasFieldCache& fieldCache, const Trk::TrackParameters& Tp, const EventContext& ctx) const
553{
554 const double cor = 0.8;
555
556 double zfield = 0.;
557 if(m_fieldModeEnum!=Trk::NoField && fieldCache.solenoidOn()) {
558 const Amg::Vector3D& pos = Tp.position();
559 double f[3], p[3] ={pos[Amg::x],pos[Amg::y],pos[Amg::z]};
560 fieldCache.getFieldZR (p, f);
561 zfield = 299.7925*f[2];
562 }
563
564 const Trk::CylinderBounds bounds = get_bounds(ctx);
565
566 if( std::abs(zfield) < .0000001 ) return bounds;
567
568 const AmgVector(5)& Vp = Tp.parameters();
569
570 double cur = zfield*Vp[4]/std::sin(Vp[3]);
571
572 if( std::abs(cur)*bounds.r() < cor ) return bounds;
573 //coverity[DIVIDE_BY_ZERO:FALSE]
574 double rad = 1./cur;
575 if(cor*std::abs(rad) > bounds.r() ) return bounds;
576
577 const Amg::Vector3D& Gp = Tp.position() ;
578 double sn,cs; sincos(Vp[2],&sn,&cs);
579 double xc = Gp.x()+sn*rad ;
580 double yc = Gp.y()-cs*rad ;
581 double rm = (std::sqrt(xc*xc+yc*yc)+std::abs(rad))*cor;
582 if( rm > bounds.r() ) return bounds;
583 Trk::CylinderBounds CB(rm,bounds.halflengthZ());
584 return CB;
585}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x)
#define AmgVector(rows)
static Double_t a
static Double_t Tp(Double_t *t, Double_t *par)
static Double_t sc
#define G(x, y, z)
Definition MD5.cxx:113
#define z
static const Attributes_t empty
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
Virtual base class of TRT readout elements.
virtual const Amg::Vector3D & normal() const override final
Element Surface: normal of a straw layer.
virtual const Amg::Vector3D & center() const override final
Element Surface: center of a straw layer.
static double stepToDetElement(const InDetDD::TRT_BaseElement *&, Amg::Vector3D &, Amg::Vector3D &)
double getTRTMinR(const EventContext &ctx) const
static MsgStream & dumpEvent(MsgStream &out, int size_road)
void detElementsRoadATL(std::deque< Amg::Vector3D > &, std::vector< const InDetDD::TRT_BaseElement * > &, InDet::TRT_DetElementLink_xk::TRT_DetElemUsedMap &used, const EventContext &ctx) const
MsgStream & dumpConditions(MsgStream &out) const
TRT_DetElementsRoadMaker_xk(const std::string &, const std::string &, const IInterface *)
virtual MsgStream & dump(MsgStream &out) const override
SG::ReadCondHandleKey< TRT_DetElementsRoadData_xk > m_roadDataKey
Trk::CylinderBounds getBound(MagField::AtlasFieldCache &fieldCache, const Trk::TrackParameters &, const EventContext &ctx) const
void detElementsRoadCTB(std::deque< Amg::Vector3D > &, std::vector< const InDetDD::TRT_BaseElement * > &, InDet::TRT_DetElementLink_xk::TRT_DetElemUsedMap &used, const EventContext &ctx) const
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
PublicToolHandle< Trk::IPropagator > m_proptool
const TRT_DetElementsLayerVectors_xk * getLayers(const EventContext &ctx) const
virtual std::vector< const InDetDD::TRT_BaseElement * > detElementsRoad(const EventContext &ctx, MagField::AtlasFieldCache &fieldCache, const Trk::TrackParameters &Tp, Trk::PropDirection D, InDet::TRT_DetElementLink_xk::TRT_DetElemUsedMap &used) const override
const Trk::CylinderBounds get_bounds(const EventContext &ctx) const
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h).
bool solenoidOn() const
status of the magnets
void getFieldZR(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field valaue on the z-r plane at given position works only inside the solenoid.
Bounds for a cylindrical Surface.
virtual double r() const override final
This method returns the radius.
double halflengthZ() const
This method returns the halflengthZ.
magnetic field properties to steer the behavior of the extrapolation
MagneticFieldMode magneticFieldMode() const
Returns the MagneticFieldMode as specified.
holding In fact this class is here in order to allow STL container for all features This class is sho...
int r
Definition globals.cxx:22
Eigen::Matrix< double, 3, 1 > Vector3D
PropDirection
PropDirection, enum for direction of the propagation.
MagneticFieldMode
MagneticFieldMode describing the field setup within a volume.
@ FastField
call the fast field access method of the FieldSvc
@ NoField
Field is set to 0., 0., 0.,.
@ FullField
Field is set to be realistic, but within a given Volume.
ParametersBase< TrackParametersDim, Charged > TrackParameters
hold the test vectors and ease the comparison