X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=TPC%2FAliTPCCalPad.cxx;h=e91e4e8d36c192138e63fbaac2ec556f4aae0d27;hb=0d66cd7dd3209041764a4e08827617c44c963f48;hp=2de44a500fcba203e2faaffeb3c949d4af871069;hpb=7390f65563d0160da8c835fb4c8570799568ff55;p=u%2Fmrichter%2FAliRoot.git diff --git a/TPC/AliTPCCalPad.cxx b/TPC/AliTPCCalPad.cxx index 2de44a500fc..e91e4e8d36c 100644 --- a/TPC/AliTPCCalPad.cxx +++ b/TPC/AliTPCCalPad.cxx @@ -36,6 +36,16 @@ #include #include #include +#include + +//graphic includes +#include +#include +#include +#include +#include +#include + ClassImp(AliTPCCalPad) @@ -370,7 +380,7 @@ Double_t AliTPCCalPad::GetLTM(Double_t *sigma, Double_t fraction, AliTPCCalPad* } //_____________________________________________________________________________ -TH1F * AliTPCCalPad::MakeHisto1D(Float_t min, Float_t max,Int_t type){ +TH1F * AliTPCCalPad::MakeHisto1D(Float_t min, Float_t max,Int_t type, Int_t side){ // // make 1D histo // type -1 = user defined range @@ -403,10 +413,11 @@ TH1F * AliTPCCalPad::MakeHisto1D(Float_t min, Float_t max,Int_t type){ max = mean+sigma; } } - char name[1000]; - sprintf(name,"%s Pad 1D",GetTitle()); - TH1F * his = new TH1F(name,name,100, min,max); + TString name=Form("%s Pad 1D",GetTitle()); + TH1F * his = new TH1F(name.Data(),name.Data(),100, min,max); for (Int_t isec = 0; isec < kNsec; isec++) { + if (side==1 && isec%36>18) continue; + if (side==-1 && isec%36<18) continue; if (fROC[isec]){ for (UInt_t irow=0; irowGetNrows(); irow++){ UInt_t npads = (Int_t)fROC[isec]->GetNPads(irow); @@ -509,18 +520,11 @@ AliTPCCalPad* AliTPCCalPad::GlobalFit(const char* padName, AliTPCCalPad* PadOutl } return pad; } - -void AliTPCCalPad::GlobalSidesFit(const AliTPCCalPad* PadOutliers, const char* fitFormula, TVectorD &fitParamSideA, TVectorD &fitParamSideC,TMatrixD &covMatrixSideA, TMatrixD &covMatrixSideC, Float_t & chi2SideA, Float_t & chi2SideC, Double_t pointError, Bool_t robust, Double_t robustFraction){ - // - // Performs a fit on both sides. - // Valid information for the fitFormula are the variables - // - gx, gy, lx ,ly: meaning global x, global y, local x, local y value of the padName - // - sector: the sector number. - // eg. a formula might look 'gy' or '(sector<36) ++ gy' or 'gx ++ gy' or 'gx ++ gy ++ lx ++ lx^2' and so on +//_____________________________________________________________________________ +TObjArray* AliTPCCalPad::CreateFormulaArray(const char *fitFormula) +{ // - // PadOutliers - pads with value !=0 are not used in fitting procedure - // chi2Threshold: Threshold for chi2 when EvalRobust is called - // robustFraction: Fraction of data that will be used in EvalRobust + // create an array of TFormulas for the each parameter of the fit function // // split fit string in single parameters @@ -530,16 +534,6 @@ void AliTPCCalPad::GlobalSidesFit(const AliTPCCalPad* PadOutliers, const char* f fitString.ReplaceAll(" ",""); TObjArray *arrFitParams = fitString.Tokenize("#"); Int_t ndim = arrFitParams->GetEntries(); - //resize output data arrays - fitParamSideA.ResizeTo(ndim+1); - fitParamSideC.ResizeTo(ndim+1); - covMatrixSideA.ResizeTo(ndim+1,ndim+1); - covMatrixSideC.ResizeTo(ndim+1,ndim+1); - // create linear fitter for A- and C- Side - TLinearFitter* fitterGA = new TLinearFitter(ndim+1,Form("hyp%d",ndim)); - TLinearFitter* fitterGC = new TLinearFitter(ndim+1,Form("hyp%d",ndim)); - fitterGA->StoreData(kTRUE); - fitterGC->StoreData(kTRUE); //create array of TFormulas to evaluate the parameters TObjArray *arrFitFormulas = new TObjArray(ndim); arrFitFormulas->SetOwner(kTRUE); @@ -552,36 +546,87 @@ void AliTPCCalPad::GlobalSidesFit(const AliTPCCalPad* PadOutliers, const char* f s.ReplaceAll("sector","[4]"); arrFitFormulas->AddAt(new TFormula(Form("param%02d",idim),s.Data()),idim); } - //loop over data and add points to the fitter + delete arrFitParams; + + return arrFitFormulas; +} +//_____________________________________________________________________________ +void AliTPCCalPad::EvalFormulaArray(const TObjArray &arrFitFormulas, TVectorD &results, + const Int_t sec, const Int_t row, const Int_t pad) +{ + // + // evaluate the fit formulas + // + Int_t ndim=arrFitFormulas.GetEntries(); + results.ResizeTo(ndim); + AliTPCROC* tpcROCinstance = AliTPCROC::Instance(); // to calculate the pad's position Float_t localXYZ[3]; Float_t globalXYZ[3]; + tpcROCinstance->GetPositionLocal(sec, row, pad, localXYZ); + tpcROCinstance->GetPositionGlobal(sec, row, pad, globalXYZ); + //calculate parameter values + for (Int_t idim=0;idimSetParameters(globalXYZ[0],globalXYZ[1],localXYZ[0],localXYZ[1],sec); + results[idim]=f->Eval(0); + } +} +//_____________________________________________________________________________ +void AliTPCCalPad::GlobalSidesFit(const AliTPCCalPad* PadOutliers, const char* fitFormula, TVectorD &fitParamSideA, TVectorD &fitParamSideC,TMatrixD &covMatrixSideA, TMatrixD &covMatrixSideC, Float_t & chi2SideA, Float_t & chi2SideC, AliTPCCalPad *pointError, Bool_t robust, Double_t robustFraction){ + // + // Performs a fit on both sides. + // Valid information for the fitFormula are the variables + // - gx, gy, lx ,ly: meaning global x, global y, local x, local y value of the padName + // - sector: the sector number. + // eg. a formula might look 'gy' or '(sector<36) ++ gy' or 'gx ++ gy' or 'gx ++ gy ++ lx ++ lx^2' and so on + // + // PadOutliers - pads with value !=0 are not used in fitting procedure + // chi2Threshold: Threshold for chi2 when EvalRobust is called + // robustFraction: Fraction of data that will be used in EvalRobust + // + + TObjArray* arrFitFormulas=CreateFormulaArray(fitFormula); + Int_t ndim = arrFitFormulas->GetEntries(); + //resize output data arrays + fitParamSideA.ResizeTo(ndim+1); + fitParamSideC.ResizeTo(ndim+1); + covMatrixSideA.ResizeTo(ndim+1,ndim+1); + covMatrixSideC.ResizeTo(ndim+1,ndim+1); + // create linear fitter for A- and C- Side + TLinearFitter* fitterGA = new TLinearFitter(ndim+1,Form("hyp%d",ndim)); + TLinearFitter* fitterGC = new TLinearFitter(ndim+1,Form("hyp%d",ndim)); + fitterGA->StoreData(kTRUE); + fitterGC->StoreData(kTRUE); + //parameter values TVectorD parValues(ndim); + + AliTPCCalROC *rocErr=0x0; for (UInt_t isec = 0; isecGetCalROC(isec); AliTPCCalROC *rocData=GetCalROC(isec); + if (pointError) rocErr=pointError->GetCalROC(isec); if (!rocData) continue; for (UInt_t irow = 0; irow < GetCalROC(isec)->GetNrows(); irow++) { for (UInt_t ipad = 0; ipad < GetCalROC(isec)->GetNPads(irow); ipad++) { //check for outliers if (rocOut && rocOut->GetValue(irow,ipad)) continue; - //calculate local and global pad positions - tpcROCinstance->GetPositionLocal(isec, irow, ipad, localXYZ); - tpcROCinstance->GetPositionGlobal(isec, irow, ipad, globalXYZ); //calculate parameter values - for (Int_t idim=0;idimAt(idim); - f->SetParameters(globalXYZ[0],globalXYZ[1],localXYZ[0],localXYZ[1],isec); - parValues[idim]=f->Eval(0); - } + EvalFormulaArray(*arrFitFormulas,parValues,isec,irow,ipad); //get value Float_t value=rocData->GetValue(irow,ipad); + //point error + Int_t err=1; + if (rocErr) { + err=TMath::Nint(rocErr->GetValue(irow,ipad)); + if (err==0) err=1; + } //add points to the fitters if (isec/18%2==0){ - fitterGA->AddPoint(parValues.GetMatrixArray(),value,pointError); + fitterGA->AddPoint(parValues.GetMatrixArray(),value,err); }else{ - fitterGC->AddPoint(parValues.GetMatrixArray(),value,pointError); + fitterGC->AddPoint(parValues.GetMatrixArray(),value,err); } } } @@ -600,151 +645,242 @@ void AliTPCCalPad::GlobalSidesFit(const AliTPCCalPad* PadOutliers, const char* f fitterGA->GetCovarianceMatrix(covMatrixSideA); fitterGC->GetCovarianceMatrix(covMatrixSideC); - delete arrFitParams; delete arrFitFormulas; delete fitterGA; delete fitterGC; } - -/* -void AliTPCCalPad::GlobalSidesFit(const AliTPCCalPad* PadOutliers, TVectorD &fitParamSideA, TVectorD &fitParamSideC,TMatrixD &covMatrixSideA, TMatrixD &covMatrixSideC, Float_t & chi2SideA, Float_t & chi2SideC, Int_t fitType, Bool_t robust, Double_t chi2Threshold, Double_t robustFraction){ +// +AliTPCCalPad *AliTPCCalPad::CreateCalPadFit(const char* fitFormula, const TVectorD &fitParamSideA, const TVectorD &fitParamSideC) +{ // - // Makes a GlobalFit over each side and return fit-parameters, covariance and chi2 for each side - // fitType == 0: fit plane function - // fitType == 1: fit parabolic function - // PadOutliers - pads with value !=0 are not used in fitting procedure - // chi2Threshold: Threshold for chi2 when EvalRobust is called - // robustFraction: Fraction of data that will be used in EvalRobust // - TLinearFitter* fitterGA = 0; - TLinearFitter* fitterGC = 0; - - if (fitType == 1) { - fitterGA = new TLinearFitter (6,"x0++x1++x2++x3++x4++x5"); - fitterGC = new TLinearFitter (6,"x0++x1++x2++x3++x4++x5"); - } - else { - fitterGA = new TLinearFitter(3,"x0++x1++x2"); - fitterGC = new TLinearFitter(3,"x0++x1++x2"); + // + TObjArray *arrFitFormulas=CreateFormulaArray(fitFormula); + Int_t ndim = arrFitFormulas->GetEntries(); + //check if dimension of fit formula and fit parameters agree + if (ndim!=fitParamSideA.GetNrows()||ndim!=fitParamSideC.GetNrows()){ + printf("AliTPCCalPad::CreateCalPadFit: Dimensions of fit formula and fit Parameters does not match!"); + return 0; } - fitterGA->StoreData(kTRUE); - fitterGC->StoreData(kTRUE); - fitterGA->ClearPoints(); - fitterGC->ClearPoints(); - Double_t xx[6]; - Int_t npointsA=0; - Int_t npointsC=0; - - Float_t localXY[3] = {0}; // pad's position, needed to get the pad's position - Float_t lx, ly; // pads position - - AliTPCROC* tpcROCinstance = AliTPCROC::Instance(); // to calculate the pad's position - - // loop over all sectors and pads and read data into fitterGA and fitterGC - if (fitType == 1) { - // parabolic fit - fitParamSideA.ResizeTo(6); - fitParamSideC.ResizeTo(6); - covMatrixSideA.ResizeTo(6,6); - covMatrixSideC.ResizeTo(6,6); - for (UInt_t isec = 0; isec<72; isec++){ - for (UInt_t irow = 0; irow < GetCalROC(isec)->GetNrows(); irow++) { - for (UInt_t ipad = 0; ipad < GetCalROC(isec)->GetNPads(irow); ipad++) { - // fill fitterG - tpcROCinstance->GetPositionLocal(isec, irow, ipad, localXY); // calculate position localXY by sector, pad and row number - lx = localXY[0]; - ly = localXY[1]; - xx[0] = 1; - xx[1] = lx; - xx[2] = ly; - xx[3] = lx*lx; - xx[4] = ly*ly; - xx[5] = lx*ly; - if (!PadOutliers || PadOutliers->GetCalROC(isec)->GetValue(irow, ipad) != 1) { - // if given pad is no outlier, add it to TLinearFitter, decide to which of both -// sector 0 - 17: IROC, A -// sector 18 - 35: IROC, C -// sector 36 - 53: OROC, A -// sector 54 - 71: CROC, C - if (isec <= 17 || (isec >= 36 && isec <= 53)) { // Side A - npointsA++; - fitterGA->AddPoint(xx, GetCalROC(isec)->GetValue(irow, ipad), 1); - } - else { // side C - npointsC++; - fitterGC->AddPoint(xx, GetCalROC(isec)->GetValue(irow, ipad), 1); - } - } - } + //create cal pad + AliTPCCalPad *pad=new AliTPCCalPad("fitResultPad",Form("Fit result: %s",fitFormula)); + //fill cal pad with fit results if requested + for (UInt_t isec = 0; isecGetCalROC(isec); + for (UInt_t irow = 0; irow < roc->GetNrows(); irow++) { + for (UInt_t ipad = 0; ipad < roc->GetNPads(irow); ipad++) { + const TVectorD *fitPar=0; + TVectorD fitResArray; + if (isec/18%2==0){ + fitPar=&fitParamSideA; + }else{ + fitPar=&fitParamSideC; + } + EvalFormulaArray(*arrFitFormulas,fitResArray, isec, irow, ipad); + for (Int_t idim=0;idimSetValue(irow,ipad,fitResArray.Sum()); } } } - else { - // linear fit - fitParamSideA.ResizeTo(3); - fitParamSideC.ResizeTo(3); - covMatrixSideA.ResizeTo(3,3); - covMatrixSideC.ResizeTo(3,3); - - for (UInt_t isec = 0; isec<72; isec++){ - for (UInt_t irow = 0; irow < GetCalROC(isec)->GetNrows(); irow++) { - for (UInt_t ipad = 0; ipad < GetCalROC(isec)->GetNPads(irow); ipad++) { - // fill fitterG - tpcROCinstance->GetPositionLocal(isec, irow, ipad, localXY); // calculate position localXY by sector, pad and row number - lx = localXY[0]; - ly = localXY[1]; - xx[0] = 1; - xx[1] = lx; - xx[2] = ly; - if (!PadOutliers || PadOutliers->GetCalROC(isec)->GetValue(irow, ipad) != 1) { - // if given pad is no outlier, add it to TLinearFitter, decide to which of both -// sector 0 - 17: IROC, A -// sector 18 - 35: IROC, C -// sector 36 - 53: OROC, A -// sector 54 - 71: CROC, C - if (isec <= 17 || (isec >= 36 && isec <= 53)) { - // Side A - npointsA++; - fitterGA->AddPoint(xx, GetCalROC(isec)->GetValue(irow, ipad), 1); - } - else { - // side C - npointsC++; - fitterGC->AddPoint(xx, GetCalROC(isec)->GetValue(irow, ipad), 1); - } - } - } - } - } - } - - fitterGA->Eval(); - fitterGC->Eval(); - fitterGA->GetParameters(fitParamSideA); - fitterGC->GetParameters(fitParamSideC); - fitterGA->GetCovarianceMatrix(covMatrixSideA); - fitterGC->GetCovarianceMatrix(covMatrixSideC); - if (fitType == 1){ - chi2SideA = fitterGA->GetChisquare()/(npointsA-6.); - chi2SideC = fitterGC->GetChisquare()/(npointsC-6.); - } - else { - chi2SideA = fitterGA->GetChisquare()/(npointsA-3.); - chi2SideC = fitterGC->GetChisquare()/(npointsC-3.); - } - if (robust && chi2SideA > chi2Threshold) { - // std::cout << "robust fitter called... " << std::endl; - fitterGA->EvalRobust(robustFraction); - fitterGA->GetParameters(fitParamSideA); + delete arrFitFormulas; + return pad; +} + + + +TCanvas * AliTPCCalPad::MakeReportPadSector(TTree *chain, const char* varName, const char*varTitle, const char *axisTitle, Float_t min, Float_t max, const char *cutUser){ + // + // Make a report - cal pads per sector + // mean valeus per sector and local X + // + TH1* his=0; + TLegend *legend = 0; + TCanvas *canvas = new TCanvas(Form("Sector: %s",varTitle),Form("Sector: %s",varTitle),1500,1100); + + canvas->Divide(2); + chain->SetAlias("lX","lx.fElements"); + // + canvas->cd(1); + TString strDraw=varName; + strDraw+=":lX"; + legend = new TLegend(0.5,0.50,0.9,0.9, Form("%s TPC A side", varTitle)); + for (Int_t isec=-1; isec<18; isec+=1){ + TCut cutSec=Form("sector%%36==%d",isec); + cutSec+=cutUser; + if (isec==-1) cutSec="sector%36<18"; + chain->SetMarkerColor(1+(isec+2)%5); + chain->SetLineColor(1+(isec+2)%5); + chain->SetMarkerStyle(25+(isec+2)%4); + // + chain->Draw(strDraw.Data(),cutSec,"profgoff"); + his=(TH1*)chain->GetHistogram()->Clone(); + delete chain->GetHistogram(); + his->SetMaximum(max); + his->SetMinimum(min); + his->GetXaxis()->SetTitle("R (cm)"); + his->GetYaxis()->SetTitle(axisTitle); + his->SetTitle(Form("%s- sector %d",varTitle, isec)); + his->SetName(Form("%s- sector %d",varTitle, isec)); + if (isec==-1) his->SetTitle(Form("%s A side",varTitle)); + if (isec==-1) his->Draw(); + his->Draw("same"); + legend->AddEntry(his); } - if (robust && chi2SideC > chi2Threshold) { - // std::cout << "robust fitter called... " << std::endl; - fitterGC->EvalRobust(robustFraction); - fitterGC->GetParameters(fitParamSideC); + legend->Draw(); + canvas->cd(2); + // + legend = new TLegend(0.5,0.50,0.9,0.9, Form("%s TPC C side", varTitle)); + for (Int_t isec=-1; isec<18; isec+=1){ + TCut cutSec=Form("(sector+18)%%36==%d",isec); + cutSec+=cutUser; + if (isec==-1) cutSec="sector%36>18"; + chain->SetMarkerColor(1+(isec+2)%5); + chain->SetLineColor(1+(isec+2)%5); + chain->SetMarkerStyle(25+isec%4); + // + chain->Draw(strDraw.Data(),cutSec,"profgoff"); + his=(TH1*)chain->GetHistogram()->Clone(); + delete chain->GetHistogram(); + his->SetMaximum(max); + his->SetMinimum(min); + his->GetXaxis()->SetTitle("R (cm)"); + his->GetYaxis()->SetTitle(axisTitle); + his->SetTitle(Form("%s- sector %d",varTitle,isec)); + his->SetName(Form("%s- sector %d",varTitle,isec)); + if (isec==-1) his->SetTitle(Form("%s C side",varTitle)); + if (isec==-1) his->Draw(); + his->Draw("same"); + legend->AddEntry(his); } - delete fitterGA; - delete fitterGC; + legend->Draw(); + // + // + return canvas; } -*/ + +TCanvas * AliTPCCalPad::MakeReportPadSector2D(TTree *chain, const char* varName, const char*varTitle, const char *axisTitle, Float_t min, Float_t max, const char *cutUser){ + // + // Make a report - cal pads per sector + // 2D view + // Input tree should be created using AliPreprocesorOnline before + // + TH1* his=0; + TCanvas *canvas = new TCanvas(Form("%s2D",varTitle),Form("%s2D",varTitle),1500,1100); + canvas->Divide(2); + // + TString strDraw=varName; + strDraw+=":gy.fElements:gx.fElements>>his(250,-250,250,250,-250,250)"; + // + TVirtualPad * pad=0; + pad=canvas->cd(1); + pad->SetMargin(0.15,0.15,0.15,0.15); + TCut cut=cutUser; + chain->Draw(strDraw.Data(),"sector%36<18"+cut,"profgoffcolz2"); + his=(TH1*)chain->GetHistogram()->Clone(); + delete chain->GetHistogram(); + his->SetMaximum(max); + his->SetMinimum(min); + his->GetXaxis()->SetTitle("x (cm)"); + his->GetYaxis()->SetTitle("y (cm)"); + his->GetZaxis()->SetTitle(axisTitle); + his->SetTitle(Form("%s A side",varTitle)); + his->SetName(Form("%s A side",varTitle)); + his->Draw("colz2"); + // + pad=canvas->cd(2); + pad->SetMargin(0.15,0.15,0.15,0.15); + + chain->Draw(strDraw.Data(),"sector%36>=18"+cut,"profgoffcolz2"); + his=(TH1*)chain->GetHistogram()->Clone(); + delete chain->GetHistogram(); + his->SetMaximum(max); + his->SetMinimum(min); + his->GetXaxis()->SetTitle("x (cm)"); + his->GetYaxis()->SetTitle("y (cm)"); + his->GetZaxis()->SetTitle(axisTitle); + his->SetTitle(Form("%s C side",varTitle)); + his->SetName(Form("%s C side",varTitle)); + his->Draw("colz2"); + // + // + return canvas; +} + +void AliTPCCalPad::Draw(Option_t* option){ + // + // Draw function - standard 2D view + // + TH1* his=0; + TCanvas *canvas = new TCanvas(Form("%s2D",GetTitle()),Form("%s2D",GetTitle()),900,900); + canvas->Divide(2,2); + // + // + TVirtualPad * pad=0; + pad=canvas->cd(1); + pad->SetMargin(0.15,0.15,0.15,0.15); + his=MakeHisto2D(0); + his->GetXaxis()->SetTitle("x (cm)"); + his->GetYaxis()->SetTitle("y (cm)"); + his->GetZaxis()->SetTitle(GetTitle()); + his->SetTitle(Form("%s A side",GetTitle())); + his->SetName(Form("%s A side",GetTitle())); + his->Draw(option); + // + pad=canvas->cd(2); + pad->SetMargin(0.15,0.15,0.15,0.15); + his=MakeHisto2D(1); + his->GetXaxis()->SetTitle("x (cm)"); + his->GetYaxis()->SetTitle("y (cm)"); + his->GetZaxis()->SetTitle(GetTitle()); + his->SetTitle(Form("%s C side",GetTitle())); + his->SetName(Form("%s C side",GetTitle())); + his->Draw(option); + // + pad=canvas->cd(3); + pad->SetMargin(0.15,0.15,0.15,0.15); + his=MakeHisto1D(-8,8,0,1); + his->GetXaxis()->SetTitle(GetTitle()); + his->SetTitle(Form("%s A side",GetTitle())); + his->SetName(Form("%s A side",GetTitle())); + his->Draw("err"); + // + pad=canvas->cd(4); + pad->SetMargin(0.15,0.15,0.15,0.15); + his=MakeHisto1D(-8,8,0,-1); + his->GetXaxis()->SetTitle(GetTitle()); + his->SetTitle(Form("%s C side",GetTitle())); + his->SetName(Form("%s C side",GetTitle())); + his->Draw("err"); + + +} + + +AliTPCCalPad * AliTPCCalPad::MakeCalPadFromHistoRPHI(TH2 * hisA, TH2* hisC){ + // + // Make cal pad from r-phi histograms + // + AliTPCROC *proc= AliTPCROC::Instance(); + AliTPCCalPad *calPad = new AliTPCCalPad("his","his"); + Float_t globalPos[3]; + for (Int_t isec=0; isec<72; isec++){ + AliTPCCalROC* calRoc = calPad->GetCalROC(isec); + TH2 * his = ((isec%36<18) ? hisA:hisC); + for (UInt_t irow=0; irowGetNrows(); irow+=1){ + Int_t jrow=irow; + if (isec>=36) jrow+=63; + for (UInt_t ipad=0;ipadGetNPads(isec,irow);ipad+=1){ + proc->GetPositionGlobal(isec,irow,ipad, globalPos); + Double_t phi=TMath::ATan2(globalPos[1],globalPos[0]); + //if (phi<0) phi+=TMath::Pi()*2; + Int_t bin=his->FindBin(phi,jrow); + Float_t value= his->GetBinContent(bin); + calRoc->SetValue(irow,ipad,value); + } + } + } + return calPad; +}