StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StPmdSimulatorMaker.cxx
1 /***************************************************************
2  *
3  * $Id: StPmdSimulatorMaker.cxx,v 1.14 2017/04/26 19:57:00 perev Exp $
4  * Author: Subhasis Chattopadhyay
5  ***************************************************************
6  *
7  * Description: StPmdSimulatorMaker is class for Pmd Simulation
8  *
9  ****************************************************************
10  * changed detector(1) for PMD and detector(0) for CPV while
11  * filling StPmdCollection : Dipak
12  *
13  * $Log: StPmdSimulatorMaker.cxx,v $
14  * Revision 1.14 2017/04/26 19:57:00 perev
15  * Hide m_DataSet
16  *
17  * Revision 1.13 2007/04/26 04:14:57 perev
18  * Remove StBFChain dependency
19  *
20  * Revision 1.12 2004/09/22 19:24:56 perev
21  * Leak fixed + mess with i,j indexes
22  *
23  * Revision 1.11 2004/06/24 13:52:52 subhasis
24  * numbering of det0 and det1 interchanged
25  *
26  * Revision 1.10 2004/01/26 23:01:49 perev
27  * WarnOff
28  *
29  * Revision 1.9 2003/11/27 12:33:41 subhasis
30  * calib constant values updated
31  *
32  * Revision 1.8 2003/10/23 04:25:29 perev
33  * Stiostream again
34  *
35  * Revision 1.7 2003/10/15 10:40:18 subhasis
36  * Changes by Dipak (eg GeV to keV
37  *
38  * Revision 1.5 2003/08/14 10:37:35
39  * Edep changed from GeV to Kev
40  * Proper binning of the histograms added.
41  **
42  * Revision 1.4 2003/05/12 11:37:35 subhasis
43  * Stevent added
44  *
45  * Revision 1.3 2002/09/09 11:39:08 subhasis
46  * warning removed
47  *
48  * Revision 1.2 2002/09/05 06:21:05 subhasis
49  * Calibration and readout resolution added
50  *
51  ****************************************************************
52  ****************************************************************/
53 #include "Stiostream.h"
54 #include <assert.h>
55 #include <math.h>
56 #include "TROOT.h"
57 #include <TRandom.h>
58 #include <TBrowser.h>
59 #include <StMessMgr.h>
60 #include "StPmdSimulatorMaker.h"
62 #include "StPhmdCollection.h"
63 #include "StPhmdClusterCollection.h"
64 #include "StPhmdDetector.h"
65 #include "StPhmdHit.h"
66 #include "StPhmdModule.h"
67 
68 #include "StPmdUtil/StPmdCollection.h"
69 #include "StPmdUtil/StPmdDetector.h"
70 #include "StPmdUtil/StPmdHit.h"
71 #include "StPmdUtil/StPmdModule.h"
72 #include "StPmdUtil/StPmdMapUtil.h"
73 #include "tables/St_g2t_pmd_hit_Table.h"
74 #include "tables/St_g2t_track_Table.h"
75 #include <TTableSorter.h>
76 // added for StEvent
77 #include "StEvent/StEvent.h"
78 #include "StEvent/StEventTypes.h"
79 
80 
81 ClassImp(StPmdSimulatorMaker)
82 
83  TDataSet *geaIn;
84 
85 St_g2t_pmd_hit *g2t_pmd_hit;
86 StPmdGeom *mpmdgeom;
87 StPmdMapUtil *mPmdMapUtil; // Mapping from SM,row,col to Chain Number
88 
89 //St_g2t_track *track;
90 
92 {
94  adcconstants();
95  mpmdgeom=new StPmdGeom();
96  mPmdMapUtil= new StPmdMapUtil();
97  mPmdCollection=NULL;
98  gMessMgr->SetLimit("StPmdSimulator",100);
99 }
100 
101 StPmdSimulatorMaker::~StPmdSimulatorMaker()
102 {
103  delete mpmdgeom;
104  delete mPmdMapUtil;
105 }
106 
108 {
109  bookHistograms();
110  return StMaker::Init();
111 }
112 void StPmdSimulatorMaker::bookHistograms()
113 {
114  m_pmdEdep2D = new TH2F("PMDEdep2D" ,"PMD Edep (2D)",150,-150.,150.,150,-150.,150.);
115  m_cpvEdep2D = new TH2F("CPVEdep2D" ,"CPV Edep (2D)",150,-150.,150.,150,-150.,150.);
116 
117  mEdepPmd = new TH1F("PmdEdep" ,"Edep for PMD",1000,0.,500.);
118  mEdepPmd_part = new TH1F("PmdEdep_part" ,"Edep Part for PMD",1000,0.,1000.);
119  mPmdAdc = new TH1F("pmdadc" ,"ADC for PMD",1000, 0.,1000.);
120  mHitPmd = new TH1F("PMDHit" ,"Hits for PMD",9000, -0.5,8999.5);
121 
122  mEdepCpv = new TH1F("CpvEdep" ,"Edep for CPV",400,0.,200.);
123  mEdepCpv_part = new TH1F("CpvEdep_part" ,"Edep Part for CPV",200,0.,200.);
124  mCpvAdc = new TH1F("cpvadc" ,"ADC for CPV",1000, 0.,1000.);
125  mHitCpv = new TH1F("CpvHit" ,"Hits for CPV",5000, -0.5,4999.5);
126 
127  m_pmdsuper = new TH1F("PmdSuper" ,"Super for PMD",12,0.5,12.5);
128  m_pmdrow = new TH2F("PMD_SupervsRow" ,"Pmd super vs row",12,0.5,12.5,100,0.5,100.5);
129  m_pmdcol = new TH2F("PMD_SupervsCol" ,"Pmd super vs col",12,0.5,12.5,100,0.5,100.5);
130 
131  m_cpvsuper = new TH1F("CpvSuper" ,"Super for CPV",12,0.5,12.5);
132  m_cpvrow = new TH2F("CPV_SupervsRow" ,"Cpv super vs row",12,0.5,12.5,100,0.5,100.5);
133  m_cpvcol = new TH2F("CPV_SupervsCol" ,"Cpv super vs col",12,0.5,12.5,100,0.5,100.5);
134 
135 }
136 
137 
139 {
141  geaIn = GetDataSet("geant");
142  if (geaIn == 0) {
143  geaIn = GetDataSet("event/geant/Event");
144  if (geaIn == 0) {
145  gMessMgr->Error()<<"Geant Data didn't find in event/geant/Event and geant directories"<<endm;
146  return kStWarn;
147  }
148  }
149 
150  Int_t retpmd;
151  retpmd = GetPmd();
152  return retpmd;
153 }
154 
156 {
157  g2t_pmd_hit = (St_g2t_pmd_hit *) geaIn->Find("g2t_pmd_hit");
158  // track = (St_g2t_track *) geaIn->Find("g2t_track");
159 
160  if ( g2t_pmd_hit && g2t_pmd_hit->GetTableSize()>0)
161  { // O"k
162 
163  Int_t phit=makePmdHits();
164  if(phit!=kStOK){cout<<"problem in Hit formation"<<endl;return kStWarn;}
165  }
166  else gMessMgr->Warning()<<
167  "StPmdSimulatorMaker::makePmd=>table g2t_PMD_hit isn't found in dataset or size is 0 "<<
168  geaIn->GetName()<<endm;
169  return kStOK;
170 }
171 
174 {
178  mPmdCollection = new StPmdCollection("PmdCollection");
179  AddData(mPmdCollection);
180  StPmdDetector* det0 = mPmdCollection->detector(1);
181  StPmdDetector* det1 = mPmdCollection->detector(0);
182 
183  g2t_pmd_hit_st *hit = g2t_pmd_hit->GetTable();
184  Int_t nhits = g2t_pmd_hit->GetNRows();
185 
186  // g2t_track_st *tra = track->GetTable();
187 
188  if(nhits<=0)
189  {
190  return kStWarn;
191  }
192  for(Int_t ihit=0; ihit<nhits; ihit++,hit++) {
193  Int_t sector=0,super=0,subdet=0,row=0,col=0;
194  Int_t gsuper;
195 
197 
198  Int_t decode=Decode_VolId(hit->volume_id,sector,super,subdet,row,col);
199 
201  mpmdgeom->NModule(Int_t(sector),Int_t(super),gsuper);
202 
204 
205  mpmdgeom->Sim2Detmap(gsuper,row,col);
206 
208 
209  if(decode==kStOK)
210  {
211  StPmdHit *phit = new StPmdHit();
212  phit->setGsuper(Int_t(gsuper));
213  phit->setSubDetector(Int_t(subdet));
214  phit->setRow(Int_t(row));
215  phit->setColumn(Int_t(col));
216  phit->setEdep((hit->de)*1000000.);
217 
218 //VP Int_t ChainNo;
219  Float_t xPMD,yPMD;
220  if(subdet==1){
221 
222  /**** Switch OFF the chains which were not working in RUN-4 *****/
223  /*
224  mPmdMapUtil->ChainNumber(gsuper+12,row,col,ChainNo);
225  Int_t BeamEnergy;
226  BeamEnergy = 0; //Default setting
227  switch(BeamEnergy)
228  {
229  case 1: //For 62 GeV data
230  if(ChainNo == 25 || ChainNo == 27 || ChainNo == 38 || ChainNo == 39 || ChainNo == 40 ||
231  ChainNo ==45 || ChainNo == 47 || ChainNo == 48)
232  {
233  hit->de =0.;
234  phit->setEdep(0.); //Putting the cell Edep as Zero
235  break;
236  }
237  }
238  */
239 
240  if(det0->module_hit(Int_t(gsuper))==0)
241  {
242  det0->addHit(phit);
243  }
244  else
245  {
246  //if phit already exist
247  StPmdHit *hitmatched=Exist(phit,det0,Int_t(gsuper));
248  if(hitmatched)
249  {
250  Float_t newEdep=hitmatched->Edep()+(hit->de)*1000000.;
251  hitmatched->setEdep(newEdep);
252  delete phit;
253  }
254  else
255  {
256  det0->addHit(phit);
257  }
258  }
259 
260  m_pmdEdep2D->Fill(xPMD,yPMD,hit->de);
262  m_pmdsuper->Fill(Float_t(gsuper));
263  m_pmdrow->Fill(Float_t(gsuper),Float_t(row));
264  m_pmdcol->Fill(Float_t(gsuper),Float_t(col));
265  }
266 
267  if(subdet==2){
268  if(det1->module_hit(Int_t(gsuper))==0)
269  {
270  det1->addHit(phit);}
271  else
272  {
273  //if phit already exist
274  StPmdHit *hitmatched=Exist(phit,det1,Int_t(gsuper));
275  if(hitmatched)
276  {
277  Float_t newEdep=hitmatched->Edep()+(hit->de)*1000000.;
278  hitmatched->setEdep(newEdep);
279  delete phit;
280  }
281  else
282  {
283  det1->addHit(phit);
284  }
285  }
287  Float_t xCPV,yCPV,etaCPV,phiCPV;
288  mpmdgeom->DetCell_xy(gsuper,Int_t(row),Int_t(col),xCPV,yCPV,etaCPV,phiCPV);
289  m_cpvEdep2D->Fill(xCPV,yCPV,hit->de);
291  m_cpvsuper->Fill(Float_t(gsuper));
292  m_cpvrow->Fill(Float_t(gsuper),Float_t(row));
293  m_cpvcol->Fill(Float_t(gsuper),Float_t(col));
294  }
295  }
296  }
297 
298 
299  if(det0)
300  {
301  for(Int_t ii=1;ii<13;ii++)
302  {
303  FinalEdep(det0,ii);
304  }
305  }
306  if(det1)
307  {
308  for(Int_t ii=1;ii<13;ii++)
309  {
310  FinalEdep(det1,ii);
311  }
312  }
313 
314  for(Int_t ii=1;ii<13;ii++)
315  {
316  FillHistograms(det0,det1,ii);
317  }
319  fillStEvent(det0,det1);
320 
321  return kStOK;
322 }
323 
325 {
326  // if(mPmdCollection) b->Add((TDataSet*)mPmdCollection);
327  TDataSet::Browse(b);
328 }
329 
331 
332 Int_t StPmdSimulatorMaker::Decode_VolId(Int_t& vol, Int_t& sector, Int_t& super,Int_t& subdet, Int_t& row, Int_t& col)
333 {
334 
335  Int_t temp0=vol%1000000;
336  Int_t temp1=temp0%100000;
337  Int_t temp2=temp1%10000;
338  Int_t temp3=temp2%100;
339 
340  col=temp3;
341  row=temp2/100;
342  subdet=temp1/10000;
343  super=temp0/100000;
344  sector=vol/1000000;
345 
346  return kStOK;
347 
348 }
349 
351 {
352  Int_t xpad,ypad,super;
353  Int_t nmh=pdet->module_hit(id);
354  StPmdModule * pmod=pdet->module(id);
355  TIter next(pmod->Hits());
356  StPmdHit *spmcl;
357  // Loop over hits for each SM
358  for(Int_t im=0; im<nmh; im++)
359  {
360  spmcl = (StPmdHit*)next();
361  if(spmcl)
362  {
363  ypad=spmcl->Row();
364  xpad=spmcl->Column();
365  super = spmcl->Gsuper();
366  if(phit->Row()==ypad && phit->Column()==xpad && phit->Gsuper() == super) return spmcl;
367  }
368  }
369  return NULL;
370 }
371 
372 
374 {
375  StPmdModule* pmd_mod=pmd_det->module(id);
376  Int_t nmh1=pmd_det->module_hit(id);
377  Float_t edep_part = 0.;
378  if(nmh1>0){
379  TIter next(pmd_mod->Hits());
380  StPmdHit *spmcl1;
381  for(Int_t im=0; im<nmh1; im++)
382  {
383  spmcl1 = (StPmdHit*)next();
384  if(spmcl1)
385  {
386  Int_t gsuper = spmcl1->Gsuper();
387  Int_t row=spmcl1->Row();
388  Int_t col=spmcl1->Column();
389  Float_t edep=spmcl1->Edep();
390  Int_t adc=spmcl1->Adc();
391 
392  if(edep>0.)mEdepPmd->Fill(edep);
393  if(edep>0.) edep_part = edep_part+edep;
394  mPmdAdc->Fill(Float_t(adc));
395  Float_t xPMD,yPMD,etaPMD,phiPMD;
396  mpmdgeom->DetCell_xy(gsuper,Int_t(row),Int_t(col),xPMD,yPMD,etaPMD,phiPMD);
397  m_pmdEdep2D->Fill(xPMD,yPMD,edep);
398  m_pmdsuper->Fill(Float_t(gsuper));
399  m_pmdrow->Fill(Float_t(gsuper),Float_t(row));
400  m_pmdcol->Fill(Float_t(gsuper),Float_t(col));
401  }
402  }
403  }
404  if(nmh1>0)mHitPmd->Fill(nmh1);
405 
406  if(edep_part>0) mEdepPmd_part->Fill(edep_part);
407 
408 
409  StPmdModule* cpv_mod=cpv_det->module(id);
410  edep_part = 0.;
411  Int_t nmh2=cpv_det->module_hit(id);
412  if(nmh2>0){
413  TIter next(cpv_mod->Hits());
414  StPmdHit *spmcl2;
415 
416  for(Int_t im=0; im<nmh2; im++)
417  {
418 
419  spmcl2 = (StPmdHit*)next();
420  if(spmcl2){
421  Int_t gsuper = spmcl2->Gsuper();
422  Int_t row=spmcl2->Row();
423  Int_t col=spmcl2->Column();
424  Float_t edep=spmcl2->Edep();
425 
426  Float_t xCPV,yCPV,etaCPV,phiCPV;
427  mpmdgeom->DetCell_xy(gsuper,Int_t(row),Int_t(col),xCPV,yCPV,etaCPV,phiCPV);
428 
429  mEdepCpv->Fill(edep);
430  if(edep>0.4) edep_part = edep_part+edep;
431 
432  mpmdgeom->DetCell_xy(gsuper,Int_t(row),Int_t(col),xCPV,yCPV,etaCPV,phiCPV);
433 
434  m_cpvEdep2D->Fill(xCPV,yCPV,edep);
435  m_cpvsuper->Fill(Float_t(gsuper));
436  m_cpvrow->Fill(Float_t(gsuper),Float_t(row));
437  m_cpvcol->Fill(Float_t(gsuper),Float_t(col));
438  }
439  }
440  }
441  if(nmh2>0)mHitCpv->Fill(nmh2);
442 
443  if(edep_part>0) mEdepCpv_part->Fill(edep_part);
444 }
445 
446 
447 
449 {
450  StEvent *currevent = (StEvent*)GetInputDS("StEvent");
452  currevent->setPhmdCollection(mevtPmdCollection);
453 
454  StPhmdDetector* evtdet0 = mevtPmdCollection->detector(StDetectorId(kPhmdId));
455  StPhmdDetector* evtdet1 = mevtPmdCollection->detector(StDetectorId(kPhmdCpvId));
456 
457 
458  for(Int_t id=1;id<13;id++)
459  {
460 
461  // Int_t hitpmd=0, hitcpv=0;
462  Int_t subdet=1;
463  //Filling StEvent for PMD
464 
465  StPmdModule * pmd_mod=pmd_det->module(id);
466  Int_t nmh1=pmd_det->module_hit(id);
467  if(nmh1>0)
468  {
469  TIter next(pmd_mod->Hits());
470  StPmdHit *spmcl1;
471  for(Int_t im=0; im<nmh1; im++)
472  {
473  spmcl1 = (StPmdHit*)next();
474  if(spmcl1)
475  {
476  Int_t gsuper=spmcl1->Gsuper();
477  Int_t col=spmcl1->Column();
478  Int_t row=spmcl1->Row();
479  Float_t edep=spmcl1->Edep();
480  Int_t adc=spmcl1->Adc();
482  StPhmdHit *phit = new StPhmdHit();
483  phit->setSuperModule(Int_t(gsuper-1)); // filling supermodule no (range 0-11)
484  phit->setSubDetector(Int_t(subdet)); // filling subdetector PMD = 1 and CPV = 2
485  phit->setRow(Int_t(row)); // filling row 1-72
486  phit->setColumn(Int_t(col)); // filling col 1-96
487  phit->setEnergy(edep); // filling energy in KeV
488  phit->setAdc(adc); // filling energy(ADC)
489  evtdet0->addHit(phit);
490  }
491  }
492  }
493 
494  // Filling StEvent for CPV
495  StPmdModule * cpv_mod=cpv_det->module(id);
496  Int_t nmh2=cpv_det->module_hit(id);
497  if(nmh2>0)
498  {
499  subdet=2;
500  TIter next(cpv_mod->Hits());
501  StPmdHit *spmcl2;
502  for(Int_t im=0; im<nmh2; im++)
503  {
504  spmcl2 = (StPmdHit*)next();
505  if(spmcl2)
506  {
507  Int_t gsuper=spmcl2->Gsuper();
508  Int_t col=spmcl2->Column();
509  Int_t row=spmcl2->Row();
510  Float_t edep=spmcl2->Edep();
511  Int_t adc=spmcl2->Adc();
513  StPhmdHit *phit = new StPhmdHit();
514  phit->setSuperModule(Int_t(gsuper-1)); // filling supermodule no (0-11)
515  phit->setSubDetector(Int_t(subdet)); // filling subdetector PMD=1 and CPV=2
516  phit->setRow(Int_t(row)); // filling row 1-72
517  phit->setColumn(Int_t(col)); // filling col 1-96
518  phit->setEnergy(edep); // filling energy in KeV
519  phit->setAdc(adc); // filling energy(ADC)
520  evtdet1->addHit(phit);
521  }
522  }
523  }
524  }
525 
526  return kStOK;
527 }
528 
529 void StPmdSimulatorMaker::FinalEdep(StPmdDetector* pdet,Int_t id)
530 {
531 
532  StPmdModule * mod=pdet->module(id);
533  Int_t nmh=pdet->module_hit(id);
534  if(nmh>0)
535  {
536  TIter next(mod->Hits());
537  StPmdHit *spmcl;
538  for(Int_t im=0; im<nmh; im++)
539  {
540  Float_t rawadc=0.;
541  //Float_t Edep=0.;
542  Int_t ADC=0;
543  spmcl = (StPmdHit*)next();
544  if(spmcl)
545  {
546  Float_t rawedep=spmcl->Edep();
547  Float_t keVedep=rawedep;
548  keV_ADC(keVedep,rawadc);
549  if(mResFlag) ADC_Readout(rawadc,ADC);
550  else ADC = (int)rawadc;
551  //commented because of saturation problem in Edep
552 
553  // mpmdgeom->ADC2Edep(ADC,Edep); //Again changeing back to Edep
554  // spmcl->setEdep(Edep);
555  spmcl->setAdc(ADC);
556  }
557  }
558  }
559 }
560 
561 Float_t StPmdSimulatorMaker::keV_ADC(Float_t edep, Float_t& adc)
562 {
563  adc=mlcon0 + mlcon1*edep + mlcon2*pow(edep,2);
564  return kStOK;
565 }
566 
567 Float_t StPmdSimulatorMaker::ADC_Readout(Float_t adc,Int_t& ADC)
568 {
569  Float_t reso_percent=0., reso=0.;
570  reso_percent=mpcon0 + mpcon1*adc + mpcon2*pow(adc,2);
571  reso=(reso_percent*100.)/adc;
572 
573  Float_t adcprime=gRandom->Gaus(adc,reso);
574  if(adcprime<0)adcprime=0;
575  ADC=Int_t(adcprime);
576  return kStOK;
577 }
578 
579 
580 
581 
582 
583 
584 
Int_t GetPmd()
Getting GEANT tables from input file.
bool addHit(StPmdHit *)
no of modules
Int_t fillStEvent(StPmdDetector *, StPmdDetector *)
Int_t module_hit(Int_t)
module number
StPmdDetector * detector(Int_t)
destructor
TH2F * m_cpvrow
Pmd super vs row.
Int_t Decode_VolId(Int_t &, Int_t &, Int_t &, Int_t &, Int_t &, Int_t &)
Making Pmd hits after slow simulation.
void FillHistograms(StPmdDetector *, StPmdDetector *, Int_t)
Booking histograms.
StPhmdCollection * mevtPmdCollection
Pmd and CPV collections.
TH1F * m_cpvsuper
total no of Supermodules for PMD
virtual void AddData(TDataSet *data, const char *dir=".data")
User methods.
Definition: StMaker.cxx:332
TH2F * m_pmdcol
Cpv super vs row.
TH1F * mHitPmd
total ADC on PMD
TH1F * mCpvAdc
Total edep on CPV.
TH1F * mEdepPmd
2D-Edep Display of Cpv
virtual void Browse(TBrowser *b)
Browse this dataset (called by TBrowser).
Definition: TDataSet.cxx:297
void Sim2Detmap(Int_t &, Int_t &, Int_t &)
function for convering supermodule,row,col (from GEANT) to supermodule,row,col as in hardware...
Definition: StPmdGeom.cxx:300
TH2F * m_pmdEdep2D
Pmd and CPV collections for Stevent.
void DetCell_xy(Int_t, Float_t, Float_t, Float_t &, Float_t &, Float_t &, Float_t &)
function for converting supermodule,row,col to x,y,eta,phi after conversionfrom 17 to 12 supermodule ...
Definition: StPmdGeom.cxx:227
Int_t Row() const
function for subdetector
Definition: StPmdHit.h:95
Int_t Column() const
function for row
Definition: StPmdHit.h:96
TH2F * m_cpvEdep2D
2D-Edep Display of Pmd
TH1F * m_pmdsuper
total no of hits on Cpv
void Browse(TBrowser *b)
Readout resolution is applied when Flag = 1.
virtual Int_t Init()
A destructor.
TH2F * m_cpvcol
Pmd super vs col.
Int_t makePmdHits()
Getting Pmdhits from geant.
Int_t NModule(Int_t, Int_t, Int_t &)
A destructor.
Definition: StPmdGeom.cxx:199
void setGsuper(Int_t)
Cell status (chain selection based)
Definition: StPmdHit.h:104
Definition: Stypes.h:42
Int_t Gsuper() const
A destructor.
Definition: StPmdHit.h:91
Definition: Stypes.h:40
TH1F * mEdepPmd_part
cell edep on Pmd
TH1F * mPmdAdc
total edep on Pmd
TH1F * mEdepCpv
total no of hits on Pmd
StPmdHit * Exist(StPmdHit *, StPmdDetector *, Int_t)
decoding
Float_t Edep() const
function for col
Definition: StPmdHit.h:97
StPmdModule * module(unsigned int)
number of hits
TH1F * mEdepCpv_part
cell edep on CPV
virtual TDataSet * Find(const char *path) const
Definition: TDataSet.cxx:362
TH2F * m_pmdrow
total no of Supermodules for CPV
TH1F * mHitCpv
Total ADC on CPV.