00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #define __STDC_LIMIT_MACROS
00014
00015
00016
00017
00018 #include "TimeTool/Analyze.h"
00019
00020
00021
00022
00023 #include <cfloat>
00024 #include <limits.h>
00025 #include <fstream>
00026 #include <iterator>
00027 #include <algorithm>
00028 #include "psalg/psalg.h"
00029
00030
00031
00032
00033
00034
00035 #include "MsgLogger/MsgLogger.h"
00036 #include "PSEvt/EventId.h"
00037 #include "psddl_psana/evr.ddl.h"
00038 #include "psddl_psana/lusi.ddl.h"
00039 #include "psddl_psana/camera.ddl.h"
00040 #include "psddl_psana/opal1k.ddl.h"
00041 #include "psddl_psana/timetool.ddl.h"
00042 #include "ndarray/ndarray.h"
00043 #include "PSCalib/CalibParsStore.h"
00044
00045 #include <iomanip>
00046 #include <fstream>
00047 #include <sstream>
00048
00049
00050
00051
00052
00053
00054 using namespace TimeTool;
00055 PSANA_MODULE_FACTORY(Analyze)
00056
00057 namespace {
00058
00059 static bool
00060 calculate_logic(const ndarray<const Psana::TimeTool::EventLogic,1>& cfg,
00061 const ndarray<const Psana::EvrData::FIFOEvent,1>& event)
00062 {
00063 bool v = (cfg.size()==0) ||
00064 (cfg[0].logic_op() == Psana::TimeTool::EventLogic::L_AND ||
00065 cfg[0].logic_op() == Psana::TimeTool::EventLogic::L_AND_NOT);
00066 for(unsigned i=0; i<cfg.size(); i++) {
00067
00068 bool p=false;
00069 for(unsigned j=0; j<event.size(); j++)
00070 if (event[j].eventCode()==cfg[i].event_code()) {
00071 p=true;
00072 break;
00073 }
00074 switch(cfg[i].logic_op()) {
00075 case Psana::TimeTool::EventLogic::L_OR:
00076 v = v||p; break;
00077 case Psana::TimeTool::EventLogic::L_AND:
00078 v = v&&p; break;
00079 case Psana::TimeTool::EventLogic::L_OR_NOT:
00080 v = v||!p; break;
00081 case Psana::TimeTool::EventLogic::L_AND_NOT:
00082 v = v&&!p; break;
00083 default: break;
00084 }
00085 }
00086 return v;
00087 }
00088
00089 class TimeToolData : public Psana::TimeTool::DataV2 {
00090 public:
00091
00092
00093
00094
00095
00096
00097 TimeToolData(Psana::TimeTool::DataV2::EventType event_type_arg,
00098 double amplitude_arg,
00099 double position_pixel_arg,
00100 double position_time_arg,
00101 double position_fwhm_arg,
00102 double ref_amplitude_arg,
00103 double nxt_amplitude_arg)
00104 : m_event_type(event_type_arg),
00105 m_amplitude(amplitude_arg),
00106 m_position_pixel(position_pixel_arg),
00107 m_position_time(position_time_arg),
00108 m_position_fwhm(position_fwhm_arg),
00109 m_ref_amplitude(ref_amplitude_arg),
00110 m_nxt_amplitude(nxt_amplitude_arg)
00111 {}
00112
00113 virtual enum Psana::TimeTool::DataV2::EventType event_type() const { return m_event_type; }
00114 virtual double amplitude() const { return m_amplitude; }
00115 virtual double position_pixel() const { return m_position_pixel; }
00116 virtual double position_time() const { return m_position_time; };
00117 virtual double position_fwhm() const { return m_position_fwhm; };
00118 virtual double ref_amplitude() const { return m_ref_amplitude; };
00119 virtual double nxt_amplitude() const { return m_nxt_amplitude; };
00120 virtual ndarray<const int32_t, 1> projected_signal() const { return m_projected_signal; };
00121 virtual ndarray<const int32_t, 1> projected_sideband() const { return m_projected_sideband; };
00122 virtual ndarray<const int32_t, 1> projected_reference() const { return m_projected_reference; };
00123
00124 private:
00125 Psana::TimeTool::DataV2::EventType m_event_type;
00126 double m_amplitude;
00127 double m_position_pixel;
00128 double m_position_time;
00129 double m_position_fwhm;
00130 double m_ref_amplitude;
00131 double m_nxt_amplitude;
00132 ndarray<const int32_t, 1> m_projected_signal;
00133 ndarray<const int32_t, 1> m_projected_sideband;
00134 ndarray<const int32_t, 1> m_projected_reference;
00135 };
00136
00137
00138 void local_rolling_average(const ndarray<const uint16_t,2> &newArray,
00139 ndarray<double,2> &accumulatedArray,
00140 double newFraction,
00141 const std::string &loggerName) {
00142 if (accumulatedArray.empty()) {
00143 accumulatedArray = ndarray<double,2>(newArray.shape());
00144 for (unsigned row = 0; row < newArray.shape()[0]; ++row) {
00145 for (unsigned col = 0; col < newArray.shape()[1]; ++col) {
00146 accumulatedArray[row][col] = double(newArray[row][col]);
00147 }
00148 }
00149 } else {
00150 if ((newArray.shape()[0] != accumulatedArray.shape()[0]) or
00151 (newArray.shape()[1] != accumulatedArray.shape()[1])) {
00152 MsgLog(loggerName, error, "newArray shape != accumArray shape");
00153 }
00154 for (unsigned row = 0; row < newArray.shape()[0]; ++row) {
00155 for (unsigned col = 0; col < newArray.shape()[1]; ++col) {
00156 double oldVal = accumulatedArray[row][col];
00157 accumulatedArray[row][col] = (1.0-newFraction)*oldVal + newFraction * newArray[row][col];
00158 }
00159 }
00160
00161 }
00162 }
00163
00164 }
00165
00166
00167
00168
00169
00170
00171 namespace TimeTool {
00172
00173
00174
00175
00176 Analyze::Analyze (const std::string& name)
00177 : Module(name)
00178 {
00179 std::string emptys;
00180
00181
00182 m_get_key = configSrc("get_key","DetInfo(:Opal1000)");
00183 m_beam_on_off_key = configStr("beam_on_off_key","");
00184 m_laser_on_off_key = configStr("laser_on_off_key","");
00185 m_put_key = configStr("put_key","TTSPEC");
00186
00187
00188 m_validConfigKeys.insert("get_key");
00189 m_validConfigKeys.insert("beam_on_off_key");
00190 m_validConfigKeys.insert("laser_on_off_key");
00191 m_validConfigKeys.insert("put_key");
00192 m_validConfigKeys.insert("eventcode_nobeam");
00193
00194 int eventcode_nobeam = config("eventcode_nobeam",0);
00195 if (eventcode_nobeam>0) {
00196 ndarray<Psana::TimeTool::EventLogic,1> e =
00197 make_ndarray<Psana::TimeTool::EventLogic>(1);
00198 e[0] = Psana::TimeTool::EventLogic(eventcode_nobeam,
00199 Psana::TimeTool::EventLogic::L_AND_NOT);
00200 m_beam_logic = e;
00201 }
00202 else if (eventcode_nobeam<0) {
00203 ndarray<Psana::TimeTool::EventLogic,1> e =
00204 make_ndarray<Psana::TimeTool::EventLogic>(1);
00205 e[0] = Psana::TimeTool::EventLogic(-eventcode_nobeam,
00206 Psana::TimeTool::EventLogic::L_AND);
00207 m_beam_logic = e;
00208 }
00209
00210 int eventcode_skip = config("eventcode_skip",0);
00211 m_validConfigKeys.insert("eventcode_skip");
00212
00213 if (eventcode_skip>0) {
00214 ndarray<Psana::TimeTool::EventLogic,1> e =
00215 make_ndarray<Psana::TimeTool::EventLogic>(1);
00216 e[0] = Psana::TimeTool::EventLogic(eventcode_skip,
00217 Psana::TimeTool::EventLogic::L_AND_NOT);
00218 m_laser_logic = e;
00219 }
00220 else if (eventcode_skip<0) {
00221 ndarray<Psana::TimeTool::EventLogic,1> e =
00222 make_ndarray<Psana::TimeTool::EventLogic>(1);
00223 e[0] = Psana::TimeTool::EventLogic(-eventcode_skip,
00224 Psana::TimeTool::EventLogic::L_AND);
00225 m_laser_logic = e;
00226 }
00227
00228 m_validConfigKeys.insert("ipm_get_key");
00229 m_validConfigKeys.insert("ipm_beam_threshold");
00230 m_validConfigKeys.insert("calib_poly");
00231
00232 m_ipm_get_key = configStr("ipm_get_key",emptys);
00233 m_ipm_beam_threshold = config("ipm_beam_threshold",DBL_MIN);
00234
00235 { std::vector<double> v = configList("calib_poly");
00236 if (v.size()) {
00237 ndarray<double,1> e = make_ndarray<double>(v.size());
00238 std::copy(v.begin(),v.end(),e.begin());
00239 m_calib_poly = e;
00240 } }
00241
00242 m_projectX_set = !config("projectX",true).isDefault();
00243 m_projectX = config("projectX",true);
00244 m_proj_cut = config("proj_cut" ,INT_MIN);
00245
00246 m_validConfigKeys.insert("proj_cut");
00247 m_validConfigKeys.insert("projectX");
00248
00249 std::vector<unsigned> uempty;
00250 std::vector<unsigned> sig_roi_x = configList("sig_roi_x", uempty);
00251 std::vector<unsigned> sig_roi_y = configList("sig_roi_y", uempty);
00252 std::vector<unsigned> sb_roi_x = configList("sb_roi_x", uempty);
00253 std::vector<unsigned> sb_roi_y = configList("sb_roi_y", uempty);
00254
00255 m_validConfigKeys.insert("sb_roi_x");
00256 m_validConfigKeys.insert("sb_roi_y");
00257 m_validConfigKeys.insert("sig_roi_x");
00258 m_validConfigKeys.insert("sig_roi_y");
00259
00260 m_frame_roi[0] = m_frame_roi[1] = 0;
00261
00262 if (sb_roi_x.size() && sb_roi_y.size()) {
00263 m_sb_roi_set = true;
00264 if (m_projectX) {
00265 if (sb_roi_x[0]!=sig_roi_x[0] ||
00266 sb_roi_x[1]!=sig_roi_x[1]) {
00267 sb_roi_x[0] = sig_roi_x[0];
00268 sb_roi_x[1] = sig_roi_x[1];
00269 MsgLog(name, warning,
00270 name << ": Signal and sideband roi x ranges differ. Setting sideband roi to signal.");
00271 }
00272 if ((sb_roi_y[1]-sb_roi_y[0]) != (sig_roi_y[1]-sig_roi_y[0])) {
00273 MsgLog(name, fatal,
00274 name << ": Signal and sideband roi y range sizes differ.");
00275 }
00276 }
00277 else {
00278 if (sb_roi_y[0]!=sig_roi_y[0] ||
00279 sb_roi_y[1]!=sig_roi_y[1]) {
00280 sb_roi_y[0] = sig_roi_y[0];
00281 sb_roi_y[1] = sig_roi_y[1];
00282 MsgLog(name, warning,
00283 name << ": Signal and sideband roi y ranges differ. Setting sideband roi to signal.");
00284 }
00285 if ((sb_roi_x[1]-sb_roi_x[0]) != (sig_roi_x[1]-sig_roi_x[0])) {
00286 MsgLog(name, fatal,
00287 name << ": Signal and sideband roi x range sizes differ.");
00288 }
00289 }
00290 m_sb_roi_lo[0] = sb_roi_y[0];
00291 m_sb_roi_hi[0] = sb_roi_y[1];
00292 m_sb_roi_lo[1] = sb_roi_x[0];
00293 m_sb_roi_hi[1] = sb_roi_x[1];
00294 }
00295 else {
00296 m_sb_roi_set = false;
00297 m_sb_roi_lo[0] = m_sb_roi_hi[0] = 0;
00298 m_sb_roi_lo[1] = m_sb_roi_hi[1] = 0;
00299 }
00300
00301 if (sig_roi_x.size() && sig_roi_y.size()) {
00302 m_sig_roi_set = true;
00303 m_sig_roi_lo[0] = sig_roi_y[0];
00304 m_sig_roi_hi[0] = sig_roi_y[1];
00305 m_sig_roi_lo[1] = sig_roi_x[0];
00306 m_sig_roi_hi[1] = sig_roi_x[1];
00307 }
00308 else {
00309 m_sig_roi_set = false;
00310 m_sig_roi_lo[0] = 0;
00311 m_sig_roi_hi[0] = 0;
00312 m_sig_roi_lo[1] = 0;
00313 m_sig_roi_hi[1] = 0;
00314 }
00315
00316 m_ref_roi_set = false;
00317 m_ref_roi_lo[0] = 0;
00318 m_ref_roi_hi[0] = 0;
00319 m_ref_roi_lo[1] = 0;
00320 m_ref_roi_hi[1] = 0;
00321
00322 m_sb_avg_fraction = config("sb_avg_fraction",DBL_MIN);
00323 m_ref_avg_fraction = config("ref_avg_fraction",DBL_MIN);
00324
00325 m_validConfigKeys.insert("sb_avg_fraction");
00326 m_validConfigKeys.insert("ref_avg_fraction");
00327 m_validConfigKeys.insert("weights");
00328 m_validConfigKeys.insert("weights_file");
00329 m_validConfigKeys.insert("ref_load");
00330
00331 { std::vector<double> w = configList("weights");
00332 if (w.size()==0) {
00333 std::string weights_file = configStr("weights_file");
00334 if (!weights_file.empty()) {
00335 std::ifstream s(weights_file.c_str());
00336 while(s.good()) {
00337 double v;
00338 s >> v;
00339 w.push_back(v);
00340 }
00341 }
00342 }
00343 if (w.size()==0) {
00344
00345 }
00346 else {
00347
00348
00349 ndarray<double,1> a = make_ndarray<double>(w.size());
00350 for(unsigned i=0; i<w.size(); i++)
00351 a[i] = w[w.size()-i-1];
00352 m_weights = a;
00353 }
00354 }
00355
00356 m_use_calib_db_ref = config("use_calib_db_ref",false);
00357 m_validConfigKeys.insert("use_calib_db_ref");
00358
00359 std::string ref_load = configStr("ref_load", "");
00360 if (!ref_load.empty()) {
00361 if (m_use_calib_db_ref) {
00362 MsgLog(name, fatal, name << ": ref_load and use_calib_db_ref confict, both are set.");
00363 }
00364 std::ifstream s(ref_load.c_str());
00365 if (not s) {
00366 MsgLog(name, fatal, "Could not open reference file: " << ref_load);
00367 }
00368 std::vector<double> ref;
00369 while(s.good()) {
00370 double v;
00371 s >> v;
00372 ref.push_back(v);
00373 }
00374 ref.resize(ref.size()-1);
00375
00376 m_ref_avg = make_ndarray<double>(ref.size());
00377 for(unsigned i=0; i<ref.size(); i++)
00378 m_ref_avg[i] = ref[i];
00379
00380 MsgLog(name, info, name <<": loaded reference of size " << m_ref_avg.size());
00381 for(unsigned i=0; i<5; i++)
00382 MsgLog(name, info, name <<": ref[" << i << "=" << m_ref_avg[i]);
00383 MsgLog(name, info, name << ": ..");
00384 for(unsigned i=m_ref_avg.size()-5; i<m_ref_avg.size(); i++)
00385 MsgLog(name, info, name <<": ref[" << i << "=" << m_ref_avg[i]);
00386
00387 }
00388
00389 m_ref_store = configStr("ref_store");
00390
00391 m_pedestal = 0;
00392
00393 m_analyze_event = config("analyze_event",-1);
00394
00395 if (config("eventdump",false)) {
00396 m_eventDump.init(m_put_key);
00397 }
00398
00399 unsigned ndump = config("dump",0);
00400 for(unsigned i=0; i<ndump; i++)
00401 m_hdump.push_back(DumpH());
00402
00403 m_validConfigKeys.insert("dump");
00404 m_validConfigKeys.insert("eventdump");
00405 m_validConfigKeys.insert("analyze_event");
00406 m_validConfigKeys.insert("ref_store");
00407
00408 checkForInvalidConfigKeys(m_validConfigKeys);
00409 }
00410
00411 void Analyze::checkForInvalidConfigKeys(const std::set<std::string> &validConfigKeys) const {
00412 ConfigSvc::ConfigSvc cfgSvc = configSvc();
00413 std::list<std::string> configKeys = cfgSvc.getKeys(name());
00414 std::list<std::string>::iterator iter;
00415 bool invalidKeyFound = false;
00416 for (iter = configKeys.begin(); iter != configKeys.end(); ++iter) {
00417 if (validConfigKeys.end()==validConfigKeys.find(*iter)) {
00418 MsgLog(name(), error, name() << ": invalid configuration key: " << *iter);
00419 invalidKeyFound = true;
00420 }
00421 }
00422 if (invalidKeyFound) {
00423 WithMsgLog(name(), info, str) {
00424 str << ": invalid keys found. The valid keys are: ";
00425 std::ostream_iterator<std::string> str_it(str, "\n ");
00426 std::copy(validConfigKeys.begin(), validConfigKeys.end(), str_it);
00427 }
00428 }
00429 }
00430
00431
00432
00433
00434 Analyze::~Analyze ()
00435 {
00436 }
00437
00438
00439 void
00440 Analyze::beginJob(Event& evt, Env& env)
00441 {
00442 m_analyze_projections = false;
00443
00444 if (m_hdump.size()>0) {
00445 m_hmgr = env.hmgr();
00446 if (not m_hmgr) {
00447 MsgLog(name(), error,
00448 "env does not have a histogram manager, but histogramming has been requested "
00449 "(config dump parmameter > 0). No histograms will be made");
00450 }
00451 }
00452
00453 shared_ptr<Psana::TimeTool::ConfigV2> c =
00454 env.configStore().get(m_get_key);
00455 if (c.get()) {
00456 const Psana::TimeTool::ConfigV2& config = *c.get();
00457 if (m_beam_logic.size()==0)
00458 m_beam_logic = config.beam_logic();
00459 if (m_laser_logic.size()==0)
00460 m_laser_logic = config.laser_logic();
00461 if (m_calib_poly.size()==0)
00462 m_calib_poly = config.calib_poly();
00463 if (!m_projectX_set)
00464 m_projectX = unsigned(config.project_axis())==unsigned(Psana::TimeTool::ConfigV1::X);
00465 if (m_proj_cut != INT_MIN)
00466 m_proj_cut = config.signal_cut();
00467 if (!m_sig_roi_set) {
00468 m_sig_roi_lo[0] = config.sig_roi_lo().row();
00469 m_sig_roi_lo[1] = config.sig_roi_lo().column();
00470 m_sig_roi_hi[0] = config.sig_roi_hi().row();
00471 m_sig_roi_hi[1] = config.sig_roi_hi().column();
00472 }
00473 if (!m_sb_roi_set && config.subtract_sideband()) {
00474 m_sb_roi_lo[0] = config.sb_roi_lo().row();
00475 m_sb_roi_lo[1] = config.sb_roi_lo().column();
00476 m_sb_roi_hi[0] = config.sb_roi_hi().row();
00477 m_sb_roi_hi[1] = config.sb_roi_hi().column();
00478 }
00479 if (m_sb_avg_fraction != DBL_MIN)
00480 m_sb_avg_fraction = config.sb_convergence();
00481 if (m_ref_avg_fraction != DBL_MIN)
00482 m_ref_avg_fraction = config.ref_convergence();
00483 if (m_weights.size()==0)
00484 m_weights = config.weights();
00485
00486 m_analyze_projections = config.write_projections();
00487
00488 m_analyze_projections &=
00489 m_projectX == (unsigned(config.project_axis())==unsigned(Psana::TimeTool::ConfigV1::X)) &&
00490 m_sig_roi_lo[0] == config.sig_roi_lo().row() &&
00491 m_sig_roi_lo[1] == config.sig_roi_lo().column() &&
00492 m_sig_roi_hi[0] == config.sig_roi_hi().row() &&
00493 m_sig_roi_hi[1] == config.sig_roi_hi().column();
00494
00495 if (m_sb_roi_set) {
00496 m_analyze_projections &=
00497 config.subtract_sideband() &&
00498 m_sb_roi_lo[0] == config.sb_roi_lo().row() &&
00499 m_sb_roi_lo[1] == config.sb_roi_lo().column() &&
00500 m_sb_roi_hi[0] == config.sb_roi_hi().row() &&
00501 m_sb_roi_hi[1] == config.sb_roi_hi().column();
00502 }
00503 }
00504 else {
00505 shared_ptr<Psana::TimeTool::ConfigV1> c =
00506 env.configStore().get(m_get_key);
00507 if (c.get()) {
00508 const Psana::TimeTool::ConfigV1& config = *c.get();
00509 if (m_beam_logic.size()==0)
00510 m_beam_logic = config.beam_logic();
00511 if (m_laser_logic.size()==0)
00512 m_laser_logic = config.laser_logic();
00513 if (m_calib_poly.size()==0)
00514 m_calib_poly = config.calib_poly();
00515 if (!m_projectX_set)
00516 m_projectX = config.project_axis()==Psana::TimeTool::ConfigV1::X;
00517 if (m_proj_cut != INT_MIN)
00518 m_proj_cut = config.signal_cut();
00519 if (!m_sig_roi_set) {
00520 m_sig_roi_lo[0] = config.sig_roi_lo().row();
00521 m_sig_roi_lo[1] = config.sig_roi_lo().column();
00522 m_sig_roi_hi[0] = config.sig_roi_hi().row();
00523 m_sig_roi_hi[1] = config.sig_roi_hi().column();
00524 }
00525 if (!m_sb_roi_set && config.subtract_sideband()) {
00526 m_sb_roi_lo[0] = config.sb_roi_lo().row();
00527 m_sb_roi_lo[1] = config.sb_roi_lo().column();
00528 m_sb_roi_hi[0] = config.sb_roi_hi().row();
00529 m_sb_roi_hi[1] = config.sb_roi_hi().column();
00530 }
00531 if (m_sb_avg_fraction != DBL_MIN)
00532 m_sb_avg_fraction = config.sb_convergence();
00533 if (m_ref_avg_fraction != DBL_MIN)
00534 m_ref_avg_fraction = config.ref_convergence();
00535 if (m_weights.size()==0)
00536 m_weights = config.weights();
00537
00538 m_analyze_projections = config.write_projections();
00539
00540 m_analyze_projections &=
00541 m_projectX == (config.project_axis()==Psana::TimeTool::ConfigV1::X) &&
00542 m_sig_roi_lo[0] == config.sig_roi_lo().row() &&
00543 m_sig_roi_lo[1] == config.sig_roi_lo().column() &&
00544 m_sig_roi_hi[0] == config.sig_roi_hi().row() &&
00545 m_sig_roi_hi[1] == config.sig_roi_hi().column();
00546
00547 if (m_sb_roi_set) {
00548 m_analyze_projections &=
00549 config.subtract_sideband() &&
00550 m_sb_roi_lo[0] == config.sb_roi_lo().row() &&
00551 m_sb_roi_lo[1] == config.sb_roi_lo().column() &&
00552 m_sb_roi_hi[0] == config.sb_roi_hi().row() &&
00553 m_sb_roi_hi[1] == config.sb_roi_hi().column();
00554 }
00555 }
00556 }
00557
00558 if (m_beam_logic.size()==0)
00559 MsgLog(name(), info,
00560 name() << ": no beam_logic configuration given. Assume beam is always T");
00561 if (m_laser_logic.size()==0)
00562 MsgLog(name(), info,
00563 name() << ": no laser_logic configuration given. Assume laser is always T");
00564
00565 {
00566 shared_ptr<Psana::Camera::FrameFexConfigV1> config =
00567 env.configStore().get(m_get_key);
00568 if (config.get() &&
00569 config->forwarding()==Psana::Camera::FrameFexConfigV1::RegionOfInterest) {
00570 MsgLog(name(), info,
00571 name() << ": found configured roi of ["
00572 << config->roiBegin().column() << ','
00573 << config->roiEnd ().column() << "] ["
00574 << config->roiBegin().row() << ','
00575 << config->roiEnd ().row() << "]");
00576
00577
00578 #if 0
00579 unsigned roi_y = config->roiBegin().row();
00580 m_frame_roi [0] = roi_y;
00581 m_sig_roi_lo[0] -= roi_y;
00582 m_sig_roi_hi[0] -= roi_y;
00583 m_sb_roi_lo [0] -= roi_y;
00584 m_sb_roi_hi [0] -= roi_y;
00585
00586 unsigned roi_x = config->roiBegin().column();
00587 m_frame_roi [1] = roi_x;
00588 m_sig_roi_lo[1] -= roi_x;
00589 m_sig_roi_hi[1] -= roi_x;
00590 m_sb_roi_lo [1] -= roi_x;
00591 m_sb_roi_hi [1] -= roi_x;
00592 #endif
00593 }
00594 }
00595
00596 unsigned pdim = m_projectX ? 1:0;
00597 Axis a(m_sig_roi_hi[pdim]-m_sig_roi_lo[pdim]+1,
00598 double(m_sig_roi_lo[pdim])-0.5,double(m_sig_roi_hi[pdim]+0.5));
00599 unsigned i=0;
00600 if (m_hmgr) {
00601 for(std::list<DumpH>::iterator it=m_hdump.begin();
00602 it!=m_hdump.end(); it++,i++) {
00603 { std::stringstream s;
00604 s << "Raw projection: event " << i;
00605 it->hraw = m_hmgr->hist1d(s.str().c_str(),"projection",a); }
00606 { std::stringstream s;
00607 s << "Ref projection: event " << i;
00608 it->href = m_hmgr->hist1d(s.str().c_str(),"projection",a); }
00609 { std::stringstream s;
00610 s << "Ratio: event " << i;
00611 it->hrat = m_hmgr->hist1d(s.str().c_str(),"ratio",a); }
00612 { std::stringstream s;
00613 s << "Filtered: event " << i;
00614 it->hflt = m_hmgr->hist1d(s.str().c_str(),"filtered",a); }
00615 }
00616 }
00617
00618 m_count=0;
00619 }
00620
00621
00622 void
00623 Analyze::beginRun(Event& evt, Env& env)
00624 {
00625 if (m_use_calib_db_ref) {
00626
00627
00628 shared_ptr<EventId> eventId = evt.get();
00629 int run = 0;
00630 if (eventId.get()) {
00631 run = eventId->run();
00632 } else {
00633 MsgLog(name(), warning, name() << ": Looking up refernce in calibration database. Cannot determine run number, will use 0.");
00634 }
00635
00636
00637 boost::shared_ptr<PSEvt::AliasMap> amap = env.aliasMap();
00638 if (not amap) {
00639 MsgLog(name(), fatal, name() << ": could not get alias map from env");
00640 }
00641 Source::SrcMatch srcMatch = m_get_key.srcMatch(*amap);
00642 Pds::Src src(srcMatch.src());
00643
00644
00645 std::string calib_dir = env.calibDir();
00646 MsgLog(name(), trace, name() << ": Using " << calib_dir << " for calibration database");
00647 std::string group = "Camera::CalibV1";
00648 const int maxPrintBits = 0xFF;
00649 PSCalib::CalibPars* calibpars = PSCalib::CalibParsStore::Create(calib_dir, group, src,
00650 run, maxPrintBits);
00651 if (not calibpars) {
00652 MsgLog(name(), fatal, name() << ": failed to create CalibPars object");
00653 }
00654
00655 const PSCalib::CalibPars::pedestals_t* ped_data = calibpars->pedestals();
00656 if (not ped_data) {
00657 MsgLog(name(), fatal, name() << ": use_calib_db_ref has been specified,"
00658 << " but no pedestals were obtained from the calibration database "
00659 << "for this run: " << run << ". Look in: " << calib_dir << "/"
00660 << group << "/" << src);
00661 }
00662
00663 size_t rank = calibpars->ndim(PSCalib::PEDESTALS);
00664 const PSCalib::CalibPars::shape_t * shape = calibpars->shape(PSCalib::PEDESTALS);
00665
00666 if (rank != 2) {
00667 MsgLog(name(), fatal, name() << ": unexpected, size of pedestals is not two. It is" << rank);
00668 }
00669 if ((shape[0] != 1024) and (shape[1] != 1024)) {
00670 MsgLog(name(), warning, name() <<
00671 ": unexpected, shape of calibration pedestals for ref avg is " <<
00672 "not 1024 x 1024, it is " << shape[0] << " x " << shape[1]);
00673 }
00674 double avg = 0.0;
00675 m_ref_frame_avg = make_ndarray<double>(shape[0], shape[1]);
00676 for (unsigned row = 0; row < shape[0]; ++row) {
00677 for (unsigned col = 0; col < shape[1]; ++col) {
00678 avg += *ped_data;
00679 m_ref_frame_avg[row][col] = *ped_data++;
00680 }
00681 }
00682 MsgLog(name(), info, "** Successfully loaded pedestal file for initial Reference. Average pedestal value: " << avg/double(shape[0]*shape[1]));
00683 delete calibpars;
00684 }
00685 }
00686
00687
00688 void
00689 Analyze::beginCalibCycle(Event& evt, Env& env)
00690 {
00691 }
00692
00693 bool Analyze::getIsOffFromOnOffKey(const std::string & moduleParameter, const std::string & key, Event & evt)
00694 {
00695 boost::shared_ptr<std::string> onOff = evt.get(m_get_key, key);
00696 if (not onOff) {
00697 onOff = evt.get(key);
00698 if (not onOff) MsgLog(name(), fatal, moduleParameter << "=" << key
00699 << " specified but not present for either the source specified with the get_key="
00700 << m_get_key << " nor no source. It must be present in all events ");
00701 }
00702 bool isOn = *onOff == "on";
00703 bool isOff = *onOff == "off";
00704 if ((not isOn) and (not isOff)) MsgLog(name(), fatal, key
00705 << " found but value must be on of 'on' or 'off', "
00706 << "all lowercase. However it is: " << *onOff);
00707 return isOff;
00708 }
00709
00710 bool
00711 Analyze::setBeamAndLaserStatusForEvent(bool &nobeam, bool &nolaser, Event &evt)
00712 {
00713 shared_ptr<Psana::EvrData::DataV4> evr4 = evt.get(Source("DetInfo(:Evr)"));
00714 shared_ptr<Psana::EvrData::DataV3> evr3;
00715 if (not evr4) evr3 = evt.get(Source("DetInfo(:Evr)"));
00716 if (not(evr3 or evr4)) {
00717 MsgLog(name(), warning, name() << ": Could not fetch evr data - tried DataV3 and DataV4.");
00718 m_eventDump.returnReason(evt,"no_evr_data");
00719 return false;
00720 }
00721
00722 ndarray<const Psana::EvrData::FIFOEvent,1> fifoEvents = \
00723 evr4 ? evr4->fifoEvents() : evr3->fifoEvents();
00724
00725 if (m_beam_on_off_key.length()>0) {
00726 nobeam = getIsOffFromOnOffKey("beam_on_off_key",
00727 m_beam_on_off_key, evt);
00728 } else {
00729 nobeam = !calculate_logic(m_beam_logic,
00730 fifoEvents);
00731 }
00732
00733
00734 if (m_laser_on_off_key.length()>0) {
00735 nolaser = getIsOffFromOnOffKey("laser_on_off_key",
00736 m_laser_on_off_key, evt);
00737 } else {
00738 nolaser = !calculate_logic(m_laser_logic,
00739 fifoEvents);
00740 }
00741
00742 MsgLog(name(), trace, name() << ": evr_codes " << fifoEvents.size()
00743 << ": nobeam " << (nobeam ? 'T':'F')
00744 << ": nolaser " << (nolaser ? 'T':'F')
00745 << (nolaser ? " -- not processing event as no laser" : ""));
00746
00747 m_eventDump.laserBeamStatus(nobeam, nolaser, evt);
00748
00749 if (nolaser) {
00750 m_eventDump.returnReason(evt,"no_laser");
00751 return false;
00752 }
00753 return true;
00754 }
00755
00756
00757 void
00758 Analyze::updateBeamStatusBasedOnIpm(bool &nobeam, Event &evt) {
00759
00760
00761
00762 if (!m_ipm_get_key.empty()) {
00763 shared_ptr<Psana::Lusi::IpmFexV1> ipm = evt.get(Source(m_ipm_get_key));
00764 if (ipm.get()) {
00765 MsgLog(name(), info, name() << ": ipm sum = " << ipm.get()->sum());
00766 nobeam |= ipm.get()->sum() < m_ipm_beam_threshold;
00767 }
00768 else {
00769 MsgLog(name(), info, name() << ": failed to get ipm " << m_ipm_get_key);
00770
00771 MsgLog(name(), info, name() << ":\t src \tkey\talias");
00772 std::list<EventKey> keys = evt.keys();
00773 for(std::list<EventKey>::iterator it=keys.begin(); it!=keys.end(); it++) {
00774 MsgLog(name(), info, name() << ": "
00775 << '\t' << std::setw(8) << std::hex << it->src().phy()
00776 << '\t' << it->key()
00777 << '\t' << it->alias());
00778 }
00779 }
00780 }
00781 }
00782
00783 bool
00784 Analyze::isRefShot(Event &evt) {
00785 bool nobeam, nolaser;
00786 if (not setBeamAndLaserStatusForEvent(nobeam, nolaser, evt)) return false;
00787 updateBeamStatusBasedOnIpm(nobeam, evt);
00788 if ((not nolaser) and (nobeam)) return true;
00789 return false;
00790 }
00791
00792
00793
00794
00795 void
00796 Analyze::event(Event& evt, Env& env)
00797 {
00798 bool nobeam, nolaser;
00799 if (not setBeamAndLaserStatusForEvent(nobeam, nolaser, evt)) return;
00800 updateBeamStatusBasedOnIpm(nobeam, evt);
00801
00802 ndarray<const int32_t,1> sig;
00803 ndarray<const int32_t,1> sb;
00804 ndarray<const int32_t,1> ref;
00805 unsigned pdim = m_projectX ? 1:0;
00806
00807 ndarray<const uint16_t,2> frameData;
00808
00809 if (m_analyze_projections) {
00810 shared_ptr<Psana::TimeTool::DataV2> tt = evt.get(m_get_key);
00811 if (tt.get()) {
00812 sig = tt.get()->projected_signal();
00813 sb = tt.get()->projected_sideband();
00814 ref = tt.get()->projected_reference();
00815 }
00816 else {
00817 shared_ptr<Psana::TimeTool::DataV1> tt = evt.get(m_get_key);
00818 if (tt.get()) {
00819 sig = tt.get()->projected_signal();
00820 sb = tt.get()->projected_sideband();
00821 }
00822 else {
00823 MsgLog(name(), warning, name() << ": analyze_projections is true, but could not fetch timetool data");
00824 m_eventDump.returnReason(evt, "no_timetool_data");
00825 return;
00826 }
00827 }
00828 }
00829 else {
00830 shared_ptr<Psana::Camera::FrameV1> frame = evt.get(m_get_key);
00831 if (!frame.get()) {
00832 MsgLog(name(), warning, name() << ": Could not fetch frame data");
00833 m_eventDump.returnReason(evt,"no_frame_data");
00834 return;
00835 }
00836
00837 if (frame->depth() <= 8) {
00838 MsgLog(name(), warning, name() << ": frame data is 8 bit, not analyzing data");
00839 m_eventDump.returnReason(evt,"8bit_frame_data");
00840 return;
00841 }
00842
00843 m_pedestal = frame->offset();
00844
00845 frameData = frame->data16();
00846
00847 bool lfatal=false;
00848 for(unsigned i=0; i<2; i++) {
00849 if (m_sig_roi_hi[i] >= frameData.shape()[i]) {
00850 lfatal |= (m_projectX == (i==0));
00851 MsgLog(name(), warning,
00852 name() << ": signal " << (i==0 ? 'Y':'X') << " upper bound ["
00853 << m_sig_roi_hi[i] << "] exceeds frame bounds ["
00854 << frameData.shape()[i] << "].");
00855 m_sig_roi_hi[i] = frameData.shape()[i]-1;
00856 }
00857 if (m_sb_roi_hi[i] >= frameData.shape()[i]) {
00858 lfatal |= (m_projectX == (i==0));
00859 MsgLog(name(), warning,
00860 name() << ": sideband " << (i==0 ? 'Y':'X') << " upper bound ["
00861 << m_sb_roi_hi[i] << "] exceeds frame bounds ["
00862 << frameData.shape()[i] << "].");
00863 m_sb_roi_hi[i] = frameData.shape()[i]-1;
00864 }
00865 if (m_ref_roi_hi[i] >= frameData.shape()[i]) {
00866 lfatal |= (m_projectX == (i==0));
00867 MsgLog(name(), warning,
00868 name() << ": reference " << (i==0 ? 'Y':'X') << " upper bound ["
00869 << m_ref_roi_hi[i] << "] exceeds frame bounds ["
00870 << frameData.shape()[i] << "].");
00871 m_ref_roi_hi[i] = frameData.shape()[i]-1;
00872 }
00873 }
00874 if (lfatal)
00875 MsgLog(name(), fatal,
00876 name() << ": Fix bounds before proceeding.");
00877
00878
00879
00880
00881 if ((m_sig_roi_hi[0] == m_sig_roi_lo[0]) or (m_sig_roi_hi[1] == m_sig_roi_lo[1])) {
00882 MsgLog(name(), fatal, name() << ": signal ROI has a 0-length width or height. Set sig_roi_x and sig_roi_y config parameters.");
00883 }
00884 m_eventDump.arrayROI(m_sig_roi_lo, m_sig_roi_hi, pdim, "_sig", evt);
00885 sig = psalg::project(frameData,
00886 m_sig_roi_lo,
00887 m_sig_roi_hi,
00888 m_pedestal, pdim);
00889 m_eventDump.array(sig, evt, "_sig");
00890
00891
00892
00893
00894 if (use_sb_roi()) {
00895 m_eventDump.arrayROI(m_sb_roi_lo, m_sb_roi_hi, pdim, "_sb", evt);
00896 sb = psalg::project(frameData,
00897 m_sb_roi_lo ,
00898 m_sb_roi_hi,
00899 m_pedestal, pdim);
00900 m_eventDump.array(sb, evt, "_sb");
00901 }
00902
00903
00904
00905
00906 if (use_ref_roi()) {
00907 m_eventDump.arrayROI(m_ref_roi_lo, m_ref_roi_hi, pdim, "_ref", evt);
00908 ref = psalg::project(frameData,
00909 m_ref_roi_lo ,
00910 m_ref_roi_hi,
00911 m_pedestal, pdim);
00912 }
00913 }
00914
00915 ndarray<double,1> sigd = make_ndarray<double>(sig.shape()[0]);
00916 ndarray<double,1> refd = make_ndarray<double>(sig.shape()[0]);
00917
00918
00919
00920
00921 if (sb.size()) {
00922 psalg::rolling_average(sb, m_sb_avg, m_sb_avg_fraction);
00923 m_eventDump.array(m_sb_avg, evt, "_sb_avg");
00924
00925 ndarray<const double,1> sbc = psalg::commonModeLROE(sb, m_sb_avg);
00926 m_eventDump.array(sbc, evt, "_sb_commonMode");
00927
00928 if (use_ref_roi())
00929 for(unsigned i=0; i<sig.shape()[0]; i++) {
00930 sigd[i] = double(sig[i])-sbc[i];
00931 refd[i] = double(ref[i])-sbc[i];
00932 }
00933 else
00934 for(unsigned i=0; i<sig.shape()[0]; i++)
00935 sigd[i] = double(sig[i])-sbc[i];
00936 }
00937 else {
00938 if (use_ref_roi())
00939 for(unsigned i=0; i<sig.shape()[0]; i++) {
00940 sigd[i] = double(sig[i]);
00941 refd[i] = double(ref[i]);
00942 }
00943 else
00944 for(unsigned i=0; i<sig.shape()[0]; i++)
00945 sigd[i] = double(sig[i]);
00946 }
00947
00948
00949
00950
00951 bool lcut=true;
00952 for(unsigned i=0; i<sig.shape()[0]; i++)
00953 if (sigd[i]>m_proj_cut)
00954 lcut=false;
00955
00956 if (lcut) {
00957 MsgLog(name(), trace, name() << ": signal projection does not have minimum amplitude for laser presence based on proj_cut:" << m_proj_cut << ", returning from Event");
00958 m_eventDump.returnReason(evt,"fails_proj_cut");
00959 return;
00960 }
00961
00962 bool setInitial = setInitialReferenceIfUsingCalibirationDatabase(pdim);
00963 if (setInitial and !nobeam) {
00964
00965
00966 m_eventDump.frameRef(m_ref_frame_avg, evt);
00967 }
00968
00969 if (nobeam) {
00970 MsgLog(name(), trace, name() << ": Updating reference.");
00971 psalg::rolling_average(ndarray<const double,1>(use_ref_roi()? refd:sigd),
00972 m_ref_avg, m_ref_avg_fraction);
00973
00974 if (m_eventDump.doDump()) {
00975 local_rolling_average(frameData, m_ref_frame_avg, m_ref_avg_fraction, name());
00976 m_eventDump.frameRef(m_ref_frame_avg, evt);
00977 m_eventDump.array(use_ref_roi()?refd:sigd, evt, "_ref");
00978 }
00979
00980
00981
00982
00983
00984 if (!(m_analyze_event<0 || m_count<=m_analyze_event))
00985 std::copy(m_analyze_signal.begin(),
00986 m_analyze_signal.end(),
00987 sigd.begin());
00988 else {
00989 MsgLog(name(), trace, name() << " exiting early do to nobeam");
00990 m_eventDump.returnReason(evt, "nobeam");
00991 return;
00992 }
00993 }
00994 else if (use_ref_roi()) {
00995 psalg::rolling_average(ndarray<const double,1>(refd),
00996 m_ref_avg, m_ref_avg_fraction);
00997 }
00998
00999 if (m_ref_avg.size()==0) {
01000 MsgLog(name(), warning, name() << ": No reference.");
01001 m_eventDump.returnReason(evt, "no_reference");
01002 return;
01003 }
01004
01005 if (!(m_analyze_event<0)) {
01006
01007
01008
01009
01010 if (m_count==m_analyze_event) {
01011 if (!nobeam) {
01012 m_analyze_signal = make_ndarray<double>(sigd.size());
01013 std::copy(sigd.begin(), sigd.end(), m_analyze_signal.begin());
01014 } else {
01015 MsgLog(name(), error, name() << " analyze_event set, and this is the event count=" << m_count << " but there is no beam.");
01016 m_eventDump.returnReason(evt, "analyze_event_but_nobeam_for_event");
01017 }
01018 } else if (!nobeam) {
01019 MsgLog(name(), trace, name() << " analyze_event is set, but no beam");
01020 m_eventDump.returnReason(evt,"analyze_event_nobeam");
01021 return;
01022 }
01023 }
01024
01025 m_count++;
01026 m_eventDump.array(m_ref_avg, evt, "_ref_avg");
01027
01028
01029
01030
01031 for(unsigned i=0; i<sig.shape()[0]; i++)
01032 sigd[i] = sigd[i]/m_ref_avg[i] - 1;
01033
01034 m_eventDump.array(sigd, evt, "_sigd");
01035
01036
01037
01038 ndarray<double,1> qwf = psalg::finite_impulse_response(m_weights,sigd);
01039 m_eventDump.array(qwf, evt, "_qwf");
01040
01041 if (!m_hdump.empty() and m_hmgr) {
01042 DumpH& h = m_hdump.front();
01043 for(unsigned i=0; i<sig.shape()[0]; i++)
01044 h.hraw->fill(double(i)+m_sig_roi_lo[pdim],double(sig[i]));
01045 for(unsigned i=0; i<sig.shape()[0]; i++)
01046 h.href->fill(double(i)+m_sig_roi_lo[pdim],m_ref_avg[i]);
01047 for(unsigned i=0; i<sigd.shape()[0]; i++)
01048 h.hrat->fill(double(i)+m_sig_roi_lo[pdim],sigd[i]);
01049 for(unsigned i=0; i<qwf.shape()[0]; i++)
01050 h.hflt->fill(double(i)+m_sig_roi_lo[pdim],qwf[i]);
01051 m_hdump.pop_front();
01052 }
01053
01054
01055
01056
01057 const double afrac = 0.50;
01058 std::list<unsigned> peaks =
01059 psalg::find_peaks(qwf, afrac, 2);
01060
01061 unsigned nfits = peaks.size();
01062 if (nfits>0) {
01063 unsigned ix = *peaks.begin();
01064 ndarray<double,1> pFit0 = psalg::parab_fit(qwf,ix,0.8);
01065 if (pFit0[2]>0) {
01066 double xflt = pFit0[1]+m_sig_roi_lo[pdim]+m_frame_roi[pdim];
01067
01068 double xfltc = 0;
01069 for(unsigned i=m_calib_poly.size(); i!=0; )
01070 xfltc = xfltc*xflt + m_calib_poly[--i];
01071
01072 double nxtAmpl=0;
01073 if (nfits>1) {
01074 ndarray<double,1> pFit1 =
01075 psalg::parab_fit(qwf,*(++peaks.begin()),0.8);
01076 if (pFit1[2]>0)
01077 nxtAmpl = pFit1[0];
01078 }
01079
01080
01081 boost::shared_ptr<Psana::TimeTool::DataV2> timeToolEvtData =
01082 boost::make_shared<TimeToolData>(Psana::TimeTool::DataV2::Signal,
01083 pFit0[0],
01084 xflt,
01085 xfltc,
01086 pFit0[2],
01087 m_ref_avg[ix],
01088 nxtAmpl);
01089 evt.put(timeToolEvtData,m_put_key);
01090 MsgLog(name(), trace, name() << " added TimeToolData");
01091 m_eventDump.returnReason(evt, "success");
01092 } else {
01093 MsgLog(name(), trace, name() << " pfits <=0 , nodata");
01094 m_eventDump.returnReason(evt, "no_parab_fit");
01095 }
01096 } else {
01097 MsgLog(name(), trace, name() << " no peaks, no data");
01098 m_eventDump.returnReason(evt, "no_peaks");
01099 }
01100 }
01101
01102 bool
01103 Analyze::setInitialReferenceIfUsingCalibirationDatabase(unsigned pdim) {
01104 if (not m_use_calib_db_ref) return false;
01105 if (0 != m_ref_avg.size()) return false;
01106 if (use_ref_roi()) {
01107 MsgLog(name(), warning, name() << ": use_ref_roi is set, and use_calib_db_ref is true. not implemented");
01108 return false;
01109 }
01110
01111 ndarray<uint16_t,2> ref_frame_avg_uint16(m_ref_frame_avg.shape());
01112 for (unsigned row = 0; row < m_ref_frame_avg.shape()[0]; row++) {
01113 for (unsigned col = 0; col < m_ref_frame_avg.shape()[1]; col++) {
01114 double origVal = m_ref_frame_avg[row][col];
01115 uint16_t uintVal = uint16_t(origVal);
01116 if ((origVal > UINT16_MAX) or (origVal < 0)) {
01117 MsgLog(name(), warning, name() << ": ref_frame_avg[" << row << "][" << col << "] has value outside 16 bit unsigned integer bounds. Clamping");
01118 if (origVal > UINT16_MAX) {
01119 uintVal = UINT16_MAX;
01120 } else if (origVal < 0) {
01121 uintVal = 0;
01122 }
01123 }
01124 ref_frame_avg_uint16[row][col] = uintVal;
01125 }
01126 }
01127
01128 ndarray<const uint16_t,2> ref_frame_avg_const_uint16(ref_frame_avg_uint16);
01129
01130 ndarray<const int,1> ref_avg = psalg::project(ref_frame_avg_const_uint16,
01131 m_sig_roi_lo,
01132 m_sig_roi_hi,
01133 m_pedestal, pdim);
01134
01135 m_ref_avg = ndarray<double,1>(ref_avg.shape());
01136 for (unsigned i = 0; i < ref_avg.shape()[0]; ++i) {
01137 m_ref_avg[i]=double(ref_avg[i]);
01138 }
01139
01140 return true;
01141 }
01142
01143
01144 void
01145 Analyze::endCalibCycle(Event& evt, Env& env)
01146 {
01147 }
01148
01149
01150 void
01151 Analyze::endRun(Event& evt, Env& env)
01152 {
01153 }
01154
01155
01156 void
01157 Analyze::endJob(Event& evt, Env& env)
01158 {
01159 if (!m_ref_store.empty()) {
01160 std:: ofstream f(m_ref_store.c_str());
01161 for(unsigned i=0; i<m_ref_avg.size(); i++)
01162 f << m_ref_avg[i] << ' ';
01163 f << std::endl;
01164 }
01165 }
01166
01167 }
01168