Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

BDSwicCalibrator.cxx

Go to the documentation of this file.
00001 #include <algorithm>
00002 
00003 #include "BDSwicCalibrator.h"
00004 #include "BDSwicDevice.h"
00005 
00006 #include <Conventions/Munits.h>
00007 #include <RawData/RawBeamMonHeaderBlock.h>
00008 #include <RawData/RawBeamMonBlock.h>
00009 
00010 #include <MessageService/MsgService.h>
00011 CVSID("$Id: BDSwicCalibrator.cxx,v 1.13 2009/02/28 21:46:11 gmieg Exp $");
00012 
00013 
00014 static const float max_profile_pedestal_rms = 15.0; // ADC
00015 
00016 BDSwicCalibrator* BDSwicCalibrator::fInstance = 0;
00017 
00018 BDSwicCalibrator& BDSwicCalibrator::Get()
00019 {
00020     if (!fInstance) fInstance = new BDSwicCalibrator;
00021     return *fInstance;
00022 }
00023 
00024 BDSwicCalibrator::BDSwicCalibrator()
00025     : fPeds(), fMask()
00026 {
00027 }
00028 
00029 BDSwicCalibrator::~BDSwicCalibrator()
00030 {
00031 }
00032 
00033 void BDSwicCalibrator::Calibrate(const RawBeamMonHeaderBlock& rbmhb,
00034                                  const RawBeamMonBlock& rbmb)
00035 {
00036     VldContext vc = rbmhb.GetVldContext();
00037     bool new_peds = fPeds.SetSpillTime(vc);
00038     bool new_mask = fMask.SetSpillTime(vc);
00039 
00040     if (! (new_peds || new_mask)) return;
00041 
00042     DevList::iterator it, done = fDevList.end();
00043     for (it=fDevList.begin(); it != done; ++it) {
00044         this->CalibrateOne(rbmhb,rbmb,**it);
00045     }
00046 }
00047 
00048 void BDSwicCalibrator::CalibrateOne(const RawBeamMonHeaderBlock& /*rbmhb*/,
00049                                     const RawBeamMonBlock& rbmb,
00050                                     BDSwicDevice& sd)
00051 {
00052     if (!sd.IsValid()) {
00053         MSG("BD",Msg::kDebug)
00054             << "BDSwicCalibrator: given invalid SWIC data\n";
00055         return;
00056     }
00057 
00058     string name = sd.GetData().GetName();
00059     MSG("BDU",Msg::kVerbose)
00060         << "BDSwicCalibrator: calibrating " << name << endl;
00061 
00062     // Pedestals
00063     vector<double> mean(96,0), sigma(96,0);
00064     int ok = fPeds.GetPeds(name.c_str(),mean,sigma);
00065     if (!ok) {
00066         MSG("BD",Msg::kDebug) << "BDSwicCalibrator:: no peds for: " 
00067                                 << name << endl;
00068     }
00069     
00070     // Channel masks
00071     vector<double> mask = fMask.GetMask(name.c_str());
00072     if (!mask.size()) {
00073         MSG("BD",Msg::kWarning) << "BDSwicCalibrator:: no mask for: "
00074                                 << name << endl;
00075         mask = vector<double>(96,1);
00076     }
00077     // for now hard code some masking of high peds in addition to any
00078     // masking from the DB.
00079     BDSwicDevice::MonitorType monitor_type = sd.GetMonitorType();
00080     if (monitor_type == BDSwicDevice::kProfile) {
00081         for (int ind=0; ind<96; ++ind)
00082             if (sigma[ind] > max_profile_pedestal_rms) mask[ind] = 0.0;
00083     }
00084 
00085     switch (monitor_type) {
00086     case BDSwicDevice::kMuon:
00087         sd.SetCapacitance(1.0e2*Munits::picofarad);
00088         break;
00089     case BDSwicDevice::kProfile: // fall through
00090     case BDSwicDevice::kHadron:  // fall through
00091     case BDSwicDevice::kUnknown: // fall through
00092     default:                     // fall through
00093         sd.SetCapacitance(1.0e5*Munits::picofarad);
00094         break;
00095     }
00096 
00097     sd.SetPeds(mean);
00098     sd.SetNoise(sigma);
00099     sd.SetMask(mask);
00100 
00101     // if we don't have a PIC type device we are done here
00102     BDSwicDevice::MonitorType type = sd.GetMonitorType();
00103     if (! (type == BDSwicDevice::kHadron || type == BDSwicDevice::kMuon)) return;
00104     
00105     // temp/pressure corrections for PICs - this is a quasi static
00106     // calibration in that we hard code the gain formula.  This may
00107     // migrate to a DB table some day.
00108 
00109     // Get corresponding temperature/pressure device name
00110     string tname="", pname="";
00111     if (name == "E:HADMDS") {
00112         //tname = "E:TTHADM";
00113         tname = "E:HMRTD";
00114         //pname = "E:HMGPD";
00115         pname = "E:HMGPR";
00116     }
00117     else if (name == "E:MMA1DS") {
00118         //tname = "E:TTMA1";
00119         tname = "E:MM1RTD";
00120         //pname = "E:MM1GPD";
00121         pname = "E:MM1GPR";
00122     }
00123     else if (name == "E:MMA2DS") {
00124         //tname = "E:TTMA2";
00125         tname = "E:MM2RTD";
00126         //pname = "E:MM2GPD";
00127         pname = "E:MM2GPR";
00128     }
00129     else if (name == "E:MMA3DS") {
00130         //tname = "E:TTMA2";
00131         tname = "E:MM3RTD";
00132         //pname = "E:MM3GPD";
00133         pname = "E:MM3GPR";
00134     }
00135     else {
00136         MSG("BD",Msg::kWarning) 
00137             << "Unknown had/mu monitor: " << name
00138             << " no temp/pressure correction done\n";
00139         return;
00140     }
00141 
00142     const RawBeamData* rbd_temp = rbmb[tname.c_str()];
00143     const RawBeamData* rbd_pres = rbmb[pname.c_str()];
00144 
00145     if (!rbd_temp || !rbd_pres ||
00146         !rbd_temp->GetDataLength() || !rbd_pres->GetDataLength()) {
00147         MSG("BD",Msg::kWarning) 
00148             << "Could not get temp/pres devices for "
00149             << name << " no temp/pressure correction done\n";
00150         return;
00151     }
00152     
00153     const double temp = Munits::ToCelcius(Munits::FromFahrenheit(rbd_temp->GetData()[0]));
00154     const double pres = rbd_pres->GetData()[0];
00155 
00156     // temperature / pressure correction.  Currently the constants are
00157     // hard coded.  If they ever need to change, we need the DBI
00158     // machinery to hold them.
00159 
00160     // From Dharma:
00161     // Icorr = Iraw*(1+.0013*(gasPressure-756 torr))*(1+0.0034*(alcoveTemp-20 C))
00162 
00163     // From Mary:
00164     // (1+0.00078*(gasPressure-756 torr))*(1+0.00135*(alcoveTemp-20 C))
00165 
00166     const double pressure_nominal = 756; // tor
00167     const double temperature_nominal = 20; // degC
00168 
00169 #if 0
00170     const double pressure_factor = 0.00078;
00171     const double temperature_factor = 0.00135;
00172 #else  // Dharma:
00173     const double pressure_factor = 0.0013;
00174     const double temperature_factor = 0.0034;
00175 #endif
00176 
00177     double tp_scale = 
00178         (1.0+pressure_factor   *(pres - pressure_nominal)) *
00179         (1.0+temperature_factor*(temp - temperature_nominal));
00180     
00181     sd.SetGainCorrection(tp_scale);
00182 
00183 
00184     // Note: we don't do any truly static calibrations at this stage
00185     // since they were done when the device as added, below.
00186 }
00187 
00188 bool BDSwicCalibrator::AddDevice(BDSwicDevice& dev)
00189 {
00190     // Reject if no underlying data.
00191     if (!dev.IsValid()) {
00192         MSG("BD",Msg::kWarning)
00193             << "Not adding invalid device\n";
00194         return false;
00195     }
00196 
00197     const char* device_name = dev.GetData().GetName().c_str();
00198 
00199     // Already gotchya, sucker.
00200     if (find(fDevList.begin(),fDevList.end(),&dev) != fDevList.end()) {
00201         return true;
00202     }
00203 
00204     fPeds.AddDevice(device_name);
00205     fMask.AddDevice(device_name);
00206 
00207     // add device to list
00208     fDevList.push_back(&dev);
00209 
00210     return true;
00211 }
00212 
00213 void BDSwicCalibrator::RemoveDevice(BDSwicDevice& dev)
00214 {
00215     fDevList.remove(&dev);
00216 }

Generated on Sat Nov 7 01:25:06 2009 for loon by  doxygen 1.3.9.1