TimeTool/src/Setup.cpp

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 // File and Version Information:
00003 //      $Id$
00004 //
00005 // Description:
00006 //      Class TimeTool::Setup...
00007 //
00008 // Author List:
00009 //      Matthew J. Weaver
00010 //
00011 //------------------------------------------------------------------------
00012 
00013 //-----------------------
00014 // This Class's Header --
00015 //-----------------------
00016 #include "TimeTool/Setup.h"
00017 
00018 //-----------------
00019 // C/C++ Headers --
00020 //-----------------
00021 #include <fstream>
00022 #include "psalg/psalg.h"
00023 
00024 //-------------------------------
00025 // Collaborating Class Headers --
00026 //-------------------------------
00027 // to work with detector data include corresponding 
00028 // header from psddl_psana package
00029 #include "MsgLogger/MsgLogger.h"
00030 #include "PSEvt/EventId.h"
00031 #include "psddl_psana/evr.ddl.h"
00032 #include "psddl_psana/lusi.ddl.h"
00033 #include "psddl_psana/camera.ddl.h"
00034 #include "psddl_psana/opal1k.ddl.h"
00035 
00036 #include <iomanip>
00037 #include <fstream>
00038 #include <sstream>
00039 
00040 //-----------------------------------------------------------------------
00041 // Local Macros, Typedefs, Structures, Unions and Forward Declarations --
00042 //-----------------------------------------------------------------------
00043 
00044 // This declares this class as psana module
00045 using namespace TimeTool;
00046 PSANA_MODULE_FACTORY(Setup)
00047 
00048 //              ----------------------------------------
00049 //              -- Public Function Member Definitions --
00050 //              ----------------------------------------
00051 
00052 namespace TimeTool {
00053 
00054 //----------------
00055 // Constructors --
00056 //----------------
00057 Setup::Setup (const std::string& name)
00058   : Module(name), m_hacf(0)
00059 {
00060   // get the values from configuration or use defaults
00061   m_get_key = configSrc("get_key","DetInfo(:Opal1000)");
00062 
00063   m_eventcode_nobeam = config("eventcode_nobeam",162);
00064 
00065   m_eventcode_skip   = config("eventcode_skip");
00066 
00067   m_ipm_get_key        = configStr("ipm_get_key");
00068   m_ipm_beam_threshold = config("ipm_beam_threshold",0.);
00069 
00070   m_projectX  = config("projectX",true);
00071   m_proj_cut  = config("proj_cut" ,0);
00072 
00073 #define initList(l)                             \
00074   std::vector<unsigned> l = configList(#l);
00075 
00076   initList(sig_roi_x)
00077   initList(sig_roi_y)
00078   initList(sb_roi_x)
00079   initList(sb_roi_y)
00080 #undef initList
00081 
00082   m_frame_roi[0] = m_frame_roi[1] = 0;
00083 
00084   if (sb_roi_x.size() && sb_roi_y.size()) {
00085     if (m_projectX) {
00086       if (sb_roi_x[0]!=sig_roi_x[0] ||
00087           sb_roi_x[1]!=sig_roi_x[1]) {
00088         sb_roi_x[0] = sig_roi_x[0];
00089         sb_roi_x[1] = sig_roi_x[1];
00090         MsgLog(name, warning, 
00091                name << ": Signal and sideband roi x ranges differ.  Setting sideband roi to signal.");
00092       }
00093       if ((sb_roi_y[1]-sb_roi_y[0]) != (sig_roi_y[1]-sig_roi_y[0])) {
00094         MsgLog(name, fatal, 
00095                name << ": Signal and sideband roi y range sizes differ.");
00096       }
00097     }
00098     else {
00099       if (sb_roi_y[0]!=sig_roi_y[0] ||
00100           sb_roi_y[1]!=sig_roi_y[1]) {
00101         sb_roi_y[0] = sig_roi_y[0];
00102         sb_roi_y[1] = sig_roi_y[1];
00103         MsgLog(name, warning, 
00104                name << ": Signal and sideband roi y ranges differ.  Setting sideband roi to signal.");
00105       }
00106       if ((sb_roi_x[1]-sb_roi_x[0]) != (sig_roi_x[1]-sig_roi_x[0])) {
00107         MsgLog(name, fatal, 
00108                name << ": Signal and sideband roi x range sizes differ.");
00109       }
00110     }
00111     m_sb_roi_lo[0] = sb_roi_y[0];
00112     m_sb_roi_hi[0] = sb_roi_y[1];
00113     m_sb_roi_lo[1] = sb_roi_x[0];
00114     m_sb_roi_hi[1] = sb_roi_x[1];
00115   }
00116   else {
00117     m_sb_roi_lo[0] = m_sb_roi_hi[0] = 0;
00118     m_sb_roi_lo[1] = m_sb_roi_hi[1] = 0;
00119   }
00120 
00121   m_sig_roi_lo[0] = sig_roi_y[0];
00122   m_sig_roi_hi[0] = sig_roi_y[1];
00123   m_sig_roi_lo[1] = sig_roi_x[0];
00124   m_sig_roi_hi[1] = sig_roi_x[1];
00125 
00126   m_sb_avg_fraction  = config("sb_avg_fraction",0.05);
00127   m_ref_avg_fraction = config("ref_avg_fraction",1.);
00128 
00129   std::string ref_load  = configStr("ref_load");
00130   if (!ref_load.empty()) {
00131     std::ifstream s(ref_load.c_str());
00132     std::vector<double> ref;
00133     while(s.good()) {
00134       double v;
00135       s >> v;
00136       ref.push_back(v);
00137     }
00138 
00139     m_ref = make_ndarray<double>(ref.size());
00140     for(unsigned i=0; i<ref.size(); i++)
00141       m_ref[i] = ref[i];
00142 
00143     if (m_ref.size()==0) {
00144       MsgLog(name, fatal, 
00145              name << ": Reference load failed");
00146     }
00147   }
00148   else {
00149     MsgLog(name, fatal, 
00150            name << ": No ref_load parameter provided");
00151   }
00152 
00153   m_pedestal  = 0;
00154 
00155   unsigned ndump = config("dump",0);
00156   for(unsigned i=0; i<ndump; i++)
00157     m_hdump.push_back(DumpH());
00158 }
00159 
00160 //--------------
00161 // Destructor --
00162 //--------------
00163 Setup::~Setup ()
00164 {
00165 }
00166 
00167 /// Method which is called once at the beginning of the job
00168 void 
00169 Setup::beginJob(Event& evt, Env& env)
00170 {
00171   {
00172     shared_ptr<Psana::Opal1k::ConfigV1> config = 
00173       env.configStore().get(m_get_key);
00174     if (config.get()) {
00175       m_pedestal = config->output_offset();
00176       MsgLog(name(), info, 
00177              name() << ": found configured offset of " << m_pedestal);
00178     }
00179   }
00180 
00181   {
00182     shared_ptr<Psana::Camera::FrameFexConfigV1> config = 
00183       env.configStore().get(m_get_key);
00184     if (config.get() && 
00185         config->forwarding()==Psana::Camera::FrameFexConfigV1::RegionOfInterest) {
00186       MsgLog(name(), info, 
00187              name() << ": found configured roi of [" 
00188              << config->roiBegin().column() << ','
00189              << config->roiEnd  ().column() << "] ["
00190              << config->roiBegin().row() << ','
00191              << config->roiEnd  ().row() << "]");
00192 
00193       //  current software does not correct for ROI
00194 #if 0
00195       unsigned roi_y = config->roiBegin().row();
00196       m_frame_roi [0] = roi_y;
00197       m_sig_roi_lo[0] -= roi_y;
00198       m_sig_roi_hi[0] -= roi_y;
00199       m_sb_roi_lo [0] -= roi_y;
00200       m_sb_roi_hi [0] -= roi_y;
00201 
00202       unsigned roi_x = config->roiBegin().column();
00203       m_frame_roi [1] = roi_x;
00204       m_sig_roi_lo[1] -= roi_x;
00205       m_sig_roi_hi[1] -= roi_x;
00206       m_sb_roi_lo [1] -= roi_x;
00207       m_sb_roi_hi [1] -= roi_x;
00208 #endif
00209     }
00210   }
00211   
00212   if (m_hdump.size()>0) {
00213     m_hmgr = env.hmgr();
00214     if (not m_hmgr) {
00215       MsgLog(name(), error, "histogram manager returned by psana env "
00216              "is null, but histogramming has been requested in configuration. "
00217              "No histograms will be created.");
00218     }
00219   }
00220   
00221   if (m_hmgr) {
00222     unsigned pdim = m_projectX ? 1:0;
00223     Axis a(m_sig_roi_hi[pdim]-m_sig_roi_lo[pdim]+1,
00224            double(m_sig_roi_lo[pdim])-0.5,double(m_sig_roi_hi[pdim]+0.5));
00225     for(unsigned i=0; i<m_hdump.size(); i++) {
00226       { std::stringstream s;
00227         s << "Raw projection: event " << i;
00228         m_hdump[i].hraw = m_hmgr->hist1d(s.str().c_str(),"projection",a); }
00229       { std::stringstream s;
00230         s << "Corr projection: event " << i;
00231         m_hdump[i].hcor = m_hmgr->hist1d(s.str().c_str(),"projection",a); }
00232       { std::stringstream s;
00233         s << "Corr reference: event " << i;
00234         m_hdump[i].href = m_hmgr->hist1d(s.str().c_str(),"projection",a); }
00235       { std::stringstream s;
00236         s << "Ratio: event " << i;
00237         m_hdump[i].hrat = m_hmgr->hist1d(s.str().c_str(),"ratio",a); }
00238       { std::stringstream s;
00239         s << "ACF: event " << i;
00240         m_hdump[i].hacf = m_hmgr->hist1d(s.str().c_str(),"acf",a); }
00241     }
00242 
00243     m_hacf = m_hmgr->prof1("Reference ACF","autocorrelation",a);
00244   } 
00245   m_count=0;
00246 }
00247 
00248 /// Method which is called at the beginning of the run
00249 void 
00250 Setup::beginRun(Event& evt, Env& env)
00251 {
00252 }
00253 
00254 /// Method which is called at the beginning of the calibration cycle
00255 void 
00256 Setup::beginCalibCycle(Event& evt, Env& env)
00257 {
00258 }
00259 
00260 /// Method which is called with event data, this is the only required 
00261 /// method, all other methods are optional
00262 void 
00263 Setup::event(Event& evt, Env& env)
00264 {
00265   bool nobeam=false;
00266   { 
00267     //
00268     //  Beam is absent if BYKIK fired
00269     //
00270     shared_ptr<Psana::EvrData::DataV3> evr4 = evt.get(Source("DetInfo(:Evr)"));
00271     shared_ptr<Psana::EvrData::DataV3> evr3;
00272     if (not evr4) evr3 = evt.get(Source("DetInfo(:Evr)"));
00273     if (evr3 or evr4) {
00274       bool nolaser=false;
00275       ndarray<const Psana::EvrData::FIFOEvent,1> f = \
00276         evr4 ? evr4->fifoEvents() : evr3->fifoEvents();
00277       unsigned ec_nobeam = unsigned(abs(m_eventcode_nobeam));
00278       unsigned ec_skip   = unsigned(abs(m_eventcode_skip));
00279       for(unsigned i=0; i<f.shape()[0]; i++) {
00280         nobeam  |= (f[i].eventCode()==ec_nobeam);
00281         nolaser |= (f[i].eventCode()==ec_skip);
00282         MsgLog(name(), trace, 
00283                name() << ": Found EVR code " << f[i].eventCode());
00284       }
00285 
00286       if (m_eventcode_nobeam  < 0) nobeam  = !nobeam;
00287       if (m_eventcode_skip    < 0) nolaser = !nolaser;
00288 
00289       if (nolaser) return;
00290     }
00291     else {
00292       MsgLog(name(), warning, 
00293              name() << ": Failed to retrieve EVR event data - tried DataV3 and DataV4.");
00294     }
00295 
00296     //
00297     //  Beam is absent if not enough signal on the IPM detector
00298     //
00299     if (!m_ipm_get_key.empty()) {
00300       shared_ptr<Psana::Lusi::IpmFexV1> ipm = evt.get(m_ipm_get_key);
00301       if (ipm.get())
00302         nobeam |= ipm.get()->sum() < m_ipm_beam_threshold;
00303     }
00304   }        
00305 
00306   if (!nobeam) return;
00307 
00308   MsgLog(name(), trace, 
00309          name() << ": fetching frame data.");
00310 
00311   // example of getting frame data from event
00312   shared_ptr<Psana::Camera::FrameV1> frame = evt.get(m_get_key);
00313   if (frame.get()) {
00314     ndarray<const uint16_t,2> f = frame->data16();
00315     bool lfatal=false;
00316     for(unsigned i=0; i<2; i++) {
00317       if (m_sig_roi_hi[i] >= f.shape()[i]) {
00318         lfatal |= (m_projectX == (i==0));
00319         MsgLog(name(), warning, 
00320                name() << ": signal " << (i==0 ? 'Y':'X') << " upper bound ["
00321                << m_sig_roi_hi[i] << "] exceeds frame bounds ["
00322                << f.shape()[i] << "].");
00323         m_sig_roi_hi[i] = f.shape()[i]-1;
00324       }
00325       if (m_sb_roi_hi[i] >= f.shape()[i]) {
00326         lfatal |= (m_projectX == (i==0));
00327         MsgLog(name(), warning, 
00328                name() << ": sideband " << (i==0 ? 'Y':'X') << " upper bound ["
00329                << m_sb_roi_hi[i] << "] exceeds frame bounds ["
00330                << f.shape()[i] << "].");
00331         m_sb_roi_hi[i] = f.shape()[i]-1;
00332       }
00333     }
00334     if (lfatal)
00335       MsgLog(name(), fatal, 
00336              name() << ": Fix bounds before proceeding.");
00337     
00338     MsgLog(name(), trace, 
00339            name() << ": projecting.");
00340 
00341     //
00342     //  Project signal ROI
00343     //
00344     unsigned pdim = m_projectX ? 1:0;
00345     ndarray<const int,1> sig = psalg::project(f, 
00346                                               m_sig_roi_lo, 
00347                                               m_sig_roi_hi,
00348                                               m_pedestal, pdim);
00349 
00350     //
00351     //  Calculate sideband correction
00352     //
00353     ndarray<const int,1> sb;
00354     if (m_sb_roi_lo[0]!=m_sb_roi_hi[0])
00355       sb = psalg::project(f, 
00356                           m_sb_roi_lo , 
00357                           m_sb_roi_hi,
00358                           m_pedestal, pdim);
00359 
00360     ndarray<double,1> sigd = make_ndarray<double>(sig.shape()[0]);
00361 
00362     MsgLog(name(), trace, 
00363            name() << ": correcting for sideband.");
00364 
00365     //
00366     //  Correct projection for common mode found in sideband
00367     //
00368     if (sb.size()) {
00369       psalg::rolling_average(sb, m_sb_avg, m_sb_avg_fraction);
00370       
00371       ndarray<const double,1> sbc = psalg::commonModeLROE(sb, m_sb_avg);
00372 
00373       for(unsigned i=0; i<sig.shape()[0]; i++)
00374         sigd[i] = double(sig[i])-sbc[i];
00375     }
00376     else {
00377       for(unsigned i=0; i<sig.shape()[0]; i++)
00378         sigd[i] = double(sig[i]);
00379     }
00380 
00381     //
00382     //  Require projection has a minimum amplitude (else no laser)
00383     //
00384     bool lcut=true;
00385     for(unsigned i=0; i<sig.shape()[0]; i++)
00386       if (sigd[i]>m_proj_cut)
00387         lcut=false;
00388       
00389     if (lcut) return;
00390 
00391     MsgLog(name(), trace, 
00392            name() << ": Divide by the reference.");
00393 
00394     //
00395     //  Divide by the reference
00396     //
00397     ndarray<double,1> drat = make_ndarray<double>(sig.shape()[0]);
00398     for(unsigned i=0; i<sig.shape()[0]; i++)
00399       drat[i] = sigd[i]/m_ref[i] - 1;
00400 
00401     if ((m_count < m_hdump.size()) and m_hmgr) {
00402       for(unsigned i=0; i<sig.shape()[0]; i++)
00403         m_hdump[m_count].hraw->fill(double(i)+m_sig_roi_lo[pdim],double(sig[i]));
00404       for(unsigned i=0; i<sigd.shape()[0]; i++)
00405         m_hdump[m_count].hcor->fill(double(i)+m_sig_roi_lo[pdim],sigd[i]);
00406       for(unsigned i=0; i<m_ref.shape()[0]; i++)
00407         m_hdump[m_count].href->fill(double(i)+m_sig_roi_lo[pdim],m_ref[i]);
00408       for(unsigned i=0; i<sigd.shape()[0]; i++)
00409         m_hdump[m_count].hrat->fill(double(i)+m_sig_roi_lo[pdim],drat[i]);
00410       for(unsigned i=0; i<sigd.shape()[0]; i++) {
00411         double wt = 1./double(sigd.shape()[0]-i);
00412         for(unsigned j=0; (i+j)<sigd.shape()[0]; j++)
00413           m_hdump[m_count].hacf->fill(double(i)+m_sig_roi_lo[pdim],drat[j]*drat[i+j]*wt);
00414       }
00415       m_count++;
00416     }
00417 
00418     MsgLog(name(), trace, 
00419            name() << ": Accumulate the ACF.");
00420 
00421     //
00422     //  Accumulate the ACF
00423     //
00424     if (m_hmgr) {
00425       for(unsigned i=0; i<sig.shape()[0]; i++)
00426         for(unsigned j=i; j<sig.shape()[0]; j++)
00427           m_hacf->fill(double(j-i),drat[i]*drat[j]);
00428     }
00429     psalg::rolling_average(ndarray<const double,1>(sigd),
00430                            m_ref, m_ref_avg_fraction);
00431     
00432   }
00433   else {
00434     MsgLog(name(), warning, name() << ": Could not fetch " << m_get_key);
00435   }
00436 }
00437  
00438 /// Method which is called at the end of the calibration cycle
00439 void 
00440 Setup::endCalibCycle(Event& evt, Env& env)
00441 {
00442 }
00443 
00444 /// Method which is called at the end of the run
00445 void 
00446 Setup::endRun(Event& evt, Env& env)
00447 {
00448 }
00449 
00450 /// Method which is called once at the end of the job
00451 void 
00452 Setup::endJob(Event& evt, Env& env)
00453 {
00454 }
00455 
00456 } // namespace TimeTool
00457 

Generated on 19 Dec 2016 for PSDMSoftware by  doxygen 1.4.7