#ifndef ANALOGDETECTOR_H #define ANALOGDETECTOR_H //#include #include #include "slsDetectorData.h" #include "pedestalSubtraction.h" #include "commonModeSubtractionNew.h" #include "ghostSummation.h" #include "tiffIO.h" #include "slsInterpolation.h" #ifdef ROOTSPECTRUM #include #include #include #include #include #include #include #include #endif using namespace std; #ifndef FRAMEMODE_DEF #define FRAMEMODE_DEF /** enum to define the flags of the data set, which are needed to seect the type of processing it should undergo: frame, pedestal, flat */ enum frameMode { eFrame, ePedestal, eFlat }; /** enum to define the detector mode */ enum detectorMode { eAnalog, ePhotonCounting, eInterpolating }; #endif template class analogDetector { /** @short class to perform pedestal subtraction etc. for an analog detector */ public: /** Constructor (no error checking if datasize and offsets are compatible!) \param d detector data structure to be used - if null it is assumed that the data are in ordered ip=iy*nx+ix \param sign is the sign of the data \param nped number of samples for pedestal averaging \param cm common mode subtraction algorithm, if any. Defaults to NULL i.e. none \param nnx detector size in x - must be specified if no data structure is defined, otherwise defaults to the size of the data structure. \param nny detector size in y - must be specified if no data structure is defined, otherwise defaults to the size of the data structure. \param gm pointer to tha gain map matrix */ analogDetector(slsDetectorData *d, int sign=1, commonModeSubtraction *cm=NULL, int nped=1000, int nnx=-1, int nny=-1, double *gm=NULL, ghostSummation *gs=NULL) : det(d), nx(nnx), ny(nny), stat(NULL), cmSub(cm), dataSign(sign), iframe(-1), gmap(gm), ghSum(gs), id(0) { if (det) det->getDetectorSize(nx,ny); stat=new pedestalSubtraction*[ny]; /* pedMean=new double*[ny]; */ /* pedVariance=new double*[ny]; */ for (int i=0; idet; nx=orig->nx; ny=orig->ny; dataSign=orig->dataSign; iframe=orig->iframe; gmap=orig->gmap; // cmSub=orig->cmSub; id=orig->id; xmin=orig->xmin; xmax=orig->xmax; ymin=orig->ymin; ymax=orig->ymax; thr=orig->thr; // nSigma=orig->nSigma; fMode=orig->fMode; myFile=orig->myFile; stat=new pedestalSubtraction*[ny]; /* pedMean=new double*[ny]; */ /* pedVariance=new double*[ny]; */ for (int i=0; iSetNPedestals(); //cout << nped << " " << orig->getPedestal(ix,iy) << orig->getPedestalRMS(ix,iy) << endl; for (iy=0; iygetPedestal(ix,iy),orig->getPedestalRMS(ix,iy),orig->GetNPedestals(ix,iy)); /* if (ix==50 && iy==50) */ /* cout << "clone ped " << " " << ix << " " << iy << " " << getPedestal(ix,iy) << " " << getPedestalRMS(ix,iy)<< " " << GetNPedestals(ix,iy) << endl; */ } } image=new int[nx*ny]; #ifdef ROOTSPECTRUM hs=(TH2F*)(orig->hs)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); #ifdef ROOTCLUST hs3=(TH2F*)(orig->hs3)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); hs5=(TH2F*)(orig->hs5)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); hs7=(TH2F*)(orig->hs7)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); hs9=(TH2F*)(orig->hs9)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); #endif #endif if (orig->cmSub) { cmSub=(orig->cmSub)->Clone(); cout <<"cloning cm" << endl; } else cmSub=NULL; if (orig->ghSum) { ghSum=(orig->ghSum)->Clone(); cout <<"cloning gs" << endl; } else ghSum=NULL; } /** clone. Must be virtual! \returns a clone of the original analog detector */ virtual analogDetector *Clone() { return new analogDetector(this); } /** Gives an id to the structure. For debugging purposes in case of multithreading. \param i is to be set \returns current id */ int setId(int i){id=i; return id;}; /** Returns id of the structure. For debugging purposes in case of multithreading. \returns current id */ int getId() {return id; }; /** Returns data size of the detector data structure \returns data size of the detector data structurein bytes */ int getDataSize(){return det->getDataSize();}; /** Returns data size of the detector image matrix \param nnx reference to image size in x \param nny reference to image size in y \param nns reference to number of subpixels for interpolating detector, will always be 1 in this case \returns number of pixels of the detector image */ virtual int getImageSize(int &nnx, int &nny, int &nnsx, int &nnsy){nnx=nx; nny=ny; nnsx=1; nnsy=1; return nx*ny;}; /** Returns data size of the detector image matrix \param nnx reference to pixel size in x \param nny reference to pixel size in y \returns number of pixels of the detector image */ virtual int getDetectorSize(int &nnx, int &nny){nnx=nx; nny=ny; return nx*ny;}; /** set gain map \param gm pointer to gain map matrix to be set - NULL unsets \returns pointer to current gain map */ double *setGainMap(double *gm) {gmap=gm; return gmap;}; /** return gain map \returns pointer to current gain map */ double *getGainMap() {return gmap;}; /** reads a 32 bit tiff file of the size of the detector and sets its values as gain map for the detector. If file does not exist returns NULL, but does not change gainmap compared to previous settings. \param imgname complete name of the file containing the gain map data \returns pointer to current gain map is file reading succeeded, NULL is file reading didn't work. */ double *readGainMap(const char * imgname) { uint32 nnx, nny; float *gm=ReadFromTiff( imgname, nny, nnx); if (gm) { if (gmap) delete [] gmap; gmap=new double[nnx*nny]; for (iy=0; iyClear(); #ifdef ROOTSPECTRUM hs->Reset(); #ifdef ROOTCLUST hs3->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); hs5->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); hs7->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); hs9->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); #endif #endif }; /** resets the commonModeSubtraction and increases the frame index */ virtual void newFrame(){iframe++; if (cmSub) cmSub->newFrame(); det->newFrame();}; /** resets the commonModeSubtraction and increases the frame index */ virtual void newFrame(char *data){ iframe++; if (cmSub) cmSub->newFrame(); det->newFrame(); // det->getData(data); calcGhost(data); // cout << getId() << " Calc ghost " << getGhost(15,15) << endl; }; /** sets the commonModeSubtraction algorithm to be used \param cm commonModeSubtraction algorithm to be used (NULL unsets) \returns pointer to the actual common mode subtraction algorithm */ commonModeSubtraction *setCommonModeSubtraction(commonModeSubtraction *cm) {cmSub=cm; return cmSub;}; /** gets the commonModeSubtraction algorithm to be used \returns pointer to the actual common mode subtraction algorithm */ commonModeSubtraction *getCommonModeSubtraction() {return cmSub;}; ghostSummation *getGhostSummation(){return ghSum;}; ghostSummation *setGhostSummation(ghostSummation *gs){ghSum=gs; return ghSum;}; /** sets the sign of the data \param sign 1 means positive values for photons, -1 negative, 0 gets \returns current sign for the data */ int setDataSign(int sign=0) {if (sign==1 || sign==-1) dataSign=sign; return dataSign;}; /** adds value to pedestal (and common mode) for the given pixel \param val value to be added \param ix pixel x coordinate \param iy pixel y coordinate \param cm 1 adds the value to common mod, 0 skips it. Defaults to 0. - not properly implemented */ virtual void addToPedestal(double val, int ix, int iy, int cm=0){ if (ix>=0 && ix=0 && iy0) { val-= getCommonMode(ix, iy); } // cout << val << " " ; val+=getGhost(ix,iy); // cout << val ; // cout << endl; stat[iy][ix].addToPedestal(val); /* if (cmSub && cm>0) { */ /* if (det) if (det->isGood(ix, iy)==0) return; */ /* cmSub->addToCommonMode(val, ix, iy); */ /* }; */ }; } double getCommonMode(int ix, int iy) { if (cmSub) { return cmSub->getCommonMode(ix, iy); } return 0; } virtual void addToCommonMode(char *data){ // cout << "+"<< getId() << endl; if (cmSub) { //cout << "*" << endl; for (iy=ymin; iy0) // if (det->isGood(ix,iy)) { addToCommonMode(data, ix, iy); // cout << ":"; // } } } //cout << "cm " << getCommonMode(0,0) << " " << getCommonMode(1,0) << endl; } } virtual void addToCommonMode(char *data, int ix, int iy=0){ // cout <<"."; if (cmSub) { //cout <<":"; if (det) if (det->isGood(ix, iy)==0) return; if (getNumpedestals(ix,iy)>0){ double val; if (det) { /* if (det->getChannel(data, ix, iy)>=0x3fff) */ /* cout << ix << " " << iy << " " << det->getChannel(data, ix, iy) <getValue(data, ix, iy)-getPedestal(ix,iy,0)); } else val= (((double*)data)[iy*nx+ix]-getPedestal(ix,iy)); val+=getGhost(ix,iy); cmSub->addToCommonMode(val, ix, iy); //cout << ":"; } } } /** gets pedestal (and common mode) \param ix pixel x coordinate \param iy pixel y coordinate \param cm 0 (default) without common mode subtraction, 1 with common mode subtraction (if defined) \returns pedestal value */ virtual double getPedestal (int ix, int iy, int cm=0){ if (ix>=0 && ix=0 && iy0) { return stat[iy][ix].getPedestal()+getCommonMode(ix,iy); //return pedMean[iy][ix]+getCommonMode(ix,iy); } //return pedMean[iy][ix]; return stat[iy][ix].getPedestal(); } else return -1; }; /** gets pedestal rms (i.e. noise) \param ix pixel x coordinate \param iy pixel y coordinate \returns pedestal rms */ virtual double getPedestalRMS(int ix, int iy){ double g=1; if (ix>=0 && ix=0 && iy=0 && ix=0 && iy=0 && ix=0 && iy=0 && ix=0 && iycalcGhost(data, ix, iy); } }; virtual void calcGhost(char *data){if (ghSum) { ghSum->calcGhost(data); // cout << getId() << " @ " << ghSum->getXTalk() << " " << ghSum->getGhost(15,15) << endl; } }; virtual double getGhost(int ix, int iy) {if (ghSum) return ghSum->getGhost(ix, iy); return 0;}; /** write 32bit tiff file with detector image data \param imgname file name to be written \returns NULL if file writing didn't succed, otherwise a pointer */ virtual void *writeImage(const char * imgname) { float *gm=NULL; void *ret; #ifdef ROOTSPECTRUM TH2F *hmap=new TH2F("hmap","hmap",nx, -0.5,nx-0.5, ny, -0.5, ny-0.5); #endif gm=new float[nx*ny]; for (iy=0; iySetBinContent(ix+1, iy+1,image[iy*nx+ix]); #endif } } ret=WriteToTiff(gm, imgname, ny, nx); delete [] gm; #ifdef ROOTSPECTRUM char rootfn[10000]; sprintf(rootfn,"%s.root",imgname); TFile *f=new TFile(rootfn,"RECREATE"); hs->Write("hs"); #ifdef ROOTCLUST hs3->Write("hs3"); hs5->Write("hs5"); hs7->Write("hs7"); hs9->Write("hs9"); #endif hmap->Write("hmap"); f->Close(); delete f; delete hmap; #endif return ret; } #ifdef ROOTSPECTRUM TH2F *getSpectrum(){return hs;}; #endif /** write 32bit tiff file containing the pedestals \param imgname file name to be written \returns NULL if file writing didn't succed, otherwise a pointer */ virtual void *writePedestals(const char * imgname) { float *gm=NULL; void *ret; gm=new float[nx*ny]; #ifdef ROOTSPECTRUM TH2F *hmap=new TH2F("hmap","hmap",nx, -0.5,nx-0.5, ny, -0.5, ny-0.5); #endif for (iy=0; iygetCommonMode(); */ /* else */ gm[iy*nx+ix]=stat[iy][ix].getPedestal(); #ifdef ROOTSPECTRUM hmap->SetBinContent(ix+1, iy+1,gm[iy*nx+ix]); #endif } } ret=WriteToTiff(gm, imgname, ny, nx); delete [] gm; #ifdef ROOTSPECTRUM char rootfn[10000]; sprintf(rootfn,"%s.root",imgname); TFile *f=new TFile(rootfn,"RECREATE"); hs->Write("hs"); #ifdef ROOTCLUST hs3->Write("hs3"); hs5->Write("hs5"); hs7->Write("hs7"); hs9->Write("hs9"); #endif hmap->Write("hmap"); f->Close(); delete f; delete hmap; #endif return ret; } /** read 32bit tiff file containing the pedestals \param imgname file name to be read \returns 0 if file reading didn't succed, otherwise 1 */ int readPedestals(const char * imgname) { uint32 nnx, nny; float *gm=ReadFromTiff( imgname, nny, nnx); if (nnx>nx) nnx=nx; if (nny>ny) nny=ny; if (gm) { for (iy=0; iynx) nnx=nx; if (nny>ny) nny=ny; if (gm) { for (iy=0; iynx) nnx=nx; if (nny>ny) nny=ny; if (gm) { for (iy=0; iyisGood(ix,iy)) { // addToPedestal(data,ix,iy,1); addToPedestal(data,ix,iy,cm); /* if (ix==50 && iy==50) */ /* cout<< "*ped* " << id << " " << ix << " " << iy << " " << det->getChannel(data,ix,iy) << " " << stat[iy][ix].getPedestal() << " " << stat[iy][ix].getPedestalRMS() <<" " << stat[iy][ix]. GetNPedestals() << endl; */ //if (ix==10 && iy==10) // cout <=0 && xmi<=nx) xmin=xmi; if (xma>=0 && xma<=nx) xmax=xma; if (xmax=0 && ymi<=ny) ymin=ymi; if (yma>=0 && yma<=ny) ymax=yma; if (ymax=0 && ix=0 && iygetValue(data, ix, iy); else val=((double*)data)[iy*nx+ix]; // cout << val << endl; /* if (ix==10 && iy==10) */ /* cout << ix << " " << iy << " " << val ; */ /* if (ix==100 && iy==100) */ /* cout << ix << " " << iy << " " << val; */ addToPedestal(val,ix,iy); // cout << val << endl; /* if (ix==10 && iy==10) */ /* cout <<" " << getPedestal(ix,iy)<< endl; */ /* if (ix==100 && iy==100) */ /* cout << " " << getPedestal(ix,iy)<< endl; */ } return ; }; /** Subtracts pedestal from the data array in the region of interest \param data pointer to the data \param val pointer where the pedestal subtracted data should be added. If NULL, the internal image is used \returns pointer to the pedestal subtracted data */ // virtual int *subtractPedestal(char *data, int *val=NULL) { virtual int *subtractPedestal(char *data, int *val=NULL, int cm=0) { newFrame(data); if (val==NULL) val=image;//new double[nx*ny]; //calcGhost(data); for (iy=ymin; iyisGood(ix,iy)) val[iy*nx+ix]+=subtractPedestal(data, ix, iy,cm); } } return val; }; /** Subtracts pedestal from the data for a selected pixel \param data pointer to the data \param ix pixel x coordinate \param iy pixel y coordinate \returns pedestal subtracted value */ virtual double subtractPedestal(char *data, int ix, int iy=0, int cm=0) { double g=1.; double val =0; if (ix>=0 && ix=0 && iygetChannel(data, ix, iy)>=0x3fff) */ /* cout << ix << " " << iy << " " << det->getChannel(data, ix, iy) <getValue(data, ix, iy)-getPedestal(ix,iy,cm))/g; } else val= (((double*)data)[iy*nx+ix]-getPedestal(ix,iy))/g; //if (val>=0.5*thr) // cout << val << " " << (dataSign*det->getValue(data, ix, iy)-getPedestal(ix,iy,cm)) << " " << g << " "; val+=getGhost(ix,iy)/g; #ifdef ROOTSPECTRUM hs->Fill(val,(iy-ymin)*(xmax-xmin)+(ix-xmin)); #ifdef ROOTCLUST double v3=0,v5=0,v7=0,v9=0; for (int iix=-4; iix<5; i++ix) for (int iiy=-4; iiy<5; i++iy) { if (det) val= (dataSign*det->getValue(data, ix+iix, iy+iiy)-getPedestal(ix+iix,iy+iiy,cm))/g; else val= (((double*)data)[(iy+iiy)*nx+ix+iix]-getPedestal(ix+iix,iy+iiy,cm))/g; if (iix>-4 && iiy>-4 && iix<4 && iiy<4) { if (iix>-3 && iiy>-3 && iix<3 && iiy<3){ if (iix>-2 && iiy>-2 && iix<2 && iiy<2){ v3+=val; } v5+=val; } v7+=val; } v9+=val; } hs3->Fill(v3,(iy-ymin)*(xmax-xmin)+(ix-xmin)); hs5->Fill(v5,(iy-ymin)*(xmax-xmin)+(ix-xmin)); hs7->Fill(v7,(iy-ymin)*(xmax-xmin)+(ix-xmin)); hs9->Fill(v9,(iy-ymin)*(xmax-xmin)+(ix-xmin)); #endif #endif return val; } return val; }; /** sets threshold value for conversion into number of photons \param t threshold to be set \returns threshold value */ double setThreshold(double t){thr=t; return thr;}; /** gets threshold value for conversion into number of photons \returns threshold value */ double getThreshold(){return thr;}; /** converts the data into number of photons for the selected pixel \param data pointer to the data \param ix pixel x coordinate \param iy pixel y coordinate \returns converted number of photons. If no threshold is set, returns gain converted pedestal subtracted data. */ virtual int getNPhotons(char *data, int ix, int iy=0) { int nph=0; double v; if (ix>=0 && ix=0 && iyFill(v,(iy-ymin)*(xmax-xmin)+(ix-xmin)); */ /* #endif */ if (thr>0) { v+=0.5*thr; nph=v/thr; /* if (ix ==10 && iy<20) */ /* cout << det->getValue(data,ix,iy) << " " << stat[iy][ix].getPedestal() << " " << getCommonMode(ix,iy) << " " << getPedestal(ix,iy,0)<< " " << getPedestal(ix,iy,1) << endl; */ // cout << subtractPedestal(data,ix,iy,0) << " " << subtractPedestal(data,ix,iy,1) << " " << nph << endl; if (nph>0) { //cout << " " << nph << endl; return nph; } return 0; } return v; } return 0; }; /** converts the data into number of photons for all pixels \param data pointer to the data \param nph pointer where the photons should added. If NULL,the internal image is used \returns pointer to array containing the number of photons */ int *getNPhotons(char *data, int *nph=NULL) { //double val; if (nph==NULL) nph=image; newFrame(data); //calcGhost(data); addToCommonMode(data); for (iy=ymin; iyisGood(ix,iy)) nph[iy*nx+ix]+=getNPhotons(data, ix, iy); } } return nph; } /** clears the image array */ virtual void clearImage(){ for (iy=0; iyReset(); #ifdef ROOTCLUST if (hs3) hs3->Reset(); if (hs5) hs5->Reset(); if (hs7) hs7->Reset(); if (hs9) hs9->Reset(); #endif //cout << "done " << endl; #endif }; /** sets/gets number of samples for moving average pedestal calculation \param i number of samples to be set (0 or negative gets) \returns actual number of samples */ int SetNPedestals(int i=-1) { int ix=0, iy=0; if (i>0) for (iy=0; iy=0 && ix=0 && iyisGood(ix,iy)) { if (ix>=0 && ix=0 && iy *det; /**< slsDetectorData to be used */ int nx; /**< Size of the detector in x direction */ int ny; /**< Size of the detector in y direction */ pedestalSubtraction **stat; /**< pedestalSubtraction class */ /* double **pedMean; /\**< pedestalSubtraction class *\/ */ /* double **pedVariance; /\**< pedestalSubtraction class *\/ */ commonModeSubtraction *cmSub;/**< commonModeSubtraction class */ int dataSign; /**< sign of the data i.e. 1 if photon is positive, -1 if negative */ int iframe; /**< frame number (not from file but incremented within the dataset every time newFrame is called */ double *gmap; ghostSummation *ghSum;/**< ghostSummation class */ int *image; int id; //int xmin, xmax, ymin, ymax; int xmin; /**< minimum x of the region of interest */ int xmin; /**< minimum x of the region of interest */ int xmax; /**< maximum x of the region of interest */ int ymin;/**< minimum y of the region of interest */ int ymax;/**< maximum y of the region of interest */ double thr; /**< threshold to be used for conversion into number of photons */ // int nSigma; /**< number of sigma to be used for conversion into number of photons if threshold is undefined */ frameMode fMode; /**< current detector frame mode */ detectorMode dMode; /**< current detector frame mode */ FILE *myFile; /**< file pointer to write to */ int ix, iy; #ifdef ROOTSPECTRUM TH2F *hs; #ifdef ROOTCLUST TH2F *hs3; TH2F *hs5; TH2F *hs7; TH2F *hs9; #endif #endif }; #endif