/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ #include #include #include #include #include #include #include #include #include "AliCheb3D.h" #include "AliCheb3DCalc.h" ClassImp(AliCheb3D) //__________________________________________________________________________________________ AliCheb3D::AliCheb3D() : fDimOut(0), fPrec(0), fChebCalc(1), fMaxCoefs(0), fResTmp(0), fGrid(0), fUsrFunName(""), fUsrMacro(0) { for (int i=3;i--;) fBMin[i] = fBMax[i] = fBScale[i] = fBOffset[i] = 0; } //__________________________________________________________________________________________ AliCheb3D::AliCheb3D(const AliCheb3D& src) : TNamed(src), fDimOut(src.fDimOut), fPrec(src.fPrec), fChebCalc(1), fMaxCoefs(src.fMaxCoefs), fResTmp(0), fGrid(0), fUsrFunName(src.fUsrFunName), fUsrMacro(0) { // read coefs from text file for (int i=3;i--;) { fBMin[i] = src.fBMin[i]; fBMax[i] = src.fBMax[i]; fBScale[i] = src.fBScale[i]; fBOffset[i] = src.fBOffset[i]; fNPoints[i] = src.fNPoints[i]; } for (int i=0;i%dD function. Precision: %e\n",GetName(),fDimOut,fPrec); printf("Region of validity: [%+.5e:%+.5e] [%+.5e:%+.5e] [%+.5e:%+.5e]\n",fBMin[0],fBMax[0],fBMin[1],fBMax[1],fBMin[2],fBMax[2]); TString opts = opt; opts.ToLower(); if (opts.Contains("l")) for (int i=0;iPrint();} // } //__________________________________________________________________________________________ void AliCheb3D::PrepareBoundaries(const Float_t *bmin, const Float_t *bmax) { // Set and check boundaries defined by user, prepare coefficients for their conversion to [-1:1] interval // for (int i=3;i--;) { fBMin[i] = bmin[i]; fBMax[i] = bmax[i]; fBScale[i] = bmax[i]-bmin[i]; if (fBScale[i]<=0) { Error("PrepareBoundaries","Boundaries for %d-th dimension are not increasing: %+.4e %+.4e\nStop\n",i,fBMin[i],fBMax[i]); exit(1); } fBOffset[i] = bmin[i] + fBScale[i]/2.0; fBScale[i] = 2./fBScale[i]; } // } //__________________________________________________________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ // Pointer on user function (faster altrnative to TMethodCall) void (*gUsrFunAliCheb3D) (float* ,float* ); void AliCheb3D::EvalUsrFunction() { // call user supplied function if (gUsrFunAliCheb3D) gUsrFunAliCheb3D(fArgsTmp,fResTmp); else fUsrMacro->Execute(); } void AliCheb3D::SetUsrFunction(const char* name) { // load user macro with function definition and compile it gUsrFunAliCheb3D = 0; fUsrFunName = name; gSystem->ExpandPathName(fUsrFunName); if (fUsrMacro) delete fUsrMacro; TString tmpst = fUsrFunName; tmpst += "+"; // prepare filename to compile if (gROOT->LoadMacro(tmpst.Data())) {Error("SetUsrFunction","Failed to load user function from %s\nStop\n",name); exit(1);} fUsrMacro = new TMethodCall(); tmpst = tmpst.Data() + tmpst.Last('/')+1; //Strip away any path preceding the macro file name int dot = tmpst.Last('.'); if (dot>0) tmpst.Resize(dot); fUsrMacro->InitWithPrototype(tmpst.Data(),"Float_t *,Float_t *"); long args[2]; args[0] = (long)fArgsTmp; args[1] = (long)fResTmp; fUsrMacro->SetParamPtrs(args); // } #endif //__________________________________________________________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ void AliCheb3D::SetUsrFunction(void (*ptr)(float*,float*)) { // assign user training function // if (fUsrMacro) delete fUsrMacro; fUsrMacro = 0; fUsrFunName = ""; gUsrFunAliCheb3D = ptr; } #endif //__________________________________________________________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ void AliCheb3D::EvalUsrFunction(const Float_t *x, Float_t *res) { // evaluate user function value // for (int i=3;i--;) fArgsTmp[i] = x[i]; if (gUsrFunAliCheb3D) gUsrFunAliCheb3D(fArgsTmp,fResTmp); else fUsrMacro->Execute(); for (int i=fDimOut;i--;) res[i] = fResTmp[i]; } #endif //__________________________________________________________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ Int_t AliCheb3D::CalcChebCoefs(const Float_t *funval,int np, Float_t *outCoefs, Float_t prec) { // Calculate Chebyshev coeffs using precomputed function values at np roots. // If prec>0, estimate the highest coeff number providing the needed precision // double sm; // do summations in double to minimize the roundoff error for (int ic=0;ic=prec) break; } if (++cfMax==0) cfMax=1; return cfMax; // } #endif //__________________________________________________________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ void AliCheb3D::DefineGrid(Int_t* npoints) { // prepare the grid of Chebyshev roots in each dimension const int kMinPoints = 1; int ntot = 0; fMaxCoefs = 1; for (int id=3;id--;) { fNPoints[id] = npoints[id]; if (fNPoints[id]=fracStep) { frac = fr; printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("%05.2f%% Done",fr*100); fflush(stdout); } // } int nc = CalcChebCoefs(fvals,fNPoints[0], tmpCoef1D, fPrec); for (int id0=fNPoints[0];id0--;) tmpCoef2D[id1 + id0*fNPoints[1]] = tmpCoef1D[id0]; if (ncmax0 && tmpCoefSurf[(id1-1)+id0*fNPoints[1]]==0) id1--; tmpCols[id0] = id1; } // find max significant row for (int id0=nRows;id0--;) {if (tmpCols[id0]>0) break; nRows--;} // find max significant column and fill the permanent storage for the max sigificant column of each row cheb->InitRows(nRows); // create needed arrays; UShort_t *nColsAtRow = cheb->GetNColsAtRow(); UShort_t *colAtRowBg = cheb->GetColAtRowBg(); int nCols = 0; int NElemBound2D = 0; for (int id0=0;id0InitCols(nCols); delete[] tmpCols; // // create the 2D matrix defining the boundary of significance for 3D coeffs.matrix // and count the number of siginifacnt coefficients // cheb->InitElemBound2D(NElemBound2D); UShort_t *coefBound2D0 = cheb->GetCoefBound2D0(); UShort_t *coefBound2D1 = cheb->GetCoefBound2D1(); fMaxCoefs = 0; // redefine number of coeffs for (int id0=0;id0InitCoefs(fMaxCoefs); Float_t *coefs = cheb->GetCoefs(); int count = 0; for (int id0=0;id0ExpandPathName(strf); FILE* stream = fopen(strf,append ? "a":"w"); SaveData(stream); fclose(stream); // } #endif //_______________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ void AliCheb3D::SaveData(FILE* stream) const { // writes coefficients data to existing output stream // fprintf(stream,"\n# These are automatically generated data for the Chebyshev interpolation of 3D->%dD function\n",fDimOut); fprintf(stream,"#\nSTART %s\n",GetName()); fprintf(stream,"# Dimensionality of the output\n%d\n",fDimOut); fprintf(stream,"# Interpolation abs. precision\n%+.8e\n",fPrec); // fprintf(stream,"# Lower boundaries of interpolation region\n"); for (int i=0;i<3;i++) fprintf(stream,"%+.8e\n",fBMin[i]); fprintf(stream,"# Upper boundaries of interpolation region\n"); for (int i=0;i<3;i++) fprintf(stream,"%+.8e\n",fBMax[i]); fprintf(stream,"# Parameterization for each output dimension follows:\n"); // for (int i=0;iSaveData(stream); fprintf(stream,"#\nEND %s\n#\n",GetName()); // } #endif //_______________________________________________ void AliCheb3D::LoadData(const char* inpFile) { // load coefficients data from txt file // TString strf = inpFile; gSystem->ExpandPathName(strf); FILE* stream = fopen(strf.Data(),"r"); LoadData(stream); fclose(stream); // } //_______________________________________________ void AliCheb3D::LoadData(FILE* stream) { // load coefficients data from stream // if (!stream) {Error("LoadData","No stream provided.\nStop"); exit(1);} TString buffs; Clear(); AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("START")) {Error("LoadData","Expected: \"START \", found \"%s\"\nStop\n",buffs.Data());exit(1);} SetName(buffs.Data()+buffs.First(' ')+1); // AliCheb3DCalc::ReadLine(buffs,stream); // N output dimensions fDimOut = buffs.Atoi(); if (fDimOut<1) {Error("LoadData","Expected: '', found \"%s\"\nStop\n",buffs.Data());exit(1);} // SetDimOut(fDimOut); // AliCheb3DCalc::ReadLine(buffs,stream); // Interpolation abs. precision fPrec = buffs.Atof(); if (fPrec<=0) {Error("LoadData","Expected: '', found \"%s\"\nStop\n",buffs.Data());exit(1);} // for (int i=0;i<3;i++) { // Lower boundaries of interpolation region AliCheb3DCalc::ReadLine(buffs,stream); fBMin[i] = buffs.Atof(); } for (int i=0;i<3;i++) { // Upper boundaries of interpolation region AliCheb3DCalc::ReadLine(buffs,stream); fBMax[i] = buffs.Atof(); } PrepareBoundaries(fBMin,fBMax); // // data for each output dimension for (int i=0;iLoadData(stream); // // check end_of_data record AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("END") || !buffs.Contains(GetName())) { Error("LoadData","Expected \"END %s\", found \"%s\".\nStop\n",GetName(),buffs.Data()); exit(1); } // } //_______________________________________________ void AliCheb3D::SetDimOut(const int d) { // init output dimensions fDimOut = d; if (fResTmp) delete fResTmp; fResTmp = new Float_t[fDimOut]; fChebCalc.Delete(); for (int i=0;i2) {printf("Maximum 3 dimensions are supported\n"); return;} fBMin[id] += dif; fBMax[id] += dif; fBOffset[id] += dif; } //_______________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ TH1* AliCheb3D::TestRMS(int idim,int npoints,TH1* histo) { // fills the difference between the original function and parameterization (for idim-th component of the output) // to supplied histogram. Calculations are done in npoints random points. // If the hostgram was not supplied, it will be created. It is up to the user to delete it! if (!fUsrMacro) { printf("No user function is set\n"); return 0; } if (!histo) histo = new TH1D(GetName(),"Control: Function - Parametrization",100,-2*fPrec,2*fPrec); for (int ip=npoints;ip--;) { gRandom->RndmArray(3,(Float_t *)fArgsTmp); for (int i=3;i--;) fArgsTmp[i] = fBMin[i] + fArgsTmp[i]*(fBMax[i]-fBMin[i]); EvalUsrFunction(); Float_t valFun = fResTmp[idim]; Eval(fArgsTmp,fResTmp); Float_t valPar = fResTmp[idim]; histo->Fill(valFun - valPar); } return histo; // } #endif //_______________________________________________ #ifdef _INC_CREATION_ALICHEB3D_ void AliCheb3D::EstimateNPoints(float Prec, int gridBC[3][3],Int_t npd1,Int_t npd2,Int_t npd3) { // Estimate number of points to generate a training data // const int kScp = 9; const float kScl[9] = {0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}; // const float sclDim[2] = {0.001,0.999}; const int compDim[3][2] = { {1,2}, {2,0}, {0,1} }; static float xyz[3]; Int_t npdTst[3] = {npd1,npd2,npd3}; // for (int i=3;i--;)for (int j=3;j--;) gridBC[i][j] = -1; // for (int idim=0;idim<3;idim++) { float dimMN = fBMin[idim] + sclDim[0]*(fBMax[idim]-fBMin[idim]); float dimMX = fBMin[idim] + sclDim[1]*(fBMax[idim]-fBMin[idim]); // int id1 = compDim[idim][0]; // 1st fixed dim int id2 = compDim[idim][1]; // 2nd fixed dim for (int i1=0;i1gridBC[ib][idim]) gridBC[ib][idim] = npt[ib]; } } } } /* void AliCheb3D::EstimateNPoints(float Prec, int gridBC[3][3]) { // Estimate number of points to generate a training data // const float sclA[9] = {0.1, 0.5, 0.9, 0.1, 0.5, 0.9, 0.1, 0.5, 0.9} ; const float sclB[9] = {0.1, 0.1, 0.1, 0.5, 0.5, 0.5, 0.9, 0.9, 0.9} ; const float sclDim[2] = {0.01,0.99}; const int compDim[3][2] = { {1,2}, {2,0}, {0,1} }; static float xyz[3]; // for (int i=3;i--;)for (int j=3;j--;) gridBC[i][j] = -1; // for (int idim=0;idim<3;idim++) { float dimMN = fBMin[idim] + sclDim[0]*(fBMax[idim]-fBMin[idim]); float dimMX = fBMin[idim] + sclDim[1]*(fBMax[idim]-fBMin[idim]); // for (int it=0;it<9;it++) { // test in 9 points int id1 = compDim[idim][0]; // 1st fixed dim int id2 = compDim[idim][1]; // 2nd fixed dim xyz[ id1 ] = fBMin[id1] + sclA[it]*( fBMax[id1]-fBMin[id1] ); xyz[ id2 ] = fBMin[id2] + sclB[it]*( fBMax[id2]-fBMin[id2] ); // int* npt = GetNCNeeded(xyz,idim, dimMN,dimMX, Prec); // npoints for Bx,By,Bz for (int ib=0;ib<3;ib++) if (npt[ib]>gridBC[ib][idim]) gridBC[ib][idim] = npt[ib];//+2; // } } } int* AliCheb3D::GetNCNeeded(float xyz[3],int DimVar, float mn,float mx, float prec) { // estimate needed number of chebyshev coefs for given function description in DimVar dimension // The values for two other dimensions must be set beforehand // static int curNC[3]; static int retNC[3]; const int kMaxPoint = 400; float* gridVal = new float[3*kMaxPoint]; float* coefs = new float[3*kMaxPoint]; // float scale = mx-mn; float offs = mn + scale/2.0; scale = 2./scale; // int curNP; int maxNC=-1; int maxNCPrev=-1; for (int i=0;i<3;i++) retNC[i] = -1; for (int i=0;i<3;i++) fArgsTmp[i] = xyz[i]; // for (curNP=3; curNP3 && (maxNC-maxNCPrev)<1 ) break; maxNCPrev = maxNC; // } delete[] gridVal; delete[] coefs; return retNC; // } */ int* AliCheb3D::GetNCNeeded(float xyz[3],int DimVar, float mn,float mx, float prec, Int_t npCheck) { // estimate needed number of chebyshev coefs for given function description in DimVar dimension // The values for two other dimensions must be set beforehand // static int retNC[3]; static int npChLast = 0; static float *gridVal=0,*coefs=0; if (npCheck<3) npCheck = 3; if (npChLast