// implementation of class PesCorrections //see the header file for more information // // 10 Jan 2005. Brian Mohr. Fix bug in setAddress bounds. // Remove PESLASER DB access. // 19 Jan 2005. Brian Mohr. Update how we access dead strip database. // We now use an "unkeyed" access by default. // #include "CalorObjects/PesCorrections.hh" #include "CalibDB/DBint.hh" #include "ErrorLogger_i/gERRLOG.hh" #include #include using std::ifstream; using std::cout; using std::endl; using std::string; bool PesCorrections::sm_useText = false; PesCorrections::PesCorrections(RunListKey *key) : _runListKey(key) { for(int i=0; i<6400; i++) { theConstants[i].theStatus=0; // BNM 1/10/05: Removed access to PESLASER DB. Initialize constants in case // they are used theConstants[i].theLaserMean = 1.0; theConstants[i].theLaserRMS = 1.0; theConstants[i].thePedestal = 0.0; } } bool PesCorrections::setAddress(const int address) { // get the info from the database and stick it in the appropriate variables. theAddress = address; //if (theAddress <= 6400 && theAddress >= 0) { if (theAddress < 6400 && theAddress >= 0) { return true;//have 6400 strips... } else { return false; } } float PesCorrections::attenuation(float position, float energy) { // calculates the attenuation of the light due to travel in the fiber. // the intensity of light in a fiber is given roughly by // I = I_0 * exp(-x/lambda) // where I_0 is the original intensity, x is the position of the // injection of the light and lambda is the attenuation length of the // fiber. For this fiber, the attenuation length is 3.4 meters. However, // this will likely change during the run as the fiber is radiation // damaged. We have I and want to get I_0. float returnValue = 0.; returnValue = energy * exp(position / theConstants[theAddress].theAttenuation[0]); return returnValue; } float PesCorrections::linearity(float counts) { // uses the formula reference = (measured -a ) / (b - c * (measured -a)) // to convert all tubes to the gain profile of a standard reference tube. float returnValue = 0.; returnValue = (counts - theConstants[theAddress].theLinearity[0]) / (theConstants[theAddress].theLinearity[1] - theConstants[theAddress].theLinearity[2]*(counts - theConstants[theAddress].theLinearity[0])); return returnValue; } float PesCorrections::laser(float counts) {//normalize to a standard tube //based on laser calibrations return (counts * theConstants[theAddress].theLaserMean / theConstants[theAddress].theLaserNorm); } float PesCorrections::source(float counts) {//normalize to a standard pixel //based on source calibrations return (counts * theConstants[theAddress].theSourceMean / theConstants[theAddress].theSourceNorm); } float PesCorrections::gain(float counts) {//normalize to the highest pixel in //this tube. //based on relative gain corrections as measured by the UCLA test stand if (theConstants[theAddress].theGain != 0) { return (counts / theConstants[theAddress].theGain * 100.); } else { return 1.; } } float PesCorrections::pedestal(float counts) {// subtract pedestal // bht 22 January 2002 // the electronics are set so there is a 12 count pedestal. Anything under 12 // should return zero. if (counts > 12) { return (counts - 12); } else { return 0; } } int PesCorrections::status() { int value = theConstants[theAddress].theStatus; return value; } bool PesCorrections::getConstants(const int runNumber, const int version, const std::string status) { // get the constants from the database and store them in an array of PesConstants. bool returnValue = true; // formulate a key as a function of this run number, version, and status. // RunListKey *key; // if (version !=0) { //use a specific version of the DB // key = new RunListKey(runNumber, version); // key->setDataStatus(status); // } // Get strip status from PESDeadChannels. // Right now the channelID is different from whats used in PlugStripMaker, // so I simply change it here. // Also the only strips in the DB right now are the dead ones with deadCode() // equal to 0. Since we want 0 = normal, 1 = dead, and 2 = hot, I hard code // all dead channels to 1 for now. // BNM 2/14/05: change DB to contain all status/quality info. It appears that // the dead strips status bits were set to zero from the old code. // This seems to be an odd "feature," but it's fortunate for us. // Since only dead strips were placed in DB, we can preserve backwards // compatability by making all status bits > 0 for new format. // Again, only channels with a non-zero flag will be added to DB. // As per request of database people, we should use the "unkeyed" get by default. // Adjustments made below. BNM 1/19/05 // int usedRun; // if (runNumber < 146100) { usedRun = 139200; } // else { usedRun =146100; } // if (DeadChannelsMgr.isValid() && DeadChannelsMgr.get(RunListKey(usedRun),DeadChannelData)==Result::success) { DeadChannelsMgr = PESDeadChannels_mgr("PESDeadChannels"); if( DeadChannelsMgr.isValid() ) { Result rcDeadChan = DeadChannelsMgr.get(DeadChannelData); if( rcDeadChan == Result::success && DeadChannelData->size() != 0 ) { PESDeadChannelsContainer::iterator it; for(it=DeadChannelData->begin(); it!=DeadChannelData->end(); ++it) { int plug = ( it->channelID() >> 12 ); int octant = ( (it->channelID() >> 9) & 7 ); int layer = ( (it->channelID() >> 8) & 1 ); int strip = ( it->channelID() & 255 ); int address = (plug | (octant<<1) | (layer<<4) | (strip<<5)); if(it->deadCode() == 0) { theConstants[address].theStatus = 1; } else { theConstants[address].theStatus = it->deadCode(); } } // end loop over DB contents } else { ERRLOG(ELwarning,"[PesCalib]") <<"ERROR: no DeadChennelData in PESDeadChannels"<size() != 0)) {// get calibrations from database PESCalibContainer::iterator iter; for(iter=CalibData->begin(); iter!=CalibData->end(); ++iter) { int address = iter->address(); theConstants[address].theLinearity[0] = iter->linearity1(); theConstants[address].theLinearity[1] = iter->linearity2(); theConstants[address].theLinearity[2] = iter->linearity3(); theConstants[address].theSourceMean = iter->sourceMean(); theConstants[address].theSourceRMS = iter->sourceRMS(); theConstants[address].theAttenuation[0] = iter->attenuation1(); theConstants[address].theGain = iter->gain(); theConstants[address].theLaserNorm = iter->laserNorm(); theConstants[address].theSourceNorm = iter->sourceNorm(); } returnValue = true; } else {//the database returned no entries! ERRLOG(ELabort,"[PesCalib]") << "ERROR: failed to retrieve database entries for PesCalibrations" << endmsg; _FillFakeConstants(CALIB); returnValue = false; } } else {//couldn't get to database; set constants so no corrections are made ERRLOG(ELabort,"[PesCalib]") << "ERROR: failed to connect to database for PesCalibrations" << endmsg; _FillFakeConstants(CALIB); returnValue = false; } //--- BNM 1/10/05: Remove access to DB for unused constants ---// // LaserMgr = PESLaser_mgr("PESLaser"); // if (LaserMgr.isValid()) { // Result rcLaser = LaserMgr.get(LaserData); // at some time I will need to put a switch in there so one can select // which calibration DB one is using. this code now supposes that one // is using a valid set-- shouldn't be a problem in the future if all data // is marked with a valid used set. bht 29 may 2001 // Result rcLaser = LaserMgr.get(*key,LaserData); // if ((rcLaser == Result::success) && (LaserData->size() !=0)) { // PESLaserContainer::iterator iter; // for (iter = LaserData->begin(); iter!=LaserData->end(); ++iter) { // int address = iter->address(); // theConstants[address].theLaserMean = iter->laserMean(); // theConstants[address].theLaserRMS = iter->laserRMS(); // theConstants[address].thePedestal = iter->pedestal(); //// std::cout<>address>>highVoltage>>gain) { theConstants[address].theGain = gain; theConstants[address].theHighVoltage = highVoltage; } corFile.close(); inFile.open("/cdf/home/tannenba/scripts/plugCalib.txt"); if (inFile.fail()) { std::cout<<"Can't open input file."<>address >>gain >>sourceMean >>sourceRMS >>sourceNorm >>laserMean >>laserRMS >>laserNorm >>linearity1 >>linearity2 >>linearity3 >>pedestal >>attenuation1 >>attenuation2 >>attenuation3 >>highVoltage) { pedestal = 0; if (theConstants[address].theGain != -1) { gain = theConstants[address].theGain; highVoltage = theConstants[address].theHighVoltage; attenuation1 = 3.37; } contC.push_back(PESCalib (address, gain, sourceMean, sourceRMS ,sourceNorm, laserNorm, linearity1, linearity2 ,linearity3, attenuation1, attenuation2, attenuation3)); contL.push_back(PESLaser (address, laserMean, laserRMS, pedestal , highVoltage)); } inFile.close(); qk.setTable("PESLaser"); qk.setID(PrimType::undefined); std::cout<<"preparing to write PESLaser"< with channelcount of " << contL.size() << endl << " and Run entry of " << qk << endl<< endl; contL.setKey(qk); std::cout<<"preparing to write PESLASER"< with channelcount of " << contC.size() << endl << " and Run entry of " << qk << endl<< endl; contC.setKey(qk); if (iomC.put(contC) == Result::success) { ERRLOG(ELinfo,"[PesCalib]") << "Information: Data written successfully for PesCalib" << endmsg; } else { ERRLOG(ELerror,"[PesCalib]") << "ERROR: writeDB failed for PesCalib" << endmsg; return false; } return true; } void PesCorrections::newConstants() { // use this routine for testing new constants; doesn't save anything to the DB std::ifstream inFile; long address; float gain; int hv; inFile.open("/cdf/home/tannenba/new_offline_corrections.txt"); if (inFile.fail()) { std::cout<<"Can't open input file new_offline_corrections.txt"<>address>>hv>>gain) { if (gain > 1.) {gain = 1.;} theConstants[address].theGain = gain; theConstants[address].theHighVoltage = hv; } inFile.close(); } // --- Allow quality flags to be read in from a file for testing --- // void PesCorrections::FillFromText(const bool value) { sm_useText = value; } // deadStrips.txt should have each dead strip on a line with: // plug octant layer strip void PesCorrections::fillDeadText() { int plg, lyr, phi, stp; ifstream ifs; ifs.open("./deadStrips.txt"); if( ifs.fail() ) { std::cout<<"ERROR: could not open file deadStrips.txt\n"; return; } while (ifs >> plg >> phi >> lyr >> stp) dead[plg][lyr][stp] |= (1 << phi); ifs.close(); } // swapStrips.txt should have each swap strip on a line with: // plug octant layer strip void PesCorrections::fillSwapText() { int plg, lyr, phi, stp; ifstream ifs; ifs.open("./swapStrips.txt"); if( ifs.fail() ) { std::cout<<"ERROR: could not open file swapStrips.txt\n"; return; } while (ifs >> plg >> phi >> lyr >> stp) swap[plg][lyr][stp] |= (1 << phi); ifs.close(); } // lowCStrips.txt should have each strip on a line with: // plug octant layer strip void PesCorrections::fillLowCountText() { int plg, lyr, phi, stp; ifstream ifs; ifs.open("./lowCStrips.txt"); if( ifs.fail() ) { std::cout<<"ERROR: could not open file lowCStrips.txt\n"; return; } while (ifs >> plg >> phi >> lyr >> stp) lowC[plg][lyr][stp] |= (1 << phi); ifs.close(); } void PesCorrections::SetStatusText() { int status; int address; for(int iplg=0;iplg<2;++iplg) for(int ioct=0;ioct<8;++ioct) for(int ilyr=0;ilyr<2;++ilyr) for(int istp=0;istp<200;++istp) { address = (iplg | (ioct<<1) | (ilyr<<4) | (istp<<5)); status = 0; status = (dead[iplg][ilyr][istp] >> ioct ) & 0x1; status |= (swap[iplg][ilyr][istp] >> (ioct-1)) & 0x2; status |= (lowC[iplg][ilyr][istp] >> (ioct-2)) & 0x4; theConstants[address].theStatus = status; } } // SetStatusText