ICP  1
ISISinstrumentControl.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "isiscrpt.h"
4 #include "isisraw.h"
5 //#include "md5.h"
6 #include "labview_xml.h"
7 #include "icputils.h"
8 #include "nexuswriter.h"
9 #include "../svn-revision.h"
10 #include "ci_string.h"
11 #include "muParser.h"
12 #include "windows.h"
13 #include "DetectorFile.h"
15 
16 #define ISISDAE_MAX_DAE2TIMECHAN 65500
17 
18 #define LV_NUM_TIME_REGIMES 6
19 
20 static const char* star_line80 = "********************************************************************************\n";
21 static const char* hash_line80 = "################################################################################\n";
22 
23 static void nxErrorFunc(void* arg, char* text)
24 {
25  DAEstatus* pStatus = (DAEstatus*)arg;
26  pStatus->addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "NEXUS ERROR: %s", text);
27 }
28 
29 int ISISinstrumentControl::readTables(const char* wiring, const char* detector, const char* spectra, DAEstatus& status)
30 {
31  static const std::string data_dae = m_app->config().getString("isisicp.datadae.file", "c:\\labview modules\\dae\\data_dae.xml");
32  static const bool do_data_dae = m_app->config().getBool("isisicp.datadae.use", false);
33  m_crpt->tables_valid = 0;
34  m_crpt->n_data_dae = 0;
35  if (readWiringTable(wiring, status) == DAEstatus::Failure)
36  {
37  return DAEstatus::Failure;
38  }
39  if (readDetectorTable(detector, status) == DAEstatus::Failure)
40  {
41  return DAEstatus::Failure;
42  }
43  if (readSpectraTable(spectra, status) == DAEstatus::Failure)
44  {
45  return DAEstatus::Failure;
46  }
47  if ( do_data_dae && (readDataDaeTable(data_dae.c_str(), status) == DAEstatus::Failure) )
48  {
49  return DAEstatus::Failure;
50  }
51  m_crpt->tables_valid = 1;
52  return DAEstatus::Success;
53 }
54 
56 {
57  Poco::NotificationCenter& notify_centre = Poco::NotificationCenter::defaultCenter();
58  notify_centre.removeObserver(Poco::Observer<ICPNotificationHandler,ICPNotification>(m_nh,&ICPNotificationHandler::handleNotification));
59  const Poco::AbstractObserver& on_progress = Poco::Observer<ICPProgressHandler, Poco::TaskProgressNotification>(m_task_ph, &ICPProgressHandler::onProgress);
60  const Poco::AbstractObserver& on_finished = Poco::Observer<ICPProgressHandler, Poco::TaskFinishedNotification>(m_task_ph, &ICPProgressHandler::onFinished);
61  m_taskmgr.removeObserver(on_progress);
62  m_taskmgr.removeObserver(on_finished);
63 // m_beam_current_timer.stop(); // seems to deadlock
64 
65  if (m_http_server != NULL)
66  {
67  m_http_server->stop();
68  delete m_http_server;
69  }
70 
72  m_shutdown_requested = true;
73  Sleep(5000);
74  if (se_close() != 0)
75  {
76  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
77  }
78  delete m_dae;
79  m_dae = 0;
81  CloseHandle(m_async_complete_event);
82  DeleteCriticalSection(&m_crpt_cs);
83  delete m_icp_config;
84 }
85 
86 static const char* muon_daes[] = { "NDXMUSR", "NDXEMU", "NDXHIFI", "NDXCHRONUS", "NDXARGUS" };
87 
88 void ISISinstrumentControl::seTransFunction(unsigned int u, EXCEPTION_POINTERS* pExp)
89 {
90  throw Win32StructuredException(u, pExp);
91 }
92 
94 {
95  // int *nullp = NULL; *nullp = 10; // force an access violation - as we are in "C" maybe C++ exceptions not allowed?
96  poco_bugcheck();
97  // poco_bugcheck() should throw an exception if no debugger is found, but add next line just in case
98  throw std::runtime_error("ISISinstrumentControl::purecallHandler()");
99 }
100 
103 {
105  {
106  return _set_se_translator(seTransFunction);
107  }
108  else
109  {
110  return NULL;
111  }
112 }
113 
115 {
117  {
118  _set_se_translator(old_func);
119  }
120 }
121 
122 ISISinstrumentControl::ISISinstrumentControl(Poco::Util::Application* pApp, const std::string& icp_service_dir, DAEreport_func_t* func, write_event_log_t* event_func, void* report_arg) : Base(), m_icp_service_dir(icp_service_dir), m_dae(0),
123  m_shutdown_requested(false), m_period_error(false), m_nexus_files(false), m_vms_raw_files(true), m_use_full_inst_name_for_files(true),
124  m_icp_options(0),m_event_log_func(event_func),m_num_async_requests(0),m_async_complete_event(NULL),m_app(pApp),
125  m_beam_current_timer(5 * 1000, 5 * 1000), m_simulation_mode(false), m_registersetranslator(false)
126 {
127  int i;
128  DWORD len_comp_name = MAX_COMPUTERNAME_LENGTH + 1;
129  char comp_name[MAX_COMPUTERNAME_LENGTH + 1];
130  std::string mess;
131  char time_buffer[128];
132 
133  setLoggerName("InstCtrl");
134 
135  if ( m_app->config().getBool("isisicp.registerpurecallhandler", false) )
136  {
137  LOGSTR_INFORMATION("Registering \"purecall\" handler");
138  _set_purecall_handler(purecallHandler);
139  }
140  _se_translator_function old_se_trans = NULL;
141  if ( m_app->config().getBool("isisicp.registersetranslator", false) )
142  {
143  LOGSTR_INFORMATION("Using win32 \"Structured Exception translator\" function");
144  m_registersetranslator = true;
145  old_se_trans = registerStructuredExceptionHandler();
146  }
147 
148  srand(static_cast<unsigned>(time(NULL)));
149 
150  time(&m_icp_start_time);
151 
152  Poco::ThreadPool::defaultPool().addCapacity(50);
153 
154  const Poco::AbstractObserver& on_progress = Poco::Observer<ICPProgressHandler, Poco::TaskProgressNotification>(m_task_ph, &ICPProgressHandler::onProgress);
155  const Poco::AbstractObserver& on_finished = Poco::Observer<ICPProgressHandler, Poco::TaskFinishedNotification>(m_task_ph, &ICPProgressHandler::onFinished);
156  m_taskmgr.addObserver(on_progress);
157  m_taskmgr.addObserver(on_finished);
158 
159  GetComputerName(comp_name, &len_comp_name);
160  comp_name[len_comp_name] = '\0';
161 
162  m_comp_name = comp_name;
163 
164  m_icp_dir = m_icp_service_dir + "\\..\\..\\.."; // remove the "x64\release" bit of path (should be same as PLATFORM_SUFFIX)
165 
166  m_data_dir = "c:\\data";
167  m_log_dir = m_data_dir + "\\log";
168 
169  CoInitializeEx(NULL, COINIT_MULTITHREADED);
170 
171  LOG_INFORMATION("startup");
172 
173  // emergency defaults until assignICPLogFiles() is called properly
174  mkdir(m_data_dir.c_str());
175  mkdir(m_log_dir.c_str());
176  m_crpt.assignLogFiles(m_log_dir + "\\startup");
177 
178  // this is used in lockCRPT() and unlockCRPT()
179  InitializeCriticalSection(&m_crpt_cs);
180 
181  SECURITY_ATTRIBUTES sec_attr = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
182  m_async_complete_event = CreateEvent(&sec_attr, FALSE, FALSE, NULL);
183 
184  ISOtime(time(NULL), time_buffer, sizeof(time_buffer));
185 
187  m_status.addInfoVa(FAC_CRPT, "ISIS ICP Starting from %s at %s\n", m_icp_service_dir.c_str(), time_buffer);
188  m_status.addInfoVa(FAC_CRPT, "SVN revision %s (%s, %s %s, %s)\n", ICPSVN_Revision.c_str(), ICPSVN_Date.c_str(), ICPSVN_Mixed.c_str(), ICPSVN_Range.c_str(), ICPSVN_Modified.c_str());
189  m_status.addInfoVa(FAC_CRPT, "SVN Source repository %s\n", ICPSVN_URL.c_str());
190  m_status.addInfoVa(FAC_CRPT, "SELOGGER with %s\n", se_version());
191 
192  // stop the DAE server process and start it in suspended state. We do this so that we do not inherit too many handles from ISISICP
194  HANDLE datasvr_thread = launchDatasvr(m_status);
195 
197  Poco::Path icp_config_path(m_icp_dir, "icp_config.xml");
198  std::string icp_config_file = icp_config_path.absolute().toString();
199  LOGSTR_INFORMATION("Loading ICP config from \"" << icp_config_file << "\"");
200  if (m_icp_config->loadFromFile(icp_config_file.c_str(), m_status) == DAEstatus::Failure)
201  {
202  mess = "*** ISIS ICP STARTUP FAILED (cannot load " + icp_config_file + ") ***";
203  exitProgram(mess, true);
204  }
205  std::string tempstr;
206  if (m_icp_config->getValue("InstDataDir", tempstr, m_status) == DAEstatus::Success)
207  {
208  m_data_dir = tempstr;
209  }
210  else
211  {
212  m_data_dir = "c:\\data";
213  }
214  if (m_icp_config->getValue("InstLogDir", tempstr, m_status) == DAEstatus::Success)
215  {
216  m_log_dir = tempstr;
217  }
218  else
219  {
220  m_log_dir = m_data_dir + "\\log";
221  }
222  mkdir(m_data_dir.c_str());
223  mkdir(m_log_dir.c_str());
224 
225  m_recovery_file = m_data_dir + "\\recovery.run";
226 
227  m_status.setReportFunction(func, report_arg);
229  m_report_func = func;
230  m_report_arg = report_arg;
231 
232  // sendSMS("07766422175", "icp starting", m_status);
233 
234  Poco::NotificationCenter& notify_centre = Poco::NotificationCenter::defaultCenter();
235  notify_centre.addObserver(Poco::Observer<ICPNotificationHandler,ICPNotification>(m_nh,&ICPNotificationHandler::handleNotification));
236 
237  if (ISISRAW::size_check() == -1)
238  {
239  mess = "*** ISIS ICP STARTUP FAILED (raw size mismatch) ***";
240  exitProgram(mess, true);
241  }
243  // determine DAE type
245  for(i=0; i<sizeof(muon_daes) / sizeof(const char*); i++)
246  {
247  if (stricmp(m_comp_name.c_str(), muon_daes[i]) == 0)
248  {
250  }
251  }
252  if (m_icp_config->getValue("DAEType", i, m_status) == DAEstatus::Success)
253  {
255  }
256  m_status.addInfoVa(FAC_CRPT, "Setting DAE type to %s on %s", ISISDAE::DAEType_desc[m_dae_type], m_comp_name.c_str());
257  if (m_dae_type == ISISDAE::MuonDAE2 || m_dae_type == ISISDAE::MuonDAE3)
258  {
259  m_nexus_files = true;
260  m_vms_raw_files = false;
263  }
264  else if (m_dae_type == ISISDAE::NeutronDAE2 || m_dae_type == ISISDAE::NeutronDAE3)
265  {
266  m_use_full_inst_name_for_files = false; // use inst_abrv instead
267  m_nexus_files = false;
268  m_vms_raw_files = true;
270  }
271  else
272  {
273  m_status.addInfoVa(FAC_CRPT, "Unknown DAE type %d", m_dae_type);
274  mess = "*** ISIS ICP STARTUP FAILED (Cannot determine DAE Type) ***";
275  exitProgram(mess, true);
276  }
277  if (m_icp_config->getValue("NeXusFiles", i, m_status) == DAEstatus::Success)
278  {
279  m_nexus_files = (i == 1 ? true : false);
280  }
281  if (m_icp_config->getValue("VMSRawFiles", i, m_status) == DAEstatus::Success)
282  {
283  m_vms_raw_files = (i == 1 ? true : false);
284  }
285  if (m_icp_config->getValue("InstSettingsDir", tempstr, m_status) == DAEstatus::Success)
286  {
287  m_inst_settings_dir = tempstr;
288  }
289  else
290  {
291  m_inst_settings_dir = "c:\\labview modules\\dae";
292  }
293  if (m_icp_config->getValue("RunDigits", i, m_status) == DAEstatus::Success)
294  {
296  }
297  if (m_run_number_digits > 5)
298  {
299  m_use_full_inst_name_for_files = true; // change the default
300  }
301  if (m_icp_config->getValue("UseFullInstNameForFiles", i, m_status) == DAEstatus::Success)
302  {
303  m_use_full_inst_name_for_files = (i == 1 ? true : false);
304  }
305  if (m_icp_config->getValue("AutoSave", i, m_status) == DAEstatus::Success)
306  {
307  if (i != 0)
308  {
310  }
311  else
312  {
314  }
315  }
316  if (m_icp_config->getValue("PeriodSequenceAutoEnd", i, m_status) == DAEstatus::Success)
317  {
318  if (i != 0)
319  {
321  }
322  else
323  {
325  }
326  }
327  if (m_icp_config->getValue("PerCycleJournal", i, m_status) == DAEstatus::Success)
328  {
329  if (i != 0)
330  {
332  }
333  else
334  {
336  }
337  }
338 
339  m_status.addInfoVa(FAC_CRPT, "Run digits = %d", m_run_number_digits);
341  m_simulation_mode = false;
342  if (m_icp_config->getValue("Simulate", i, m_status) == DAEstatus::Success)
343  {
344  m_simulation_mode = (i == 1 ? true : false);
345  }
346  bool endian_workaround = true;
347  if (m_icp_config->getValue("VXIType", i, m_status) == DAEstatus::Success)
348  {
349  if (i == 1)
350  {
351  endian_workaround = false;
352  }
353  }
354  m_dae = new ISISDAE(m_dae_type, m_status, endian_workaround, m_simulation_mode);
355  // we used to have "DAEDevice" - now we have "DAEDevice0", "DAEDevice1" etc.
356  // check for new names and, if none found, try old name
357  char dae_tag[60];
358  std::string dae_device;
359  bool dae_found = false;
360  for(i=0; i < 256; i++)
361  {
362  _snprintf(dae_tag, sizeof(dae_tag), "DAEDevice%d", i);
363  if (m_icp_config->getValue(dae_tag, dae_device, m_status) == DAEstatus::Success)
364  {
365  dae_found = true;
366  m_dae->open(dae_device.c_str(), m_status);
367  }
368  else
369  {
370  break;
371  }
372  }
373  if (!dae_found) // look for old format string
374  {
375  if (m_icp_config->getValue("DAEDevice", dae_device, m_status) == DAEstatus::Failure)
376  {
377  dae_device = "ISISDAE0";
378  }
379  m_dae->open(dae_device.c_str(), m_status);
380  }
381  if (m_icp_config->getValue("DAEBackplane", dae_device, m_status) == DAEstatus::Success)
382  {
383  m_dae->openBackplane(dae_device.c_str(), m_status);
384  }
385  m_dae->check(m_status);
386  bool noinit = false;
387  if (m_icp_config->getValue("SkipInit", i, m_status) == DAEstatus::Success)
388  {
389  noinit = (i == 1 ? true : false);
390  }
391  if (m_status >= SEV_FATAL)
392  {
393  mess = "*** ICP failed to start - your DAE may be switched OFF or is missing cards ***\r\n"
394  "*** Please check " + m_log_dir + "\\icp-*.log and " + m_crpt.debugLog() + " ***";
395  exitProgram(mess, true);
396 // noinit = true;
397  }
398 
399  // load CRPT from disk
400  // we need to do this after VISA is loaded or we seem to get problems with address mapping
401  ICPCritical cs(&m_crpt_cs);
402  float temp_f;
403  if (m_icp_config->getValue("MinTCBWidth", temp_f, m_status) == DAEstatus::Success)
404  {
405  std::string res = Poco::format("ISISICP_MIN_TCBWIDTH=%f", static_cast<double>(temp_f));
406  putenv(res.c_str());
407  }
408  if ( (loadCRPT() == DAEstatus::Failure) || !m_crpt.isValid())
409  {
410  mess = "ICP failed to start - " + m_data_dir + "\\CURRENT.RUN is either corrupt or locked out by another process; check " + m_log_dir + "\\icp*.log and " + m_crpt.debugLog();
411  exitProgram(mess, true);
412  }
413 
415 
416  // maybe impersonate a different instrument to one based on our computer name
417  if (m_icp_config->getValue("InstName", tempstr, m_status) == DAEstatus::Success)
418  {
419  m_crpt->setInstName(tempstr);
420  }
421 
424 
425  // now we have a proper CRPT, we can get proper log filenames
427 
428  // sync ICP clock to CRPT
429  ICPClock* icp_clock = g_icp_clock.get();
431 
432  FILETIME icp_ft, system_ft;
433  icp_clock->getCurrentTimeAsFiletime(icp_ft);
434  GetSystemTimeAsFileTime(&system_ft);
435  m_status.addInfoVa(FAC_DAE, "icp - system time in millisec = %f", diffFileTimesInMilliSec(system_ft, icp_ft));
436 
437  m_crpt->setDAESpecificParameters(); // @todo this can almost be removed as done when crpt rebuilt
438  // Only issue is checking ISISICP_MIN_TCBWIDTH env variable
439 
440  strncpy(m_crpt->comp_name, m_comp_name.c_str(), sizeof(m_crpt->comp_name));
442 
443  if (m_icp_config->getValue("AlertEmail", m_crpt->alert_email, sizeof(m_crpt->alert_email), true, m_status) == DAEstatus::Failure)
444  {
445  m_crpt->alert_email[0] = '\0';
446  }
448  {
449  m_crpt->uamp_scale = 1.0;
450  }
453  {
455  }
457  {
459  }
460  m_crpt_run = new CRPTProxy();
461  m_crpt_run->createFrom(m_crpt, m_crpt->run_number, true, m_status);
462  cs.unlock();
463 // se_profile("c:\\faa.log");
465  {
466  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
467  }
469  {
470  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
471  }
472 
473  logEventVa(m_crpt, m_status, "ICP_STARTUP_SUCCESS - SVN revision %s (%s, %s %s, %s)", ICPSVN_Revision.c_str(), ICPSVN_Date.c_str(), ICPSVN_Mixed.c_str(), ICPSVN_Range.c_str(), ICPSVN_Modified.c_str());
474  _snprintf(m_crpt->icp_version, sizeof(m_crpt->icp_version), "SVN R%s (%s, %s %s, %s)", ICPSVN_Revision.c_str(), ICPSVN_Date.c_str(), ICPSVN_Mixed.c_str(), ICPSVN_Range.c_str(), ICPSVN_Modified.c_str());
476  if (noinit)
477  {
478  m_status.addInfo(FAC_DAE, "Started DAE in NOINIT mode");
479  }
480  else
481  {
483  {
485  setupDAE(1, m_status);
487  }
488  else
489  {
490  setupDAE(1, m_status);
491  }
492  _beginthread(updateThread, 0, this);
493  Poco::TimerCallback<ISISinstrumentControl>* beam_current_callback = new Poco::TimerCallback<ISISinstrumentControl>(*this, &ISISinstrumentControl::beamCurrentTimerCallback);
494 // m_beam_current_timer.start(*beam_current_callback); // seems to deadlock on exit
495  }
496  ISOtime(time(NULL), time_buffer, sizeof(time_buffer));
497 
498  // now set data server running
499  ResumeThread(datasvr_thread);
500  CloseHandle(datasvr_thread);
501 
502  // need to keep a list of these connections to remove? std::list<boost::signals2::connection>
503 // m_dae->addGoodEventCallback(boost::bind(&CRPTProxy::histogramEventsToCRPT, boost::ref(m_crpt), _1, _2, _3, _4));
504  m_crpt_signals = m_dae->addGoodEventCallback(boost::bind(&CRPTProxy::histogramEventsToCRPT, boost::ref(m_crpt), boost::ref(*m_crpt_run), _1, _2, _3, _4));
505 
509 
510  Poco::RunnableAdapter<ISISinstrumentControl>* ra = new Poco::RunnableAdapter<ISISinstrumentControl>(*this, &ISISinstrumentControl::readBeamloggerBroadcast); // a memory leak, but only once - avoids race condition
511  m_beamlog_thread.start(*ra);
512 
513  bool enable_web_server = m_app->config().getBool("isisicp.services.web", true);
514  if (enable_web_server)
515  {
516  Poco::UInt16 http_server_port = m_app->config().getInt("isisicp.services.web.port", 10999);
517  Poco::Net::HTTPServerParams* http_params = new Poco::Net::HTTPServerParams;
518  http_params->setMaxQueued(100);
519  http_params->setMaxThreads(5);
520  m_http_svs = new Poco::Net::ServerSocket(http_server_port);
521  m_http_server = new Poco::Net::HTTPServer(new ICPRequestHandlerFactory(m_crpt.CRPT()), *m_http_svs, http_params);
522  m_http_server->start();
523  }
524  else
525  {
526  m_http_svs = NULL;
527  m_http_server = NULL;
528  }
529 
530  // look for previous failed ends
531  if ( m_app->config().getBool("isisicp.failedends.rerun", false) )
532  {
533  rerunFailedEnds();
534  }
535  m_status.addInfoVa(FAC_CRPT, "***\n*** ISIS ICP STARTUP COMPLETE %s, current run number %d, status is %s\n***",
536  time_buffer, m_crpt->run_number, m_crpt->runStatusName());
538  if (strlen(m_crpt->epics_lastread_iso) == 0)
539  {
542  }
547  if (m_app->config().getBool("isisicp.epicsdb.use", false))
548  {
550  }
551 }
552 
554 {
555  // need to be able to load crpt read-only
556  // also missing se blocks?
557  std::set<std::string> files;
558  Poco::Path search_expr("c:\\data\\current.run[0-9]?[0-9]*"); // poco glob is shell like not RE like
559  Poco::Glob::glob(search_expr, files, Poco::Glob::GLOB_CASELESS);
560  Poco::RegularExpression re("current.run([0-9]+)", Poco::RegularExpression::RE_CASELESS);
561  Poco::RegularExpression::MatchVec matches;
562  Poco::SharedPtr<Poco::Event> finish_event(new Poco::Event);
563  BOOST_FOREACH(const std::string& file, files)
564  {
565  re.match(file, 0, matches);
566  if (matches.size() == 2)
567  {
568  int run_num = Poco::NumberParser::parse(file.substr(matches[1].offset, matches[1].length));
569  if ( run_num != m_crpt->run_number )
570  {
571  m_status.addInfoVa(FAC_CRPT, "Re-ending run %d", run_num);
572  Poco::SharedPtr<CRPTProxy> prev_run(new CRPTProxy());
573  prev_run->loadCRPT(Poco::format("c:\\data\\current.run%d", run_num).c_str(),
574  Poco::format("c%d", run_num).c_str(),
575  Poco::format("c:\\data\\data.run%d", run_num).c_str(),
576  Poco::format("d%d", run_num).c_str(), m_crpt.rawDataSizeMax(), false, m_status);
577  if ( prev_run->CRPT() != NULL )
578  {
579  GenericTask<int>* end_task = new GenericTask<int>(Poco::format("rerunFailedEnds %d", run_num), finish_event,
580  boost::bind(&ISISinstrumentControl::endRunTask, this, prev_run,
581  boost::ref(m_nxwriter),
582  m_app->config().getBool("isisicp.failedends.keepfiles", false),
583  m_app->config().getBool("isisicp.failedends.keepfiles", false),
584  "",
585  boost::ref(m_status)));
586  m_taskmgr.start(end_task);
587  }
588  else
589  {
590  LOGSTR_ERROR("Unable to reload CRPT to re-end run " << run_num);
591  }
592  }
593  }
594  }
595 }
596 
597 int ISISinstrumentControl::writeWinEventLog(int sev, const std::string& message)
598 {
599  if (m_event_log_func != NULL)
600  {
601  return (*m_event_log_func)(sev, message.c_str(), m_report_arg);
602  }
603  else
604  {
605  return 0;
606  }
607 }
608 
610 {
611  int poll_time = 0;
613  DAEstatus& dstatus = ic->getStatusReporter();
614  _se_translator_function old_se_trans = ic->registerStructuredExceptionHandler();
615  while(!ic->shutdownRequested())
616  {
617  poll_time = ic->getPollTime();
618  if (poll_time > 0)
619  {
620  Sleep(poll_time * 1000);
621  try
622  {
623  ic->updateFunc(poll_time, false);
624  }
625  catch(const std::exception& ex)
626  {
627  dstatus.addWarningVa(FAC_DAE, "Exception in updateThread: %s", ex.what());
628  }
629  }
630  else
631  {
632  Sleep(5 * 1000);
633  }
634  }
635  ic->unregisterStructuredExceptionHandler(old_se_trans);
636 }
637 
638 
639 // load existing CRPT from disk and create mapped section
641 {
642  int crpt_data_size;
643  if (m_icp_config->getValue("CRPTSize", crpt_data_size, m_status) == DAEstatus::Failure)
644  {
645  crpt_data_size = 200 * 1000 * 1000; // 800Mb roughly
646  }
647  std::string crpt_file = m_data_dir + "\\current.run";
648  std::string crpt_data_file = m_data_dir + "\\data.run";
649  std::string crpt_name = "isis_current";
650  std::string crpt_data_name = "isis_data";
651  return m_crpt.loadOrCreateCRPT(crpt_file, crpt_name, crpt_data_file, crpt_data_name, crpt_data_size, m_dae_type, m_comp_name,
652  boost::bind(&ISISinstrumentControl::readRecoveryFile, this, _1), m_status);
653 }
654 
655 int ISISinstrumentControl::flushCRPT(DAEstatus& status, bool flush_raw_data)
656 {
657 // status.addDebugVa(FAC_CRPT, "Flushing %d bytes of CRPT", nbytes);
658 // ICPCritical cs(&m_crpt_cs);
659  return m_crpt.flushCRPT(status, flush_raw_data);
660 }
661 
662 int ISISinstrumentControl::changePeriodWhileRunning(int period, bool pause_first, DAEstatus& status)
663 {
664  bool did_pause = false;
665  ICPCritical cs(&m_crpt_cs);;
666  if (pause_first && m_crpt->run_status != RUNSTATUS_PAUSED && m_crpt->run_status != RUNSTATUS_SETUP)
667  {
668  pauseRunMain(false, status); // do not update cache to save time; alos we get called from updateFunc
669  did_pause = true;
670  }
671  changePeriod(period, status);
672  if (did_pause)
673  {
674  resumeRun(status);
675  }
676  return DAEstatus::Success;
677 }
678 
680 {
681  ICPCritical cs(&m_crpt_cs);
683  {
684  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change period in PAUSED or SETUP state");
685  return DAEstatus::Failure;
686  }
687  if (period < 0 || period >= m_crpt->nper)
688  {
689  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "period %d is invalid\n", period+1);
690  return DAEstatus::Failure;
691  }
693  {
694  return DAEstatus::Success;
695  }
696 // int per, daq_per;
697 // getCurrentPeriodNumber(per, daq_per, status);
698 // if (period != per)
699 // {
700  int daq_period = getDAQPeriod(period, status);
701  m_dae->changePeriod(period, daq_period, status);
703  {
704  m_crpt->software_period = period;
705  if (period != daq_period)
706  {
707  status.addWarningVa(FAC_CRPT, "Software period mismatch %d != %d\n", period, daq_period);
708  }
709  }
710 // }
711 // else
712 // {
713 // status.addInfoVa(FAC_CRPT, "Already in period %d\n", period+1);
714 // }
715  if (se_set_period_async(period) != 0)
716  {
717  status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
718  }
719  logEventVa(m_crpt, status, "CHANGE_PERIOD %d", period+1);
720  // what to do if we had changed period while monitoring was out of range?
721  m_crpt->monitoring.return_period = -1; // period
722  refreshCachedValues(status);
723  return DAEstatus::Success;
724 }
725 
726 int ISISinstrumentControl::startDataCollection(bool clear_counters, DAEstatus& status)
727 {
728  ICPCritical cs(&m_crpt_cs);
729  LOGSTR_DEBUG("startDataCollection");
730  int period, daq_period;
731  getCurrentPeriodNumber(period, daq_period, status);
732  PERIOD& p = m_crpt->period[period];
733  int irf, igf;
734  float goodua;
735  if (clear_counters)
736  {
737  irf = igf = 0;
738  goodua = 0.0;
739  }
740  else
741  {
742  irf = getRawFrames(status);
743  igf = getGoodFrames(status);
744  goodua = getGoodUAmpH(status);
745  }
746  m_dae->startRun(clear_counters, m_crpt->run_number, m_crpt->resume_time, status);
747  if (p.start_time == 0) // 0 means first time this period has started
748  {
750  }
751  logEventVa(m_crpt->resume_time, m_crpt, status, "START_COLLECTION PERIOD %d GF %d RF %d GUAH %f",
752  period + 1, igf, irf, goodua);
753  return 0;
754 }
755 
757 {
758  LOGSTR_DEBUG("stopDataCollection");
759  isisU32_t value32;
760  int i;
761  ICPCritical cs(&m_crpt_cs);;
762  ICPTimer icptimer1;
763  m_dae->stopRun(mode, status);
764  m_dae->disableDelayedStart(status);
765 
766  // force an update so if people do GET("IRPB") the latest values are returned
767  // we do this here rather than at the end as decisions are made based on isRunning()
768  // for the interpretation of various crpt items in the updateFunc() and those decisions
769  // are valid at this point
770 
771  // now done in relevant commands
772  // refreshCachedValues(status);
773 
774  int period, daq_period;
775  getCurrentPeriodNumber(period, daq_period, status);
776  m_dae->getCurrentPeriodSequence(&value32, status);
777  m_crpt->nperseq = value32;
778  status.addInfoVa(FAC_DAE, "Run stopped in period %d (DAQ %d), sequence %d", period+1, daq_period+1, value32);
779  PERIOD* p = &(m_crpt->period[period]);
780  time(&(m_crpt->stop_time));
781  time_t dur = 0;
782  if (m_crpt->resume_time != 0)
783  {
785  }
786  m_crpt->duration += dur;
787  p->stop_time = m_crpt->stop_time;
788  p->duration += dur;
789  isisU32_t igf, irf;
790  m_dae->getGoodFrames(&igf, status);
791  m_dae->getRawFrames(&irf, status);
792  p->good_frames += (igf - m_crpt->good_frames);
793  p->total_frames += (irf - m_crpt->total_frames);
794  m_crpt->good_frames = igf;
795  m_crpt->total_frames = irf;
796  float goodua = m_dae->getGoodUAmpHours(status);
797  float totalua = m_dae->getRawUAmpHours(status);
798  p->good_uamph += (goodua - m_crpt->good_uamph);
799  p->total_uamph += (totalua - m_crpt->total_uamph);
800 
801  logEventVa(m_crpt->stop_time, m_crpt, status, "STOP_COLLECTION PERIOD %d GF %d RF %d GUAH %f DUR %d",
802  period + 1, igf, irf, goodua, dur);
803  status.addInfoVa(FAC_DAE, "Good/Total uAH = %f / %f", goodua, totalua);
804  m_crpt->good_uamph = goodua;
805  m_crpt->total_uamph = totalua;
811  {
812  for(i=0; i<m_crpt->nper; i++)
813  {
814  p = &(m_crpt->period[i]);
815  m_dae->getRawFramesPeriod(&irf, i, status);
816  m_dae->getGoodFramesPeriod(&igf, i, status);
817  p->good_frames = igf;
818  p->total_frames = irf;
819  p->good_uamph = m_dae->getGoodUAmpHoursPeriod(i, status);
820  p->total_uamph = m_dae->getRawUAmpHoursPeriod(i, status);
821  }
822  }
823  m_dae->getSMPVetoedFrames(&(m_crpt->vetos[SMPVeto].frames), status);
824  m_dae->getMSModeVetoedFrames(&(m_crpt->vetos[MSModeVeto].frames), status);
825  m_dae->getExternalVetoedFrames(0, &(m_crpt->vetos[Ext0Veto].frames), status);
826  m_dae->getExternalVetoedFrames(1, &(m_crpt->vetos[Ext1Veto].frames), status);
827  m_dae->getExternalVetoedFrames(2, &(m_crpt->vetos[Ext2Veto].frames), status);
828  m_dae->getExternalVetoedFrames(3, &(m_crpt->vetos[Ext3Veto].frames), status);
829  m_dae->getFIFOVetoedFrames(&(m_crpt->vetos[FIFOVeto].frames), status);
830  m_dae->getTS2PulseVetoedFrames(&(m_crpt->vetos[TS2PulseVeto].frames), status);
831  m_dae->getISIS50HzVetoedFrames(&(m_crpt->vetos[ISIS50HzVeto].frames), status);
832 
833  icptimer1.info("stopDataCollection()", status);
834 
835  return 0;
836 }
837 
838 #define MAX_RC_RETRY 5
839 
840 
841 int ISISinstrumentControl::RCretry(const char* name, boost::function<int(ISISinstrumentControl*,DAEstatus&)> func, DAEstatus& status)
842 {
843  int i, stat = DAEstatus::Failure;
844  for(i=1; i <= MAX_RC_RETRY; i++)
845  {
846  try
847  {
849  stat = func(this, status);
850  if (status.OK())
851  {
852  break;
853  }
854  Sleep(1000);
855  }
856  catch(const std::exception& ex)
857  {
858  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Exception in RCretry(%s, attempt %d): %s", name, i, ex.what());
859  }
860  catch(...)
861  {
862  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Exception in RCretry(%s, attempt %d): unknown", name, i);
863  }
864  }
865  if (i > 1)
866  {
867  status.addWarningVa(FAC_DAE, "%s was tried %d times", name, i);
868  }
869  return stat;
870 }
871 
872 
874 {
875  return RCretry("BEGIN", boost::bind(&ISISinstrumentControl::beginRunMain, _1, _2), status);
876 }
877 
878 int ISISinstrumentControl::beginRunEx(bool start_paused, bool delayed_start, long period, DAEstatus& status)
879 {
880  return RCretry("BEGIN", boost::bind(&ISISinstrumentControl::beginRunMainEx, _1, start_paused, delayed_start, period, _2), status);
881 }
882 
884 {
885  return beginRunMainEx(false, false, -1, status);
886 }
887 
888 // period = -1 means do not reset period
889 int ISISinstrumentControl::beginRunMainEx(bool start_paused, bool delayed_start, long period, DAEstatus& status)
890 {
891  int i;
893  {
894  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only BEGIN in SETUP state");
895  return DAEstatus::Failure;
896  }
897  if (!m_crpt->isInitialised())
898  {
899  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "CRPT is not initialised - please set experiment parameters");
900  return DAEstatus::Failure;
901  }
902  if ( !m_crpt->tables_valid )
903  {
904  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot BEGIN run - current combination of wiring, detector and spectra tables is inconsistent");
905  return DAEstatus::Failure;
906  }
907  m_period_error = false;
908  ICPTimer icptimer;
909  ICPCritical cs(&m_crpt_cs);
910  status.addInfoVa(FAC_DAE, "BEGIN run %d", m_crpt->run_number);
911  updateCycle(status);
912  g_icp_clock.get()->syncToSystemTime();
914 
915  // on excitations instruments tcb.dat may have got changed without a full experimental setup being done
916  bool reread_tcb_file = false;
917  for(i=0; i<m_crpt->ntrg; ++i)
918  {
919  const TCBRANGE* tcr = m_crpt->tcr[i];
920  if ( (tcr[0].mode == TCBRANGE_FILE) && (tcr[0].tcb_file.hasFileChanged(status)) )
921  {
922  status.addInfoVa(FAC_TCB, "Re-reading time channels from %s", tcr[0].tcb_file.fname);
923  reread_tcb_file = true;
924  }
925  }
926  if (reread_tcb_file)
927  {
928  if (tcbcalc(status) == DAEstatus::Failure)
929  {
930  return DAEstatus::Failure;
931  }
932  }
933  if (m_crpt->wiring_table.hasFileChanged(status))
934  {
935  status.addWarningVa(FAC_DAE, "Wiring table %s has changed since last load; old values will still be used", m_crpt->wiring_table.fname);
936  }
937  if (m_crpt->detector_table.hasFileChanged(status))
938  {
939  status.addWarningVa(FAC_DAE, "Detector table %s has changed since last load; old values will still be used", m_crpt->detector_table.fname);
940  }
941  if (m_crpt->spectra_table.hasFileChanged(status))
942  {
943  status.addWarningVa(FAC_DAE, "Spectra table %s has changed since last load; old values will still be used", m_crpt->spectra_table.fname);
944  }
945  if (m_crpt->data_dae_table.hasFileChanged(status))
946  {
947  status.addWarningVa(FAC_DAE, "Data dae table %s has changed since last load; old values will still be used", m_crpt->data_dae_table.fname);
948  }
949  for(i=0; i<ISISCRPT_NUM_VETOS; i++)
950  {
951  m_crpt->vetos[i].frames = 0;
952  }
953  for(i=0; i<ISISCRPT_MAX_PERIOD; i++)
954  {
955  m_crpt->period[i].duration = 0;
956  m_crpt->period[i].good_frames = 0;
957  m_crpt->period[i].good_uamph = 0;
958  m_crpt->period[i].start_time = 0;
959  m_crpt->period[i].stop_time = 0;
960  m_crpt->period[i].total_frames = 0;
961  m_crpt->period[i].total_uamph = 0;
962  m_crpt->period[i].total_ppp_low = 0;
963  m_crpt->period[i].total_ppp_high = 0;
964  m_crpt->period[i].good_ppp_low = 0;
965  m_crpt->period[i].good_ppp_high = 0;
966  }
967  m_crpt->good_frames = 0;
968  m_crpt->total_frames = 0;
969  m_crpt->good_uamph = 0.0;
970  m_crpt->total_uamph = 0.0;
971  m_crpt->good_ppp_low = 0;
972  m_crpt->good_ppp_high = 0;
973  m_crpt->total_ppp_low = 0;
974  m_crpt->total_ppp_high = 0;
975  // shouldn't happen, but nasty if it does
976  if (m_crpt->nper <= 0)
977  {
978  m_crpt->nper_daq = m_crpt->nper = 1;
979  }
980  if (m_crpt->nper > ISISCRPT_MAX_PERIOD || m_crpt->nper_daq > ISISCRPT_MAX_PERIOD)
981  {
982  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid number of periods %d, %d", m_crpt->nper, m_crpt->nper_daq);
983  return DAEstatus::Failure;
984  }
986  {
987  if (period >= 0 && period < m_crpt->nper)
988  {
989  m_crpt->software_period = period;
990  }
992  {
993  status.addWarningVa(FAC_DAE, "Software period %d out of range; resetting to 1", m_crpt->software_period+1);
994  m_crpt->software_period = 0;
995  }
996  else
997  {
998  status.addInfoVa(FAC_DAE, "Run started in software period %d", m_crpt->software_period+1);
999  }
1000  }
1001  else
1002  {
1003  m_crpt->software_period = 0;
1004  }
1005  m_crpt->resume_time = 0;
1006  m_crpt->duration = 0;
1007  m_crpt->stop_time = 0;
1008 // m_crpt->sav_file_count = 0; // only do this on an end as we may begin, store, abort, begin
1009  m_crpt->auto_save_last = 0;
1010  m_crpt->update_num_polls = 0;
1012  m_crpt->update_good_uamph = 0.0;
1013  m_crpt->update_raw_uamph = 0.0;
1016 
1017  m_crpt->monitoring.last_gf = 0;
1018  m_crpt->monitoring.last_tc = 0;
1019  m_crpt->monitoring.last_ua = 0.0;
1020 
1021  m_crpt->nperseq = 0;
1022 
1023  Poco::Thread zero_crpt("zero_crpt"), zero_crpt_run("zero_crpt_run");
1024  Poco::RunnableAdapter<ISISinstrumentControl> zc_runnable(*this, &ISISinstrumentControl::zeroCRPTRawData);
1025  Poco::RunnableAdapter<ISISinstrumentControl> zcr_runnable(*this, &ISISinstrumentControl::zeroCRPTRunRawData);
1026  zero_crpt.start(zc_runnable);
1027  LOGSTR_DEBUG("zero_crpt thread id " << zero_crpt.tid());
1028  zero_crpt_run.start(zcr_runnable);
1029  LOGSTR_DEBUG("zero_crpt_run thread id " << zero_crpt_run.tid());
1030 
1031  setupDAE(0, status);
1032 
1033  zero_crpt.join();
1034  zero_crpt_run.join();
1035 
1036  if (delayed_start)
1037  {
1038  m_dae->enableDelayedStart(status);
1039  }
1040  if (status.OK())
1041  {
1042  time(&(m_crpt->start_time));
1043  m_icpwriter.start(); // start_time is used in NXlog, we may adjust later so NeXevEventWriter will call setOffset()
1044  if (start_paused)
1045  {
1047  m_dae->clearCounters(m_crpt->run_number, status);
1048  setRunStatusImp(RUNSTATUS_PAUSED, true, status);
1049  }
1050  else if (m_crpt->se_status == SESTATUS_INRANGE)
1051  {
1052  startDataCollection(true, status);
1053  m_crpt->start_time = m_crpt->resume_time; // real data collection start time
1054  setRunStatusImp(RUNSTATUS_RUNNING, true, status);
1055  }
1056  else
1057  {
1059  m_dae->clearCounters(m_crpt->run_number, status);
1060  setRunStatusImp(RUNSTATUS_WAITING, true, status);
1061  }
1062  }
1063  if (status.OK())
1064  {
1065  logEvent(m_crpt->start_time, m_crpt, "BEGIN", status);
1066  startEventWriter(status); // run before postcommand so that file any old file descriptor is not inherited
1067  runPostCommand("isisicp.startruncmd", padWithZeros(m_crpt->run_number, m_run_number_digits), status);
1068  }
1069  else
1070  {
1071  logEvent(m_crpt, "FAILED_BEGIN", status);
1072  setRunStatusImp(RUNSTATUS_SETUP, true, status);
1073  }
1074  refreshCachedValues(status);
1075  flushCRPT(status);
1076 // m_dae->printStatus(oss, status);
1077 // m_status.addInfo(FAC_DAE, oss.str());
1078  icptimer.info("BEGIN", status);
1079  return status.result();
1080 }
1081 
1083 {
1084  std::string lastrun_file = m_app->config().getString("isisicp.lastrunfile", "c:\\data\\lastrun.txt");
1085  std::string run_num_string = padWithZeros(crpt->run_number, m_run_number_digits);
1086  std::string sav_file_count = padWithZeros(crpt->sav_file_count, 2);
1087  std::string file_prefix = (m_use_full_inst_name_for_files ? crpt->inst_name : crpt->inst_abrv);
1088  try
1089  {
1090  std::fstream fs(lastrun_file, std::ios::out | std::ios::trunc);
1091  fs << file_prefix << " " << run_num_string << " " << sav_file_count << std::endl;
1092  fs.close();
1093  return DAEstatus::Success;
1094  }
1095  catch(const std::exception& ex)
1096  {
1097  status.addWarningVa(FAC_DAE, "createLastrunFile failed %s", ex.what());
1098  return DAEstatus::Failure;
1099  }
1100 }
1101 
1102 int ISISinstrumentControl::runPostCommand(const char* property_name, const std::string& arg, DAEstatus& status)
1103 {
1104  std::string run_command = m_app->config().getString(property_name, "");
1105  if ( run_command.size() > 0 )
1106  {
1107  std::string out_file = getPostCommandLogName();
1108  return spawnCommand(run_command, arg, true, false, NULL, "", out_file, out_file, 0, status);
1109  }
1110  else
1111  {
1112  status.addWarningVa(FAC_DAE, "runPostCommand cannot find property %s", property_name);
1113  return status.result();
1114  }
1115 }
1116 
1118 {
1119  return 0;
1120 
1121 // if (m_crpt->run_status == RUNSTATUS_SETUP)
1122 // {
1123 // return 0;
1124 // }
1125 // m_nxeventwriter.stop(true);
1126 // IXNeXusFile* ix = new IXNeXusFile(nxErrorFunc, &m_status);
1127 // ix->open(Poco::format("c:\\data\\test%d.nxs", m_crpt->run_number).c_str(), IXNeXusFile::Write);
1128 // m_nxeventwriter.start(m_crpt.CRPT(), ix, true);
1129 // return 0;
1130 }
1131 
1133 {
1134  return 0;
1135 
1136 // if (wait)
1137 // {
1138 // m_nxeventwriter.wait();
1139 // }
1140 // m_nxeventwriter.stop(true);
1141 // return 0;
1142 }
1143 
1145 {
1146  return m_crpt->isRunning();
1147 }
1148 
1150 {
1151  return m_crpt->run_status;
1152 }
1153 
1155 {
1156  return m_crpt->run_number;
1157 }
1158 
1160 {
1161  isisU32_t value;
1162  switch(bus_addr)
1163  {
1164  case 1544:
1165  m_dae->getGoodFrames(&value, status);
1166  word = (value & 0xffff);
1167  break;
1168  case 1548:
1169  m_dae->getGoodFrames(&value, status);
1170  word = (value >> 16) & 0xffff;
1171  break;
1172  case 1552:
1173  m_dae->getRawFrames(&value, status);
1174  word = (value & 0xffff);
1175  break;
1176  case 1556:
1177  m_dae->getRawFrames(&value, status);
1178  word = (value >> 16) & 0xffff;
1179  break;
1180  case 2208:
1181  m_dae->getRawPPPLower(&value, status);
1182  word = (value & 0xffff);
1183  break;
1184  case 2210:
1185  m_dae->getRawPPPLower(&value, status);
1186  word = (value >> 16) & 0xffff;
1187  break;
1188  case 2212:
1189  m_dae->getRawPPPUpper(&value, status);
1190  word = (value & 0xffff);
1191  break;
1192  case 2224:
1193  m_dae->getGoodPPPLower(&value, status);
1194  word = (value & 0xffff);
1195  break;
1196  case 2226:
1197  m_dae->getGoodPPPLower(&value, status);
1198  word = (value >> 16) & 0xffff;
1199  break;
1200  case 2228:
1201  m_dae->getGoodPPPUpper(&value, status);
1202  word = (value & 0xffff);
1203  break;
1204  default:
1205  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "RIO: unknown address %d\n", bus_addr);
1206  return DAEstatus::Failure;
1207  break;
1208  }
1209  return DAEstatus::Success;
1210 }
1211 
1212 // only call when already have CRPT lock
1213 int ISISinstrumentControl::setupDAE(int tables_only, DAEstatus& dstatus)
1214 {
1215  static bool run_external_reset_cmds = Poco::Util::Application::instance().config().getBool("isisicp.daereset.run");
1216  std::map<int,int> trcn;
1217  int i, j, dae1_vetos[30];
1218  unsigned len;
1219  dstatus.addInfo(FAC_CRPT, "Setting up DAE");
1220  int ic, maxcrate = -1, maxcard = -1, maxdae = -1;
1221  for(i=0; i<m_crpt->ndet; i++)
1222  {
1223  if ( (j = (m_crpt->crat[i])) > maxcrate )
1224  {
1225  maxcrate = j;
1226  }
1227  if ( (j = (m_crpt->crat[i] % DAE2CardPolicy::CRATE_MOD)) > maxcard )
1228  {
1229  maxcard = j;
1230  }
1231  if ( (j = (m_crpt->crat[i] / DAE2CardPolicy::CRATE_MOD)) > maxdae )
1232  {
1233  maxdae = j;
1234  }
1235  }
1236  dstatus.addInfoVa(FAC_CRPT, "Highest dae, detector card, crate number used = %d, %d, %d", maxdae, maxcard, maxcrate);
1237  // all detectors on a given card must be in the same time regime
1238  std::map<int,int>::iterator tr_it;
1239  bool dae_event_mode = false;
1240  for(j=0; j<m_crpt->ndet; j++)
1241  {
1242  ic = m_crpt->crat[j];
1243  if ( (tr_it = trcn.find(ic)) != trcn.end() )
1244  {
1245  if ( m_crpt->daeTR(tr_it->second) != m_crpt->timr_dae[j] )
1246  {
1247  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Detectors with different DAE time regimes not allowed on same card: %d != %d", m_crpt->daeTR(tr_it->second) , m_crpt->timr_dae[j]);
1248  return DAEstatus::Failure;
1249  }
1250  }
1251  else
1252  {
1253  trcn.insert(std::map<int,int>::value_type(ic, m_crpt->fullTR(j)));
1254  }
1255  if (m_crpt->timr_dae[j] > m_crpt->ntrg || m_crpt->timr_crpt[j] > m_crpt->ntrg || m_crpt->timr_file[j] > m_crpt->ntrg)
1256  {
1257  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "DAE or CRPT time regime > %d for detector %d", m_crpt->ntrg, m_crpt->udet[j]);
1258  return DAEstatus::Failure;
1259  }
1260  if ( (m_crpt->det_mode[j] & 0x1) != 0 )
1261  {
1262  dae_event_mode = true;
1263  }
1264  }
1265  for(tr_it = trcn.begin(); tr_it != trcn.end(); ++tr_it)
1266  {
1267  if (tr_it->second < 1)
1268  {
1269  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid time regime %d for crate %d", tr_it->second, tr_it->first);
1270  return DAEstatus::Failure;
1271  }
1272  }
1273  if (m_crpt->ntrg > ISISCRPT_MAX_NTRG)
1274  {
1275  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Up to %d time regimes allowed", ISISCRPT_MAX_NTRG);
1276  return DAEstatus::Failure;
1277  }
1278  dstatus.addInfoVa(FAC_CRPT, "Number of time regimes = %d", m_crpt->ntrg);
1279  // size of a period
1280  unsigned permax = m_crpt->getPeriodSize();
1281  len = permax * m_crpt->nper_daq;
1282 // neeed to check if enough DAE memory in detector cards
1283  if ( len > m_crpt.rawDataSizeMax() )
1284  {
1285  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Not enough CRPT memory for requested (spectra * time channels * periods)");
1286  return DAEstatus::Failure;
1287  }
1288  if ( m_crpt->nper > ISISCRPT_MAX_PERIOD )
1289  {
1290  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many periods %d (>%d) specified", m_crpt->nper, ISISCRPT_MAX_PERIOD);
1291  return DAEstatus::Failure;
1292  }
1294  {
1295  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many daq periods %d (>%d) specified", m_crpt->nper_daq, ISISCRPT_MAX_PERIOD);
1296  return DAEstatus::Failure;
1297  }
1298  dstatus.addInfoVa(FAC_CRPT, "CRPT memory used for histograms = %u Mb", (len * 4) / (1024 * 1024));
1299  dstatus.addInfoVa(FAC_CRPT, "Number of periods (daq, total) = (%d, %d)", m_crpt->nper_daq, m_crpt->nper);
1300  dstatus.addInfo(FAC_CRPT, "Resetting DAE - ignore veto counter values as not yet cleared");
1301  if ( run_external_reset_cmds && (tables_only == 0) )
1302  {
1303  dstatus.addInfo(FAC_CRPT, "Running external DAE reset commands");
1304  typedef std::pair<std::string,std::string> string_pair_t;
1305  std::list< string_pair_t > commands;
1306  m_dae->getExternalResetCommands(commands, dstatus);
1307  std::string out_file = getPostCommandLogName();
1308  BOOST_FOREACH(const string_pair_t& comm, commands)
1309  {
1310  dstatus.addInfoVa(FAC_CRPT, "Running: %s %s", comm.first.c_str(), comm.second.c_str());
1311  spawnCommand(comm.first, comm.second, true, false, NULL, "", out_file, out_file, 30, dstatus);
1312  }
1313  }
1314  // need to set event mode flag in dae/dc card before programming poslut - this is so when updateAddmap
1315  // and fillAddmap are called they know event mode will be used
1316  m_dae->setEventMode(dae_event_mode);
1317  m_dae->clearDCEventMode(dstatus);
1318  for(tr_it = trcn.begin(); tr_it != trcn.end(); ++tr_it)
1319  {
1320  m_dae->setDCEventMode(tr_it->first, m_crpt->isEventTR(tr_it->second), dstatus);
1321  m_dae->setDCCardMode(tr_it->first, true, dstatus);
1322  }
1323  // set event mode on any data into dae cards
1324  for(i=0; i<m_crpt->n_data_dae; ++i)
1325  {
1326  m_dae->setDCEventMode(m_crpt->data_dae[i].crate, true, dstatus);
1327  m_dae->setDCCardMode(m_crpt->data_dae[i].crate, false, dstatus);
1328  }
1329  if (tables_only == 0)
1330  {
1331  m_dae->stopRun(ISISDAE::StopRunFast/*ISISDAE::StopRunDiscard*/, dstatus);
1332  m_dae->resetRunController(dstatus);
1333  m_dae->clearHistogramMemory(dstatus);
1334  }
1335  else
1336  {
1337  m_dae->stopRun(ISISDAE::StopRunFast, dstatus);
1338  m_dae->resetRunController(dstatus);
1339  dstatus.addInfo(FAC_CRPT, "RELOAD TABLES ONLY requested - DAE memory not zeroed");
1340  }
1341  // TCG
1342  // prescale
1343  dstatus.addInfo(FAC_CRPT, "Programming Time channels");
1344  // need to allow for the prescale and delay
1345  //std::vector<unsigned long*> new_tcb;
1346  //for(i=0; i<m_crpt->ntrg; ++i)
1347  //{
1348  // new_tcb.push_back(new unsigned long[1+m_crpt->ntc[i]]);
1349  //}
1351  unsigned long* new_tcb = 0;
1352  float frame_delay;
1353  for(int k=0; k<m_crpt->ntrg; ++k)
1354  {
1355  new_tcb = new unsigned long[1+m_crpt->ntc[k]];
1356 // if we have a pulse generator, we want the first channel at 0
1357 // as we use this to signal the first bin
1358  if (m_crpt->tcb_pulse_generator != 0)
1359  {
1360  frame_delay = (float)m_crpt->tcb[k][0] / m_crpt->clock_frequency;
1361  dstatus.addInfoVa(FAC_CRPT, "PULSE_GENERATOR: frame delay %f us", m_crpt->tcb_delay + frame_delay);
1362  for(i=0; i <= m_crpt->ntc[k]; i++)
1363  {
1364 // tcb are in clock pulses, delay is in us hence * 32
1365  new_tcb[i] = m_crpt->tcb[k][i] - m_crpt->tcb[k][0];
1366  if ( (new_tcb[i] & 0xff000000) != 0 )
1367  {
1368  dstatus.addWarningVa(FAC_CRPT, "TCG value larger than 24 bits %lu", new_tcb[i]);
1369  new_tcb[i] = 0xffffff;
1370  }
1371  }
1372  }
1373  else
1374  {
1375  dstatus.addInfoVa(FAC_CRPT, "Global Frame sync delay = %d us", m_crpt->tcb_delay);
1376  dstatus.addInfoVa(FAC_CRPT, "Electronics delay = %d clock pulses", m_crpt->electronics_delay);
1377  for(i=0; i <= m_crpt->ntc[k]; i++)
1378  {
1379 // tcb are in clock pulses, delay is in us hence * 32
1380 // new_tcb1[i] = tcb1[i] * pre1 + (4 * delay) * 32;
1381 // get 0.21us for free (7 clock pulses)
1382  new_tcb[i] = m_crpt->tcb[k][i] - m_crpt->electronics_delay;
1383  if ( (new_tcb[i] & 0xff000000) != 0 )
1384  {
1385  dstatus.addWarningVa(FAC_CRPT, "TCG value larger than 24 bits %lu", new_tcb[i]);
1386  new_tcb[i] = 0xffffff;
1387  }
1388  }
1389  }
1390  for(tr_it = trcn.begin(); tr_it != trcn.end(); ++tr_it)
1391  {
1392  int dae_tr = m_crpt->daeTR(tr_it->second);
1393  if ( dae_tr == k+1 )
1394  {
1395  if ( m_crpt->ntc[k] > ISISDAE_MAX_DAE2TIMECHAN )
1396  {
1397  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many time channels %d (> %d) for time regime %d (card %d)",
1398  m_crpt->ntc[k], ISISDAE_MAX_DAE2TIMECHAN, dae_tr, tr_it->first);
1399  return DAEstatus::Failure;
1400  }
1401  dstatus.addInfoVa(FAC_CRPT, "Setting %d time channels from %f to %f us on card %d", m_crpt->ntc[k], (double)new_tcb[0] / m_crpt->clock_frequency,
1402  (double)new_tcb[m_crpt->ntc[k]] / m_crpt->clock_frequency, tr_it->first);
1403  m_dae->setTimeChannels(tr_it->first, new_tcb, m_crpt->ntc[k], dstatus);
1404  int det_fs_delay = m_crpt->tcb_trdelay[dae_tr - 1];
1405  dstatus.addInfoVa(FAC_CRPT, "Setting FS delay on DC %d to %d us", tr_it->first, det_fs_delay);
1406  m_dae->setDCFrameSyncDelay(tr_it->first, det_fs_delay, dstatus);
1407  }
1408  }
1409  // set tcb on any data into dae cards
1410  for(i=0; i<m_crpt->n_data_dae; ++i)
1411  {
1412  int dae_tr = m_crpt->daeTR(m_crpt->data_dae[i].tr);
1413  int crate = m_crpt->data_dae[i].crate;
1414  if ( dae_tr == k+1 )
1415  {
1416  if ( m_crpt->ntc[k] > ISISDAE_MAX_DAE2TIMECHAN )
1417  {
1418  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many time channels %d (> %d) for time regime %d (card %d)",
1419  m_crpt->ntc[k], ISISDAE_MAX_DAE2TIMECHAN, dae_tr, crate);
1420  return DAEstatus::Failure;
1421  }
1422  dstatus.addInfoVa(FAC_CRPT, "Setting %d time channels from %f to %f us on data dae DC %d", m_crpt->ntc[k], (double)new_tcb[0] / m_crpt->clock_frequency,
1423  (double)new_tcb[m_crpt->ntc[k]] / m_crpt->clock_frequency, crate);
1424  m_dae->setTimeChannels(crate, new_tcb, m_crpt->ntc[k], dstatus);
1425  int det_fs_delay = m_crpt->tcb_trdelay[dae_tr - 1];
1426  dstatus.addInfoVa(FAC_CRPT, "Setting FS delay on data dae DC %d to %d us", crate, det_fs_delay);
1427  m_dae->setDCFrameSyncDelay(crate, det_fs_delay, dstatus);
1428  }
1429  }
1430  delete []new_tcb;
1431  }
1433  dstatus.addInfo(FAC_DAE, "Programming POSLUT");
1434  m_dae->programDAE1POSLUT(m_crpt->crat, maxcrate, m_crpt->modn,
1435  m_crpt->mpos, m_crpt->spec, m_crpt->ndet, m_crpt->nper_daq, dstatus);
1436 
1437  updateSpecmapsFromDAE(trcn, dstatus);
1438 
1440  //
1442  {
1443  dstatus.addInfo(FAC_CRPT, "Hardware periods enabled");
1444  }
1445  else
1446  {
1447  dstatus.addInfo(FAC_CRPT, "Software periods enabled");
1448  }
1449  // period card
1450  isisU32_t val32;
1451  isisU16_t val16_0, val16_1;
1453  {
1454  // for safety, tell it to use one long period...
1455  val32 = 0;
1456  val16_0 = 0;
1457  val16_1 = 15000;
1458  dstatus.addInfo(FAC_CRPT, "(setting period card, if present, to 1 hardware period of 15000 frames)");
1460  &val16_0, &val16_1, m_crpt->period_output_delay, dstatus);
1461  m_dae->disablePeriodCard(dstatus);
1462  }
1463  else
1464  {
1465  dstatus.addInfo(FAC_CRPT, "Programming PERIOD card for hardware period control");
1466  isisU32_t* outputs = new isisU32_t[m_crpt->nper];
1467  isisU16_t* dwell_flags = new isisU16_t[m_crpt->nper];
1468  isisU16_t* frames = new isisU16_t[m_crpt->nper];
1469  for(i=0; i<m_crpt->nper; i++)
1470  {
1471  outputs[i] = m_crpt->period[i].output;
1472  dwell_flags[i] = (m_crpt->period[i].type == 2 ? 1 : 0);
1473  frames[i] = static_cast<isisU16_t>(m_crpt->period[i].requested_frames);
1474  }
1476  outputs, dwell_flags, frames, m_crpt->period_output_delay, dstatus);
1477  // The period card currently uses a cable plugged into the enviroment card
1478  // external veto port to do dwell periods; thus we always need to enable
1479  // external vetos on the environment card
1480  // howevere the new env period card does not ...
1481  // m_crpt->ext_vetos[0] = 1;
1482  delete[] outputs; delete[] dwell_flags; delete[] frames;
1483  }
1484  bool single_daq_period = (1 == m_crpt->nper_daq);
1485  m_dae->setPeriodType((ISISDAE::PeriodType)m_crpt->period_type, single_daq_period, dstatus);
1487  {
1488  changePeriod(m_crpt->software_period, dstatus);
1489 // m_dae->changePeriod(m_crpt->software_period, m_crpt->software_period, dstatus); // adjust for current period
1490  }
1491  dstatus.addInfo(FAC_CRPT, "Setting vetos");
1492  dae1_vetos[0] = m_crpt->vetos[SMPVeto].enabled;
1493  dae1_vetos[1] = m_crpt->vetos[Ext0Veto].enabled;
1494  dae1_vetos[2] = m_crpt->vetos[Ext1Veto].enabled;
1495  dae1_vetos[3] = m_crpt->vetos[Ext2Veto].enabled;
1496  dae1_vetos[4] = m_crpt->vetos[Ext3Veto].enabled;
1497  dae1_vetos[5] = m_crpt->vetos[FermiChopperVeto0].enabled;
1498  dae1_vetos[6] = m_crpt->fermi_chopper_delay[0];
1499  dae1_vetos[7] = m_crpt->fermi_chopper_width[0];
1500  dae1_vetos[8] = m_crpt->vetos[TS2PulseVeto].enabled;
1501  dae1_vetos[9] = m_crpt->vetos[ISIS50HzVeto].enabled;
1502  m_dae->setDAE1Vetos(dae1_vetos, 10, dstatus);
1503 // we do not start a run, just setup the DAE
1504  if (tables_only == 0)
1505  {
1506  dstatus.addInfo(FAC_CRPT, "Clearing frames, vetos and PPP counters");
1507  m_dae->clearCounters(dstatus);
1508  }
1509 // dstatus.addDebug(FAC_CRPT, "Leaving VME DAEBEG");
1510  return DAEstatus::Success;
1511 }
1512 
1514 {
1515  return pauseRunMain(true, dstatus);
1516 }
1517 
1518 int ISISinstrumentControl::pauseRunMain(bool refresh_cache, DAEstatus& dstatus)
1519 {
1521  {
1522  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot PAUSE in SETUP");
1523  return DAEstatus::Failure;
1524  }
1526  {
1527  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Run already paused");
1528  return DAEstatus::Failure;
1529  }
1530  ICPCritical cs(&m_crpt_cs);
1531  dstatus.addInfoVa(FAC_CRPT, "Pausing run %d", m_crpt->run_number);
1532 // dstatus.addDebug(FAC_CRPT, "Entering VME DAEPAUSE");
1533  if (isRunning())
1534  {
1536  }
1537  setRunStatusImp(RUNSTATUS_PAUSED, false, dstatus);
1538  logEvent(m_crpt, "PAUSE", dstatus);
1539 // isisU32_t igfc, irfc;
1540 // m_dae->stopRun(dstatus);
1541 // m_dae->getRawFrames(&irfc, dstatus);
1542 // m_dae->getGoodFrames(&igfc, dstatus);
1543 // m_crpt->period[m_crpt->c_period].good_frames += igfc;
1544 // m_crpt->period[m_crpt->c_period].raw_frames += irfc;
1545 // return 0 as the frame count to avoid overcounting. DAE1 zerod these
1546 // counters on stop/start data collection, but DAE-II doesn't
1547 
1548 // dstatus.addDebug(FAC_DAE, "Leaving VME DAEPAUSE");
1549  if (refresh_cache)
1550  {
1551  refreshCachedValues(dstatus);
1552  }
1553  flushCRPT(dstatus);
1554  return DAEstatus::Success;
1555 }
1556 
1557 
1559 {
1561  {
1562  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot ABORT in SETUP");
1563  return DAEstatus::Failure;
1564  }
1565  ICPCritical cs(&m_crpt_cs);
1566  dstatus.addInfoVa(FAC_CRPT, "Aborting run %d", m_crpt->run_number);
1567  if (isRunning())
1568  {
1569  stopDataCollection(ISISDAE::StopRunFast/*ISISDAE::StopRunDiscard*/, dstatus);
1570  }
1571  setRunStatusImp(RUNSTATUS_SETUP, false, dstatus);
1572  logEvent(m_crpt, "ABORT", dstatus);
1573  m_crpt->software_period = 0;
1574  refreshCachedValues(dstatus);
1575  flushCRPT(dstatus);
1576  return DAEstatus::Success;
1577 }
1578 
1580 {
1581  ICPCritical cs(&m_crpt_cs);
1583  if (isRunning())
1584  {
1585  LOGSTR_INFORMATION("Start SE wait");
1587  setRunStatusImp(RUNSTATUS_WAITING, false, dstatus);
1588  logEvent(m_crpt, "WAIT_START", dstatus);
1589  }
1590  return DAEstatus::Success;
1591 }
1592 
1594 {
1595  ICPCritical cs(&m_crpt_cs);
1597  if (isWaiting())
1598  {
1599  LOGSTR_INFORMATION("End SE wait");
1600  logEvent(m_crpt, "WAIT_FINISH", dstatus);
1601  startDataCollection(false, dstatus);
1602  setRunStatusImp(RUNSTATUS_RUNNING, false, dstatus);
1603  }
1604  return DAEstatus::Success;
1605 }
1606 
1608 {
1609  return m_crpt->run_status == RUNSTATUS_WAITING;
1610 }
1611 
1613 {
1615  {
1616  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only RESUME from PAUSED");
1617  return DAEstatus::Failure;
1618  }
1619  ICPCritical cs(&m_crpt_cs);
1620  dstatus.addInfoVa(FAC_CRPT, "Resuming run %d", m_crpt->run_number);
1621 // dstatus.addDebug(FAC_CRPT, "Entering VME DAERESUME");
1622  logEvent(m_crpt, "RESUME", dstatus);
1624  {
1625  startDataCollection(false, dstatus);
1626  setRunStatusImp(RUNSTATUS_RUNNING, false, dstatus);
1627  }
1628  else
1629  {
1630  logEvent(m_crpt, "WAIT_START", dstatus);
1631  setRunStatusImp(RUNSTATUS_WAITING, false, dstatus);
1632  }
1633 // dstatus.addDebug(FAC_CRPT, "Leaving VME DAERESUME");
1634  return dstatus.result();
1635 }
1636 
1638 {
1639  ICPCritical cs(&m_crpt_cs);
1640  dstatus.addInfo(FAC_CRPT, "Saving run");
1641 // dstatus.addDebug(FAC_CRPT, "Entering VME DAESAVE");
1642  logEvent(m_crpt, "SAVE", dstatus);
1643  updateCRPTWithDAE(true, dstatus);
1644  if (dstatus.OK())
1645  {
1646  storeCRPT(dstatus);
1647  }
1648  return dstatus.result();
1649 }
1650 
1651 
1652 int ISISinstrumentControl::updateCRPTWithDAE(bool pause_collection, DAEstatus& dstatus)
1653 {
1654  ICPCritical cs(&m_crpt_cs);
1655  logEvent(m_crpt, "UPDATE", dstatus);
1656  return updateCRPTWithDAE(m_crpt, pause_collection, dstatus);
1657 }
1658 
1660 {
1661  ICPTimer icptimer("updateCRPTwithSE", dstatus);
1662  updateSampleParameters(crpt.sampleParameters(), crpt, &blocks, dstatus);
1663  updateBeamlineParameters(crpt.beamlineParameters(), crpt, &blocks, dstatus);
1664  return DAEstatus::Success;
1665 }
1666 
1667 int ISISinstrumentControl::updateCRPTWithDAE(CRPTProxy& crpt, bool pause_collection, DAEstatus& dstatus)
1668 {
1669  ICPTimer icptimer("updateCRPTWithDAE", dstatus);
1670  int permax = crpt->getPeriodSize();
1671  int len = permax * crpt->nper_daq;
1672  dstatus.addInfoVa(FAC_CRPT, "%d DAQ periods of size %d words", crpt->nper_daq, permax);
1673  if ( len > crpt.rawDataSizeMax() )
1674  {
1675  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Not enough CRPT memory for requested (spectra * time channels * periods)");
1676  return DAEstatus::Failure;
1677  }
1679  ICPTimer icptimer1;
1680  if (crpt->isRunning() && pause_collection && (crpt->period_type == ISISDAE::PeriodTypeSoftware) )
1681  {
1683  Poco::Mutex::ScopedLock _lock(crpt.getDataLockRef()); // necessary? this will freeze out other trheads from reading/writing
1684  icptimer1.start(); // restart timer in case stopDataCollection() takes a bit of time
1685  m_dae->readAllDAE1Spectra(crpt.rawData(), len, crpt->spec_to_crpt_offset.data(), permax, dstatus);
1686  // m_dae->readHistogramMemory(0, m_crpt->raw_data, len, dstatus);
1687  startDataCollection(false, dstatus);
1688  }
1689  else
1690  {
1691 // dstatus.addInfo(FAC_CRPT, "Performed live CRPT snapshot\n");
1692  Poco::Mutex::ScopedLock _lock(crpt.getDataLockRef()); // necessary? this will freeze out other trheads from reading/writing
1693  m_dae->readAllDAE1Spectra(crpt.rawData(), len, crpt->spec_to_crpt_offset.data(), permax, dstatus);
1694  // m_dae->readHistogramMemory(0, m_crpt->raw_data, len, dstatus);
1695  }
1696  crpt.rawDataUpdated();
1697  double up_time = icptimer1.info("UPDATE", dstatus);
1698  if (up_time > 0.0)
1699  {
1700  dstatus.addInfoVa(FAC_DAE, "Average DAE transfer rate = %d KByte / s", (int)((len * 4.0) / (1000.0 * up_time)) );
1701  }
1702  crpt.flushCRPT(dstatus);
1703  return dstatus.result();
1704 }
1705 
1706 int ISISinstrumentControl::importCRPT(const char* filename, DAEstatus& dstatus)
1707 {
1708  ICPCritical cs(&m_crpt_cs);
1709  ICPTimer icptimer;
1710  readISISRAW(filename, dstatus);
1711  flushCRPT(dstatus);
1712  logEvent(m_crpt, "IMPORT", dstatus);
1713  icptimer.info("IMPORT timing", dstatus);
1714  return dstatus.result();
1715 }
1716 
1718 {
1719  ICPTimer icptimer("getSE", dstatus);
1720  if (se_get_blocks(crpt->run_number, crpt->start_time, blocks) != 0)
1721  {
1722  dstatus.addInfoVa(FAC_DAE, "SQLITE error %s", se_get_errmsg());
1723  }
1724  return DAEstatus::Success;
1725 }
1726 
1729 {
1730  static const int CARD_MOD = 100; // module numbers are 0->15 so this shift the card/crate number away from this
1731  static const bool check_noncount = m_app->config().getBool("isisicp.noncountingdetectors.check", false);
1732  static const bool email_noncount = m_app->config().getBool("isisicp.noncountingdetectors.email", false);
1733  struct crat_id_t
1734  {
1735  uint64_t c;
1736  int s;
1737  int u;
1738  crat_id_t() : c(0), s(0), u(0) { }
1739  };
1740  typedef std::map<int,crat_id_t> crat_map_t;
1741  if ( !check_noncount )
1742  {
1743  return DAEstatus::Success;
1744  }
1745  crat_map_t crat_map;
1746  std::ostringstream oss;
1747  int id;
1748  long integral;
1749  for(int i=0; i<crpt->ndet; ++i)
1750  {
1751  id = CARD_MOD * crpt->crat[i] + crpt->modn[i];
1752  getCRPTSpectrumIntegral(crpt->spec[i], 1, 0, &integral, dstatus);
1753  crat_id_t& ci = crat_map[id];
1754  ci.c += integral;
1755  ci.s = crpt->spec[i];
1756  ci.u = crpt->udet[i];
1757  }
1758  for(crat_map_t::const_iterator it = crat_map.begin(); it != crat_map.end(); ++it)
1759  {
1760  if (it->second.c == 0)
1761  {
1762  oss << "Run: " << crpt->run_number << " uAh: " << crpt->good_uamph << " Title: \"" << crpt->long_title << "\"\n";
1763  oss << "DAE Crate " << (it->first / DAE2CardPolicy::CRATE_MOD) / DAE2CardPolicy::CRATE_MOD << " detector card id " << (it->first / DAE2CardPolicy::CRATE_MOD) % DAE2CardPolicy::CRATE_MOD << " DIM/module " << it->first % DAE2CardPolicy::CRATE_MOD << " has no counts (e.g. spectrum=" << it->second.s << ",UDET=" << it->second.u << ")\n";
1764  }
1765  }
1766  if (oss.str().size() > 0)
1767  {
1768  LOGSTR_WARNING(oss.str());
1769  if ( email_noncount )
1770  {
1771  sendEmail("isisicp@shadow.nd.rl.ac.uk", crpt->alert_email, std::string(crpt->comp_name)+" zero counts in detector DIM", oss.str(), m_status);
1772  }
1773  }
1774  return DAEstatus::Success;
1775 }
1776 
1777 int ISISinstrumentControl::saveCRPTToFile(const CRPTProxy& crpt, const std::string& raw_filename, const std::string& nexus_filename, const seblock_map_t& blocks, const std::string& events_nxfile, DAEstatus& dstatus)
1778 {
1779  ICPTimer icptimer("saveCRPTToFile", dstatus);
1780  if (raw_filename.size() > 0)
1781  {
1782  remove(raw_filename.c_str());
1783  }
1784  if (nexus_filename.size() > 0)
1785  {
1786  remove(nexus_filename.c_str());
1787  }
1788  bool do_nexus = ( m_nexus_files && (nexus_filename.size() > 0) );
1790  {
1791  dstatus.addInfoVa(FAC_DAE, "Writing muon data file %s", nexus_filename.c_str());
1792  m_nxwriter.writeMuonFile(nexus_filename.c_str(), crpt.CRPT(), crpt.rawData(), crpt.rawDataSizeMax(), blocks, m_inst_settings_dir, m_instrument_xml_file, m_instrument_parameter_map_file, dstatus);
1793  createLastrunFile(crpt, dstatus);
1794  runPostCommand("isisicp.exportfilecmd", nexus_filename.c_str(), dstatus);
1795  }
1796  else
1797  {
1798  Poco::SharedPtr<Poco::Event> finish_event(new Poco::Event);
1799  if ( do_nexus )
1800  {
1801  dstatus.addInfoVa(FAC_DAE, "Writing nexus data file %s", nexus_filename.c_str());
1802  GenericTask<int>* nexus_task = new GenericTask<int>(Poco::format("saveCRPTToFile %d", crpt->run_number), finish_event,
1804  boost::ref(m_nxwriter), boost::cref(crpt), nexus_filename.c_str(), false, boost::cref(blocks),
1805  boost::cref(events_nxfile), boost::ref(dstatus)));
1806  m_taskmgr.start(nexus_task);
1807  }
1808  if ( m_vms_raw_files && (raw_filename.size() > 0) )
1809  {
1810  dstatus.addInfoVa(FAC_DAE, "Writing raw data file %s", raw_filename.c_str());
1811  writeISISRAW(crpt, raw_filename.c_str(), dstatus);
1812  createLastrunFile(crpt, dstatus);
1813  runPostCommand("isisicp.exportfilecmd", raw_filename.c_str(), dstatus);
1814  }
1815  if ( do_nexus )
1816  {
1817  finish_event->wait(); // wait for nexus file
1818  createLastrunFile(crpt, dstatus);
1819  runPostCommand("isisicp.exportfilecmd", nexus_filename.c_str(), dstatus);
1820  }
1821  }
1822  return dstatus.result();
1823 }
1824 
1825 int ISISinstrumentControl::updateCRPTWithSEandSaveToFile(CRPTProxy& crpt, const std::string& raw_filename, const std::string& nexus_filename, DAEstatus& dstatus)
1826 {
1827  static bool use_shadow = Poco::Util::Application::instance().config().getBool("isisicp.shadow.use", false);
1828  ICPTimer icptimer("updateCRPTWithSEandSaveToFile", dstatus);
1829  seblock_map_t blocks;
1830  std::string events_nxfile = "";
1831  getSE(crpt, blocks, dstatus);
1832  updateCRPTwithSE(crpt, blocks, dstatus);
1833  if (use_shadow)
1834  {
1835  events_nxfile = "c:\\data\\snap.tmp";
1836  m_icpwriter.snapshot(events_nxfile);
1837  }
1838  saveCRPTToFile(crpt, raw_filename, nexus_filename, blocks, events_nxfile, dstatus);
1839  return DAEstatus::Success;
1840 }
1841 
1842 
1843 int ISISinstrumentControl::snapshotCRPT(const char* filename, bool do_update, bool do_pause, DAEstatus& dstatus)
1844 {
1845  static bool nexus_snapshot = Poco::Util::Application::instance().config().getBool("isisicp.writenexuscrptsnapshot", true);
1846  ICPCritical cs(&m_crpt_cs);
1847  if (do_update)
1848  {
1849  updateCRPTWithDAE(m_crpt, do_pause, dstatus);
1850  }
1851  ICPTimer icptimer;
1852  Poco::Path file_path(filename);
1853  file_path.setExtension("");
1854  updateCRPTWithSEandSaveToFile(m_crpt, file_path.toString()+".raw", (nexus_snapshot ? file_path.toString()+".nxs" : ""), dstatus);
1855 
1856  runPostCommand("isisicp.endcrptsnapshotcmd", filename, dstatus);
1857  logEventVa(m_crpt, dstatus, "CRPT_SNAPSHOT %s", filename);
1858  icptimer.info("CRPT_SNAPSHOT", dstatus);
1859  return dstatus.result();
1860 }
1861 
1863 {
1864  ICPCritical cs(&m_crpt_cs);
1865  return storeCRPT(m_crpt, status);
1866 }
1867 
1869 {
1870 // char buffer[256];
1871  ICPTimer icptimer;
1872  seblock_map_t blocks;
1873 
1875  if (crpt->sav_file_count < 99)
1876  {
1877  ++(crpt->sav_file_count);
1878  }
1879  std::string run_num_string = padWithZeros(crpt->run_number, m_run_number_digits);
1880  std::string file_prefix = (m_use_full_inst_name_for_files ? crpt->inst_name : crpt->inst_abrv);
1881  std::string sav_file = Poco::format(m_data_dir + "\\%s%s.s%02d", file_prefix, run_num_string, crpt->sav_file_count);
1882  std::string nx_sav_file = Poco::format(m_data_dir + "\\%s%s.n%03d", file_prefix, run_num_string, crpt->sav_file_count);
1883  updateCRPTWithSEandSaveToFile(crpt, sav_file, nx_sav_file, dstatus);
1884  runPostCommand("isisicp.endstorecmd", Poco::format("%s %02d", run_num_string, crpt->sav_file_count), dstatus);
1885  flushCRPT(dstatus);
1886  writeRecoveryFile(dstatus);
1887  logEvent(crpt, "STORE", dstatus);
1888  icptimer.info("STORE", dstatus);
1889  return dstatus.result();
1890 }
1891 
1893 {
1894 // char buffer[256];
1895  ICPCritical cs(&m_crpt_cs);
1896  ++(m_crpt->auto_save_count);
1897  if (m_crpt->auto_save_count > 5)
1898  {
1899  m_crpt->auto_save_count = 1;
1900  }
1901  updateCRPTWithDAE(m_crpt, true, dstatus);
1902  char letter = static_cast<char>(m_crpt->auto_save_count - 1 + 'A');
1903  std::string file_prefix = (m_use_full_inst_name_for_files ? m_crpt->inst_name : m_crpt->inst_abrv);
1904  std::string auto_filename = Poco::format(m_data_dir + "\\%sauto_%c.tmp", file_prefix, letter);
1905  updateCRPTWithSEandSaveToFile(m_crpt, auto_filename, auto_filename, dstatus);
1906  runPostCommand("isisicp.endautosavecmd", Poco::format("%sauto_%c.tmp", file_prefix, letter), dstatus);
1907  flushCRPT(dstatus);
1908  logEvent(m_crpt, "AUTOSAVE", dstatus);
1909  return dstatus.result();
1910 }
1911 
1913 {
1914  return RCretry("END", boost::bind(&ISISinstrumentControl::endRunMain, _1, _2), dstatus);
1915 }
1916 
1917 
1919 {
1920  // format of file is "set cycle=cycle_09_1"
1921  try {
1922  const char* userprofile = getenv("USERPROFILE");
1923  std::string commfile = std::string(userprofile != NULL ? userprofile : "") +
1924  "\\My Documents\\configurations\\common\\setcycle.cmd";
1925  std::fstream fs(commfile.c_str(), std::ios::in);
1926  char buffer[256];
1927  std::string line;
1928  if (fs.good())
1929  {
1930  fs.getline(buffer, sizeof(buffer));
1931  buffer[sizeof(buffer)-1] = '\0';
1932  line = buffer;
1933  }
1934  else
1935  {
1936  line = "cycle_??_?";
1937  }
1938  strncpy(m_crpt->isis_cycle, line.substr(line.find("_")+1).c_str(), sizeof(m_crpt->isis_cycle)-1);
1939  return DAEstatus::Success;
1940  }
1941  catch(const std::exception& ex) {
1942  strncpy(m_crpt->isis_cycle, "??_?", sizeof(m_crpt->isis_cycle)-1);
1943  dstatus.addWarning(FAC_CRPT, ex.what());
1944  return DAEstatus::Failure;
1945  }
1946 }
1947 
1948 
1950 {
1951  ICPTimer icptimer("loadCRPTWithHistogrammedEvents", dstatus);
1952  crpt.zeroEventRawData(dstatus); // on a normal end this will be zero, but on a re-end may have stuff left in from the failed end
1953  EventStore es;
1955  es.addFileInputSource(crpt->run_number, info);
1956  es.addGoodEventCallback(boost::bind(&CRPTProxy::histogramEventsToCRPT, crpt.CRPT(), static_cast<ISISCRPT_STRUCT*>(0), crpt.crptData(), static_cast<ISISCRPT_DATA*>(0), _1, _2, _3, _4));
1957  es.start();
1958  while (!es.endHeaderSeen())
1959  {
1960  Poco::Thread::sleep(500);
1961  }
1962  es.stop(false);
1963  return 0;
1964 }
1965 
1966 // need events_nxfile as copy rather than reference as may go out of scope in caller
1967 int ISISinstrumentControl::endRunTask(Poco::SharedPtr<CRPTProxy> crpt, NeXusWriter& nxwriter, bool keep_raw_events, bool keep_crpt, std::string events_nxfile, DAEstatus& status)
1968 {
1969  bool savehistogramsineventsfile = Poco::Util::Application::instance().config().getBool("isisicp.savehistogramsineventsfile", true);
1970  static Poco::Semaphore end_semaphore(1);
1971  DAEstatus dstatus;
1972  CRPTProxy& crpt_end = *crpt;
1973  ICPTimer icptimer1, icptimer2;
1974  if ( crpt_end.CRPT() == NULL )
1975  {
1976  LOGSTR_ERROR("CRPT_END is NULL - cannot END");
1977 // we do not need to crpt_end.uloadCRPT() as it was not loaded
1978  return DAEstatus::Failure;
1979  }
1980  dstatus.addInfoVa(FAC_CRPT, "ENDing run %d task, thread id %u", crpt_end->run_number, Poco::Thread::currentTid());
1981  int permax = crpt_end->getPeriodSize();
1982 // int len = permax * crpt_end->nper_daq;
1983  dstatus.addInfoVa(FAC_CRPT, "%d DAQ periods of size %d words", crpt_end->nper_daq, permax);
1984 
1985  icptimer2.start();
1986  std::string file_prefix = (m_use_full_inst_name_for_files ? crpt_end->inst_name : crpt_end->inst_abrv);
1987 
1988  seblock_map_t blocks;
1989  getSE(crpt_end, blocks, dstatus);
1990  updateCRPTwithSE(crpt_end, blocks, dstatus);
1991 
1992  // make sure we only do the next bit one at a time - this is purely to avoid excessive CPU as it is
1993  // actually safe to do all these in parallel
1994  ScopedSemaphore _sem(end_semaphore);
1995 
1996  if ( savehistogramsineventsfile && (crpt_end->start_time < crpt_end->icp_start_time) )
1997  {
1998  LOGSTR_INFORMATION("ICP has been restarted - rehistogramming events");
1999  loadCRPTWithHistogrammedEvents(crpt_end, dstatus);
2000  }
2001  std::string run_num_string = padWithZeros(crpt_end->run_number, m_run_number_digits);
2002  saveCRPTToFile(crpt_end, Poco::format(m_data_dir + "\\%s%s.raw", file_prefix, run_num_string),
2003  Poco::format(m_data_dir + "\\%s%s.nxs", file_prefix, run_num_string), blocks,
2004  events_nxfile, dstatus);
2005 
2006  icptimer2.info("File Write", dstatus);
2007  if (dstatus.OK())
2008  {
2009  ICPTimer journal_timer;
2010  writeJournal(crpt_end, blocks, dstatus);
2011  journal_timer.info("write journal", dstatus);
2012  ICPTimer se_clear_timer;
2013  // clear only this run as others may be pending now we are doing asyn ends
2014  if ( !keep_crpt && (se_clear_values(crpt_end->run_number, crpt_end->run_number) != 0) )
2015  {
2016  dstatus.addInfoVa(FAC_DAE, "Error from SQLITE(se_clear_values): %s", se_get_errmsg());
2017  }
2018  se_clear_timer.info("se_clear_values", dstatus);
2019  runPostCommand("isisicp.endruncmd", padWithZeros(crpt_end->run_number, m_run_number_digits), dstatus);
2020  checkForNoncountingDetectors(crpt_end, dstatus);
2021  if ( !keep_raw_events )
2022  {
2023  // currently if we haven't done a begin;end;begin the run_number will still be open in ISISDAE
2024  // so here we will delete run and run-1 to make sure we carch it eventually
2026 
2027  // EventStore::deleteOutputFile(crpt_end->run_number-1, dstatus); // this may remove a previously failed run!
2028  EventStore::deleteOutputFile(crpt_end->run_number, dstatus);
2029  }
2030  else
2031  {
2032  dstatus.addInfoVa(FAC_DAE, "Keeping raw event files for run %d", crpt_end->run_number);
2033  }
2034  if ( keep_crpt )
2035  {
2036  dstatus.addInfoVa(FAC_DAE, "Keeping CRPT for run %d", crpt_end->run_number);
2037  crpt_end.unloadCRPT(false, false, dstatus);
2038  }
2039  else
2040  {
2041  crpt_end.unloadCRPT(true, true, dstatus);
2042  }
2043  }
2044  else
2045  {
2046  dstatus.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Failed to END run %d", crpt_end->run_number);
2047 // assignICPLogFiles(); // this updates log files for new run number
2048  crpt_end.unloadCRPT(false, false, dstatus);
2049  }
2050  icptimer1.info("END " + run_num_string, dstatus);
2051  status.add(dstatus, true);
2052  return dstatus.result();
2053 }
2054 
2056 {
2057  ICPTimer icptimer1, icptimer2;
2059  {
2060  dstatus.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot END in SETUP");
2061  return DAEstatus::Failure;
2062  }
2063  ICPCritical cs(&m_crpt_cs);
2064  std::string run_num_string = Poco::format("%d", m_crpt->run_number);
2065  dstatus.addInfoVa(FAC_CRPT, "ENDing run %d", m_crpt->run_number);
2066  icptimer2.info("lockCRPT()", dstatus);
2067  icptimer2.start();
2068  updateCycle(dstatus);
2069  if (isRunning())
2070  {
2072  }
2073  m_dae->closeEventFiles(dstatus);
2074  logEvent(m_crpt->stop_time, m_crpt, "END", dstatus);
2075  icptimer2.info("stopDataCollection()", dstatus);
2076 
2077  icptimer2.start();
2078 
2080  m_crpt_signals.clear();
2081 
2082  m_crpt_run->updateFrom(m_crpt, false, dstatus);
2083 
2084  if (m_crpt->start_time < m_crpt->icp_start_time) // was icp restarted during run?
2085  {
2086  LOGSTR_INFORMATION("ICP has been restarted - fast end not possible");
2087  m_crpt_run->zeroUsedRawData(dstatus);
2088  }
2089 
2090  updateCRPTWithDAE(*m_crpt_run, false, dstatus);
2091 
2092  m_icpwriter.stop();
2093  std::string events_nxfile = m_icpwriter.filename();
2094  stopEventWriter(true, dstatus);
2095 
2096  setRunStatusImp(RUNSTATUS_SETUP, false, dstatus);
2097  m_crpt->software_period = 0;
2098  // After we have incremented the run number, all database log calls will do to the
2099  // new log file. We thus need to do as many outputs as possible before then
2100  // data written to text files does not see the new number until assignICPLogFiles()
2101  // is called
2102  ++(m_crpt->run_number);
2103  // we need to tell the selogger the new number and then clear out old values
2104  if (se_set_run_number(m_crpt->run_number) != 0)
2105  {
2106  dstatus.addInfoVa(FAC_DAE, "Error from SQLITE(se_set_run_number): %s", se_get_errmsg());
2107  }
2108  m_crpt->sav_file_count = 0;
2109  writeRecoveryFile(dstatus);
2110  m_crpt.assignLogFiles(m_use_full_inst_name_for_files, m_data_dir, m_run_number_digits); // this updates log files for new run number
2111  flushCRPT(dstatus);
2112  refreshCachedValues(dstatus);
2113  Poco::SharedPtr<Poco::Event> finish_event(new Poco::Event);
2114  GenericTask<int>* end_task = new GenericTask<int>("endRunMain " + run_num_string, finish_event,
2115  boost::bind(&ISISinstrumentControl::endRunTask, this, m_crpt_run, boost::ref(m_nxwriter),
2116  Poco::Util::Application::instance().config().getBool("isisicp.keepraweventfiles", false),
2117  Poco::Util::Application::instance().config().getBool("isisicp.keependcrpt", false),
2118  events_nxfile,
2119  boost::ref(m_status)));
2120  m_taskmgr.start(end_task);
2121  if ( !Poco::Util::Application::instance().config().getBool("isisicp.asyncend", false) )
2122  {
2123  finish_event->wait();
2124 // pollUntilTasksComplete(m_taskmgr, 200);
2125  }
2126 
2127  // create a new proxy for the next run
2128  m_crpt_run = new CRPTProxy();
2129  m_crpt_run->createFrom(m_crpt, m_crpt->run_number, true, dstatus);
2130  m_crpt_signals = m_dae->addGoodEventCallback(boost::bind(&CRPTProxy::histogramEventsToCRPT, boost::ref(m_crpt), boost::ref(*m_crpt_run), _1, _2, _3, _4));
2131 
2132  icptimer1.info("END " + run_num_string, dstatus);
2133  return dstatus.result();
2134 }
2135 
2136 
2137 // if process is true apply settings to CRPT, if false just load XML into recovery map
2139 {
2140  IXNeXusFile nx(nxErrorFunc, (void*)&dstatus);
2141  std::string xml_data;
2142  std::list<std::string> entries;
2143  std::list<std::string>::const_iterator entries_iter;
2144  std::pair<recovery_map_t::iterator, bool> insert_ret;
2145  m_recovery_map.clear();
2147  {
2148  dstatus.addWarningVa(FAC_DAE, "Failed to open recovery file %s\n", m_recovery_file.c_str());
2149  return DAEstatus::Failure;
2150  }
2151  if (nx.openGroup("icp_xml", "IXicp_xml") == IXNeXusFile::OK)
2152  {
2153  nx.listEntries(entries);
2154  for(entries_iter = entries.begin(); entries_iter != entries.end(); entries_iter++)
2155  {
2156  if (nx.readData(entries_iter->c_str(), xml_data) == IXNeXusFile::OK)
2157  {
2158  insert_ret = m_recovery_map.insert(recovery_map_t::value_type(*entries_iter, xml_data));
2159  if (!insert_ret.second)
2160  {
2161  dstatus.addWarningVa(FAC_DAE, "Found duplicate for %s in recovery map\n", entries_iter->c_str());
2162 // return DAEstatus::Failure; // duplicate
2163  }
2164  }
2165  }
2166  nx.closeGroup();
2167  }
2168  else
2169  {
2170  dstatus.addWarning(FAC_DAE, "Failed to recover icp_xml\n");
2171  }
2172  if (nx.openGroup("icp_pars", "IXicp_pars") == IXNeXusFile::OK)
2173  {
2174  nx.readData("run_number", m_crpt->run_number);
2175  nx.readData("sav_file_count", m_crpt->sav_file_count);
2176  nx.closeGroup();
2177  }
2178  else
2179  {
2180  dstatus.addWarning(FAC_DAE, "Failed to recover icp_pars\n");
2181  }
2182  nx.close();
2183 
2190  updateXML("monitoring", &ISISinstrumentControl::updateMonitoringXML, dstatus);
2191 
2193  dstatus.addWarningVa(FAC_DAE, "Recovered settings from file %s\n", m_recovery_file.c_str());
2194 
2195  return DAEstatus::Success;
2196 }
2197 
2198 int ISISinstrumentControl::updateXML(const char* name, xml_update_func_t func, DAEstatus& dstatus)
2199 {
2200  recovery_map_t::const_iterator recovery_iter;
2201  if ( (recovery_iter = m_recovery_map.find(name)) != m_recovery_map.end())
2202  {
2203  (this->*func)(recovery_iter->second, dstatus);
2204  }
2205  else
2206  {
2207  dstatus.addWarningVa(FAC_DAE, "Unable to find settings for %s in recovery map\n", name);
2208  }
2209  return DAEstatus::Success;
2210 }
2211 
2212 
2214 {
2215 
2216  IXNeXusFile nx(nxErrorFunc, (void*)&dstatus);
2217  recovery_map_t::const_iterator iter;
2218  remove(m_recovery_file.c_str());
2220  {
2221  return DAEstatus::Failure;
2222  }
2223  m_recovery_map["dae"] = m_crpt->lvxml_dae;
2224  m_recovery_map["tcb"] = m_crpt->lvxml_tcb;
2225  m_recovery_map["update"] = m_crpt->lvxml_update;
2226  m_recovery_map["periods"] = m_crpt->lvxml_periods;
2227  m_recovery_map["monitoring"] = m_crpt->lvxml_monitoring;
2228 
2229  nx.makeNewGroup("icp_xml", "IXicp_xml");
2230  for(iter = m_recovery_map.begin(); iter != m_recovery_map.end(); iter++)
2231  {
2232  nx.writeData(iter->first.c_str(), iter->second.c_str());
2233  }
2234  nx.closeGroup();
2235  nx.makeNewGroup("icp_pars", "IXicp_pars");
2236  nx.writeData("run_number", m_crpt->run_number);
2237  nx.writeData("sav_file_count", m_crpt->sav_file_count);
2238  nx.closeGroup();
2239  nx.close();
2240  return DAEstatus::Success;
2241 }
2242 
2244 {
2245  killProcess("isisdatasvr.exe", dstatus);
2246  return dstatus.result();
2247 }
2248 
2250 {
2251  HANDLE h;
2252  static std::string datasvr = m_icp_service_dir + "\\isisdatasvr.exe";
2253  spawnCommand(datasvr, "", false, false, &h, "", "", "", 0, dstatus); // launch suspended and return thread handle
2254  return h;
2255 }
2256 
2257 #if 0
2258 struct SendNagiosData
2259 {
2260  int status;
2261  std::string service;
2262  std::string message;
2263  DAEstatus& dstatus;
2264  SendNagiosData(int status_, const std::string& service_, const std::string& message_, DAEstatus& dstatus_) :
2265  status(status_), service(service_), message(message_), dstatus(dstatus_) { }
2266 };
2267 
2268  Poco::NotificationQueue m_queue;
2269  NeXusWorker m_worker;
2270  Poco::Thread m_worker_thread;
2271  m_queue.enqueueNotification(new GenericWorkNotification<NeXusWorkerData>(&d));
2272 
2273 
2274 class SendNagiosWorker : public GenericWorker<SendNagiosData>
2275 {
2276 public:
2277  virtual void doWork(SendNagiosData* data);
2278  SendNagiosWorker(Poco::NotificationQueue& queue) : GenericWorker<SendNagiosData>(queue) { }
2279 };
2280 #endif /* if 0 */
2281 
2282 // HOST\tservice\treturncode\tmessage\n
2283 // return code is 0 for OK, 1 for WARNING, 2 for CRITICAL, 3 for UNKNOWN
2284 // message can contain performance data
2285 // CRITICAL - cannot do
2286 // PING OK - hello |
2287 int ISISinstrumentControl::sendNagios(int status, const std::string& service, const std::string& message, DAEstatus& dstatus)
2288 {
2289  static const bool use_nagios = m_app->config().getBool("isisicp.nagios.use", false);
2290  static const int nagios_timeout = m_app->config().getInt("isisicp.nagios.timeout", 5);
2291  static const std::string nagios_host = m_app->config().getString("isisicp.nagios.host","130.246.39.24");
2292  static const std::string send_nsca = m_icp_service_dir + "\\send_nsca.exe";
2293  static const std::string send_nsca_cfg = m_icp_service_dir + "\\send_nsca.cfg";
2294  static const std::string send_nsca_args = std::string("-H ") + nagios_host + " -c \"" + send_nsca_cfg + "\"";
2295  char* tfile = tempnam(getenv("TEMP"), "send_nsca");
2296  if (tfile == NULL)
2297  {
2298  dstatus.addWarningVa(FAC_DAE, "sendNagios: cannot create temp file");
2299  return DAEstatus::Failure;
2300  }
2301  std::string temp_file = tfile;
2302  std::ostringstream nagios_mess;
2303  free(tfile);
2304  std::fstream f;
2305  f.open(temp_file, std::ios::out);
2306  if (f.good())
2307  {
2308  nagios_mess << m_comp_name << '\t' << service << '\t' << status << '\t' << message << '\n';
2309  f << nagios_mess.str();
2310  f.close();
2311  if (use_nagios)
2312  {
2313  spawnCommand(send_nsca, send_nsca_args, false, false, NULL, temp_file, "", "", nagios_timeout, dstatus);
2314  }
2315  else
2316  {
2317 // dstatus.addInfoVa(FAC_DAE, "sendNagios: %s", nagios_mess.str().c_str());
2318  }
2319  }
2320  else
2321  {
2322  dstatus.addWarningVa(FAC_DAE, "sendNagios: cannot open temp file");
2323  }
2324  remove(temp_file.c_str());
2325  return DAEstatus::Success;
2326 }
2327 
2328 static bool getBeamlogFloat(Poco::XML::Document* pDoc, const std::string& path, float& value)
2329 {
2330  Poco::XML::Node* pNode = pDoc->getNodeByPath(path);
2331  if (pNode != NULL)
2332  {
2333  value = atof(pNode->innerText().c_str());
2334 // pNode->release();
2335  return true;
2336  }
2337  return false;
2338 }
2339 
2340 static bool getBeamlogInt(Poco::XML::Document* pDoc, const std::string& path, int& value)
2341 {
2342  Poco::XML::Node* pNode = pDoc->getNodeByPath(path);
2343  if (pNode != NULL)
2344  {
2345  value = atoi(pNode->innerText().c_str());
2346 // pNode->release();
2347  return true;
2348  }
2349  return false;
2350 }
2351 
2352 static bool getBeamlogInt64(Poco::XML::Document* pDoc, const std::string& path, int64_t& value)
2353 {
2354  Poco::XML::Node* pNode = pDoc->getNodeByPath(path);
2355  if (pNode != NULL)
2356  {
2357  value = _atoi64(pNode->innerText().c_str());
2358 // pNode->release();
2359  return true;
2360  }
2361  return false;
2362 }
2363 
2364 static bool getBeamlogString(Poco::XML::Document* pDoc, const std::string& path, std::string& value)
2365 {
2366  Poco::XML::Node* pNode = pDoc->getNodeByPath(path);
2367  if (pNode != NULL)
2368  {
2369  value = pNode->innerText();
2370 // pNode->release();
2371  return true;
2372  }
2373  return false;
2374 }
2375 
2377 {
2378  static char buffer[10000];
2379  static const int NBEAMREAD = 3;
2380  Poco::Net::DatagramSocket ds_recv;
2381  Poco::Net::SocketAddress sa_recv("0.0.0.0", 7004);
2382  Poco::Timespan recv_tmo(15,0);
2384  memset(&bl, 0, sizeof(beamlogger_t));
2385  try
2386  {
2387  ds_recv.setReceiveTimeout(recv_tmo);
2388  ds_recv.bind(sa_recv);
2389  }
2390  catch(const std::exception& ex)
2391  {
2392  LOGSTR_ERROR("readBeamloggerBroadcast: " << ex.what());
2393  return;
2394  }
2395  int n, ts = 1;
2396  unsigned nbeamz = 0, nbeamnz = 0;
2397  std::string shutter_status("OPEN"); // muons on ts1 and have no shutter
2398  bl.beam_on = false;
2399  bl.valid = false;
2400  bl.time = 0;
2401  time(&bl.beam_off_time);
2402  while(true)
2403  {
2404  try
2405  {
2406  if (difftime(time(NULL), bl.time) > 10.0)
2407  {
2408  bl.valid = false;
2409  }
2410  else
2411  {
2412  bl.valid = true;
2413  }
2414  n = ds_recv.receiveBytes(buffer, sizeof(buffer)-1);
2415  if (n <= 0)
2416  {
2417  LOGSTR_ERROR("readBeamloggerBroadcast: received " << n);
2418  Poco::Thread::sleep(10 * 1000);
2419  continue;
2420  }
2421  buffer[n] = '\0';
2422  std::stringstream inp;
2423  inp << buffer;
2425  Poco::XML::InputSource xml_src(inp);
2426  Poco::XML::DOMParser parser;
2427  Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parse(&xml_src);
2428  if (getBeamlogString(pDoc, std::string("TS1SHUTTERS/") + m_crpt->inst_name, shutter_status))
2429  {
2430  ts = 1;
2431  }
2432  else if (getBeamlogString(pDoc, std::string("TS2SHUTTERS/") + m_crpt->inst_name, shutter_status))
2433  {
2434  ts = 2;
2435  }
2436  bl.ts = ts;
2437  if ("OPEN" == shutter_status)
2438  {
2439  bl.shutter = 1;
2440  }
2441  else if ("CLOSED" == shutter_status)
2442  {
2443  bl.shutter = 0;
2444  }
2445  getBeamlogInt64(pDoc, "TIME", bl.time);
2446  getBeamlogFloat(pDoc, "BEAMS", bl.beams);
2447  getBeamlogInt(pDoc, "REPR", bl.ts1_repr);
2448  getBeamlogInt(pDoc, "MUONKICKER", bl.muonkicker);
2449  if (1 == ts)
2450  {
2451  getBeamlogFloat(pDoc, "BEAMT", bl.beamt);
2452  getBeamlogInt(pDoc, "REPR", bl.repr);
2453  getBeamlogFloat(pDoc, "TS1_TOTAL", bl.ts_total);
2454  bl.repr_normal = (bl.repr >= 40);
2455  }
2456  else if (2 == ts)
2457  {
2458  getBeamlogFloat(pDoc, "BEAMT2", bl.beamt);
2459  getBeamlogInt(pDoc, "REPR2", bl.repr);
2460  getBeamlogFloat(pDoc, "TS2_TOTAL", bl.ts_total);
2461  bl.repr_normal = (bl.repr >= 10);
2462  }
2463  if (bl.beamt <= 0.0)
2464  {
2465  ++nbeamz;
2466  nbeamnz = 0;
2467  }
2468  else
2469  {
2470  nbeamz = 0;
2471  ++nbeamnz;
2472  }
2473  if (bl.beam_on && nbeamz > NBEAMREAD)
2474  {
2475  bl.beam_on = false;
2476  bl.beam_off_time = bl.time;
2477  LOGSTR_INFORMATION("readBeamloggerBroadcast: BEAM OFF");
2478  }
2479  else if (!bl.beam_on && nbeamnz > NBEAMREAD)
2480  {
2481  bl.beam_on = true;
2482  bl.beam_on_time = bl.time;
2483  LOGSTR_INFORMATION("readBeamloggerBroadcast: BEAM ON");
2484  }
2485  }
2486  catch(const std::exception& ex)
2487  {
2488  LOGSTR_ERROR("readBeamloggerBroadcast: " << ex.what());
2489  Poco::Thread::sleep(10 * 1000);
2490  }
2491  }
2492 }
2493 
2494 bool ISISinstrumentControl::beamOn(int minutes) const
2495 {
2496  const beamlogger_t& bl = m_crpt->beamlogger;
2497  if (bl.beam_on && bl.repr_normal && difftime(time(NULL), bl.beam_on_time) > 60 * minutes)
2498  {
2499  return true;
2500  }
2501  else
2502  {
2503  return false;
2504  }
2505 }
2506 
2508 {
2509  const beamlogger_t& bl = m_crpt->beamlogger;
2510  return bl.muonkicker > 0 ? true : false;
2511 }
2512 
2513 // spawn a background command
2514 int ISISinstrumentControl::spawnCommand(const std::string& program, const std::string& args, bool use_cmd_exe, bool console, HANDLE* suspended_thread_handle,
2515  const std::string& std_in_file, const std::string& std_out_file, const std::string& std_error_file, int wait_time, DAEstatus& dstatus)
2516 {
2517  char command_line[MAX_PATH];
2518  SECURITY_ATTRIBUTES proc_attr;
2519  DWORD proc_create_flags = 0;
2520  BOOL inherit_handles = FALSE;
2521  ZeroMemory( &proc_attr, sizeof(proc_attr) );
2522  PROCESS_INFORMATION pi;
2523  ZeroMemory( &pi, sizeof(pi) );
2524  if (use_cmd_exe)
2525  {
2526  _snprintf(command_line, sizeof(command_line), "\"%s\" /c \"%s\" %s", getenv("ComSpec"), program.c_str(), args.c_str());
2527  }
2528  else
2529  {
2530  _snprintf(command_line, sizeof(command_line), "\"%s\" %s", program.c_str(), args.c_str());
2531  }
2532  NULL_TERMINATE(command_line);
2533  STARTUPINFO si;
2534  ZeroMemory( &si, sizeof(si) );
2535  si.cb = sizeof(si);
2536  HANDLE proc_stdin = INVALID_HANDLE_VALUE;
2537  HANDLE proc_stdout = INVALID_HANDLE_VALUE;
2538  HANDLE proc_stderr = INVALID_HANDLE_VALUE;
2539  if (suspended_thread_handle != NULL)
2540  {
2541  proc_create_flags |= CREATE_SUSPENDED;
2542  *suspended_thread_handle = NULL;
2543  }
2544  if (console)
2545  {
2546  si.dwFlags = STARTF_USESHOWWINDOW;
2547  si.wShowWindow = SW_MINIMIZE;
2548  proc_create_flags |= CREATE_NEW_CONSOLE;
2549  }
2550  else
2551  {
2552  si.dwFlags |= STARTF_USESTDHANDLES;
2553  proc_attr.bInheritHandle = TRUE; // Process handle inheritable - needed to use STARTF_USESTDHANDLES
2554  inherit_handles = TRUE;
2555  if (std_out_file.size() > 0)
2556  {
2557  proc_stdout = CreateFile(std_out_file.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &proc_attr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2558  SetFilePointer(proc_stdout, 0, NULL, FILE_END);
2559  }
2560  else
2561  {
2562  DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE), GetCurrentProcess(), &proc_stdout, 0, TRUE, DUPLICATE_SAME_ACCESS);
2563  }
2564  if (std_error_file.size() > 0)
2565  {
2566  if (std_error_file == std_out_file)
2567  {
2568  DuplicateHandle(GetCurrentProcess(), proc_stdout, GetCurrentProcess(), &proc_stderr, 0, TRUE, DUPLICATE_SAME_ACCESS);
2569  }
2570  else
2571  {
2572  proc_stderr = CreateFile(std_error_file.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &proc_attr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2573  SetFilePointer(proc_stderr, 0, NULL, FILE_END);
2574  }
2575  }
2576  else
2577  {
2578  DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &proc_stderr, 0, TRUE, DUPLICATE_SAME_ACCESS);
2579  }
2580  if (std_in_file.size() > 0)
2581  {
2582  proc_stdin = CreateFile(std_in_file.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &proc_attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2583  }
2584  else
2585  {
2586  DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), GetCurrentProcess(), &proc_stdin, 0, TRUE, DUPLICATE_SAME_ACCESS);
2587  }
2588  si.hStdInput = proc_stdin;
2589  si.hStdOutput = proc_stdout;
2590  si.hStdError = proc_stderr;
2591  }
2592  // Start the child process.
2593  if(CreateProcess(NULL,
2594  command_line, // Command line.
2595  &proc_attr,
2596  NULL, // Thread handle not inheritable.
2597  inherit_handles, // Set handle inheritance
2598  proc_create_flags, // creation flags.
2599  NULL, // Use parent's environment block.
2600  NULL, // Use parent's starting directory.
2601  &si, // Pointer to STARTUPINFO structure.
2602  &pi ) // Pointer to PROCESS_INFORMATION structure.
2603  )
2604  {
2605  if (wait_time > 0)
2606  {
2607  DWORD ret = WaitForSingleObject(pi.hProcess, wait_time * 1000);
2608  if (ret == WAIT_TIMEOUT)
2609  {
2610  dstatus.addInfoVa(FAC_DAE, "Timout after waiting %d seconds for %s.", wait_time, command_line);
2611  }
2612  else if (ret != WAIT_OBJECT_0)
2613  {
2614  dstatus.addInfoVa(FAC_DAE, "Error waiting for %s.", command_line);
2615  }
2616  else
2617  {
2618  DWORD exit_code;
2619  if (GetExitCodeProcess(pi.hProcess, &exit_code) != 0)
2620  {
2621  if (exit_code != 0)
2622  {
2623  dstatus.addInfoVa(FAC_DAE, "Process exit code %d for %s", exit_code, command_line);
2624  }
2625  }
2626  else
2627  {
2628  dstatus.addInfoVa(FAC_DAE, "GetExitCodeProcess() failed for %s", command_line);
2629  }
2630  }
2631  }
2632  CloseHandle(pi.hProcess);
2633  if (suspended_thread_handle != NULL)
2634  {
2635  *suspended_thread_handle = pi.hThread;
2636  }
2637  else
2638  {
2639  CloseHandle(pi.hThread);
2640  }
2641  CloseHandle(proc_stdin);
2642  CloseHandle(proc_stdout);
2643  CloseHandle(proc_stderr);
2644  }
2645  else
2646  {
2647  dstatus.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "CreateProcess failed for %s.", command_line);
2648  }
2649  return dstatus.result();
2650 }
2651 
2652 int ISISinstrumentControl::killProcess(const char* process_name, DAEstatus& dstatus)
2653 {
2654  DWORD aProcesses[1024], cbNeeded, cProcesses;
2655  unsigned int i;
2656  std::string name;
2657 
2658  if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
2659  return -1;
2660 
2661  // Calculate how many process identifiers were returned.
2662 
2663  cProcesses = cbNeeded / sizeof(DWORD);
2664 
2665  // Print the name and process identifier for each process.
2666 
2667  for ( i = 0; i < cProcesses; i++ )
2668  {
2669  if( aProcesses[i] != 0 )
2670  {
2671  name = getProcessName( aProcesses[i] );
2672  if (name == process_name)
2673  {
2674  HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, aProcesses[i]);
2675  if (hProcess != NULL)
2676  {
2677  TerminateProcess(hProcess, 0);
2678  CloseHandle(hProcess);
2679  }
2680  }
2681  }
2682  }
2683 
2684  return 0;
2685 
2686 }
2687 
2688 std::string ISISinstrumentControl::getProcessName( DWORD processID )
2689 {
2690  std::string result;
2691  TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
2692 
2693  // Get a handle to the process.
2694 
2695  HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
2696  PROCESS_VM_READ,
2697  FALSE, processID );
2698 
2699  // Get the process name.
2700  if (NULL != hProcess )
2701  {
2702  HMODULE hMod;
2703  DWORD cbNeeded;
2704 
2705  if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
2706  {
2707  GetModuleBaseName( hProcess, hMod, szProcessName,
2708  sizeof(szProcessName)/sizeof(TCHAR) );
2709  }
2710  CloseHandle( hProcess );
2711  }
2712 
2713  result = szProcessName;
2714  return result;
2715 
2716 }
2717 
2718 
2719 // Number of detectors Number of monitors :
2720 // 165891 4
2721 // Index Det. no. time reg. crate module posn. monitor mon.prescale
2722 // 1 11101001 1 1 0 0 0 0
2723 // 2 11101002 1 1 0 1 0 0
2724 
2725 
2726 // if table is loaded, marks detector and spectra tables as bad so sould only be called from readTables()
2727 int ISISinstrumentControl::readWiringTable(const char* filename, DAEstatus& status)
2728 {
2729  int ndet, nmon, i, j, exit_status = DAEstatus::Success;
2730  md5checksum_t checksum;
2731  struct stat stat_struct;
2732  RUNTABLE& wiring_table = m_crpt->wiring_table;
2733  RUNTABLE& detector_table = m_crpt->detector_table;
2734  RUNTABLE& spectra_table = m_crpt->spectra_table;
2735  typedef std::map<unsigned,unsigned> wiring_map_t;
2736  typedef std::pair<wiring_map_t::iterator,bool> wiring_insert_t;
2737  wiring_map_t::const_iterator wiring_iterator;
2738  wiring_map_t wiring_map, crate_map;
2739  wiring_insert_t insert_ret;
2740 
2741  int *index, *det_no, *time_reg, *crate, *module, *mpos, *monitor, *mon_prescale;
2742  if ( stat(filename, &stat_struct) != 0 )
2743  {
2744  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot open wiring table %s", filename);
2745  return DAEstatus::Failure;
2746  }
2747  md5sumFile(filename, checksum, status);
2748  if ( (strncmp(wiring_table.fname, filename, sizeof(wiring_table.fname)) == 0) &&
2749  (wiring_table.mod_time == stat_struct.st_mtime) &&
2750  (wiring_table.file_size == stat_struct.st_size) &&
2751  compareChecksums(wiring_table.checksum, checksum) )
2752  {
2753  status.addInfoVa(FAC_DAE, "Wiring table %s is unchanged - reload skipped", filename);
2754  return DAEstatus::Success;
2755  }
2756  std::ifstream f;
2757  f.open(filename, std::ios::in);
2758  f.ignore(50000, '\n'); // skip line "number of detectors ..."
2759  f >> ndet >> nmon;
2760  if (!f.good())
2761  {
2762  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error reading ndet and nmon from wiring table %s", filename);
2763  return DAEstatus::Failure;
2764  }
2765  if ( (ndet <= 0) || (ndet > ISISCRPT_MAX_DETECTOR) )
2766  {
2767  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid ndet = %d from wiring table %s (too big?)", ndet, filename);
2768  return DAEstatus::Failure;
2769  }
2770  if ( (nmon < 0) || (nmon > ISISCRPT_MAX_MONITOR) )
2771  {
2772  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid nmon = %d from wiring table %s (too big?)", nmon, filename);
2773  return DAEstatus::Failure;
2774  }
2775  index = new int[ndet];
2776  det_no = new int[ndet];
2777  time_reg = new int[ndet];
2778  crate = new int[ndet];
2779  module = new int[ndet];
2780  mpos = new int[ndet];
2781  monitor = new int[ndet];
2782  mon_prescale = new int[ndet];
2783  f.ignore(50000, '\n'); // skip rest of line
2784  f.ignore(50000, '\n'); // skip line "index det no ..."
2785  // module (dim) is 0-15, mpos is 0 - 4095 and crate is 0-15
2786  // so 12bits mpos, 4bit dim, 4bit crate
2787  unsigned crate_index;
2788  for(i=0; i<ndet && f.good(); i++)
2789  {
2790  f >> index[i] >> det_no[i] >> time_reg[i] >> crate[i]
2791  >> module[i] >> mpos[i] >> monitor[i] >> mon_prescale[i];
2792  f.ignore(50000, '\n'); // skip rest of line
2793  if (index[i] != i+1)
2794  {
2795  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid index for det number %d in wiring table %s - should be %d", det_no[i], filename, i+1);
2796  return DAEstatus::Failure;
2797  }
2798  if ( (crate[i] % DAE2CardPolicy::CRATE_MOD) > 15 || module[i] > 15 || mpos[i] > 4095 )
2799  {
2800  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid crate/module/position (%d/%d/%d) for det number %d in wiring table %s ",
2801  crate[i], module[i], mpos[i], det_no[i], filename);
2802  return DAEstatus::Failure;
2803  }
2804  crate_index = ( (crate[i] << 16) | (module[i] << 12) | mpos[i] );
2805  insert_ret = wiring_map.insert(wiring_map_t::value_type(det_no[i],crate_index));
2806  if (!insert_ret.second)
2807  {
2808  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error duplicate detector number %d near line %d in wiring table %s", det_no[i], i, filename);
2809  return DAEstatus::Failure;
2810  }
2811  insert_ret = crate_map.insert(wiring_map_t::value_type(crate_index,det_no[i]));
2812  if (!insert_ret.second)
2813  {
2814  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error duplicate crate/module/position for det number %d near line %d in wiring table %s", det_no[i], i, filename);
2815  return DAEstatus::Failure;
2816  }
2817  // just for debuggubng REMOVE
2818  // crate[i] = 1;
2819  }
2820  if (!f.good())
2821  {
2822  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error near line %d from wiring table %s", i, filename);
2823  return DAEstatus::Failure;
2824  }
2825  // detectors
2826  ICPCritical cs(&m_crpt_cs);
2827  m_crpt->ndet = ndet;
2828  memcpy(m_crpt->crat, crate, ndet*sizeof(int));
2829  memcpy(m_crpt->modn, module, ndet*sizeof(int));
2830  memcpy(m_crpt->mpos, mpos, ndet*sizeof(int));
2831  for(i=0; i<ndet; ++i)
2832  {
2833  m_crpt->timr_crpt[i] = m_crpt->crptTR(time_reg[i]);
2834  m_crpt->timr_dae[i] = m_crpt->daeTR(time_reg[i]);
2835  m_crpt->timr_file[i] = m_crpt->fileTR(time_reg[i]);
2836  m_crpt->det_mode[i] = m_crpt->isEventTR(time_reg[i]);
2837  }
2838  memcpy(m_crpt->udet, det_no, ndet*sizeof(int));
2839 
2840  // monitors
2841  m_crpt->nmon = nmon;
2842  memset(m_crpt->mdet.c_array(), 0, ISISCRPT_MAX_MONITOR*sizeof(int));
2843  memset(m_crpt->monp.c_array(), 0, ISISCRPT_MAX_MONITOR*sizeof(int));
2844  memset(m_crpt->save_monitor_events.c_array(), 0, ISISCRPT_MAX_MONITOR*sizeof(int));
2845  m_crpt->det_group_max = 0;
2846  for(i=0; i<ndet; i++)
2847  {
2848  j = abs(monitor[i]); // we use a negative monitor number to mean not to save events
2849  if (j > 0) // 0 means it is not a monitor
2850  {
2851  if (j > nmon)
2852  {
2853  exit_status = DAEstatus::Failure;
2854  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid monitor number %d (>%d) in wiring table %s", j, nmon, filename);
2855  }
2856  else if (m_crpt->mdet[j-1] == 0)
2857  {
2858  m_crpt->mdet[j-1] = index[i]; // mdet starts at 1 for historical (fortran) reasons (index[i] == i+1)
2859  m_crpt->monp[j-1] = mon_prescale[i];
2860  }
2861  else
2862  {
2863  exit_status = DAEstatus::Failure;
2864  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Monitor number %d defined multiple times in wiring table %s", j, filename);
2865  }
2866  m_crpt->save_monitor_events[j-1] = (monitor[i] > 0 ? 1 : 0);
2867  m_crpt->det_group[i] = 0;
2868  }
2869  else
2870  {
2871  m_crpt->det_group[i] = 1 /* m_crpt->timr[i] */;
2873  }
2874  }
2875  for(i=0; i<m_crpt->nmon; i++)
2876  {
2877  if (m_crpt->mdet[i] == 0)
2878  {
2879  status.addWarningVa(FAC_DAE, "Monitor %d is not properly defined in wiring table %s", i+1, filename);
2880  }
2881  }
2882  if (exit_status == DAEstatus::Success)
2883  {
2884  // update wiring table information
2885  strncpy(wiring_table.fname, filename, sizeof(wiring_table.fname));
2886  NULL_TERMINATE(wiring_table.fname);
2887  memcpy(wiring_table.checksum, checksum, sizeof(wiring_table.checksum));
2888  wiring_table.mod_time = stat_struct.st_mtime;
2889  wiring_table.file_size = stat_struct.st_size;
2890  status.addInfoVa(FAC_DAE, "Loaded %d detectors (%d monitors) from wiring table %s", ndet, nmon, filename);
2891  }
2892  else
2893  {
2894  wiring_table.file_size = wiring_table.mod_time = 0;
2895  memset(wiring_table.checksum, 0, sizeof(wiring_table.checksum));
2896  }
2897 
2898  // force subsequent reload of detector and spectra tables by marking them bad
2899  detector_table.file_size = detector_table.mod_time = 0;
2900  memset(detector_table.checksum, 0, sizeof(detector_table.checksum));
2901  spectra_table.file_size = spectra_table.mod_time = 0;
2902  memset(spectra_table.checksum, 0, sizeof(spectra_table.checksum));
2903 
2904  delete []index;
2905  delete []det_no;
2906  delete []time_reg;
2907  delete []crate;
2908  delete []module;
2909  delete []mpos;
2910  delete []monitor;
2911  delete []mon_prescale;
2912 
2913  return exit_status;
2914 }
2915 
2916 
2917 int ISISinstrumentControl::readDetectorTable(const char* filename, DAEstatus& status)
2918 {
2919  int i, j, nlines, nuse, det_no, exit_status = DAEstatus::Success;
2920  struct stat stat_struct;
2921  md5checksum_t checksum;
2922  typedef std::map<int,DETECTOR> detector_map_t;
2923  typedef std::pair<detector_map_t::iterator,bool> detector_insert_t;
2924  detector_map_t detector_map;
2925  detector_map_t::const_iterator detector_iterator;
2926  std::set<unsigned> udet_set;
2927  RUNTABLE& detector_table = m_crpt->detector_table;
2928  if ( stat(filename, &stat_struct) != 0 )
2929  {
2930  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot open detector table \"%s\"", filename);
2931  return DAEstatus::Failure;
2932  }
2933  md5sumFile(filename, checksum, status);
2934  if ( (strncmp(detector_table.fname, filename, sizeof(detector_table.fname)) == 0) &&
2935  (detector_table.mod_time == stat_struct.st_mtime) &&
2936  (detector_table.file_size == stat_struct.st_size) &&
2937  compareChecksums(detector_table.checksum, checksum) )
2938  {
2939  status.addInfoVa(FAC_DAE, "Detector table \"%s\" is unchanged - reload skipped", filename);
2940  return DAEstatus::Success;
2941  }
2942  for(i=0; i<m_crpt->ndet; ++i)
2943  {
2944  udet_set.insert(m_crpt->udet[i]);
2945  }
2946  Poco::SharedPtr<IDetectorFile> det_file;
2947  std::string det_filename(filename);
2948  // if filename ends in .nxs assume it is a mantid calibration file
2949  if ( (det_filename.size() > 4) && !Poco::icompare(det_filename.substr(det_filename.size() - 4), ".nxs") )
2950  {
2951  det_file = new DetectorFileMantid(filename);
2952  }
2953  else
2954  {
2955  det_file = new DetectorFileASCII(filename);
2956  }
2957  if (!det_file->good())
2958  {
2959  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error reading ndet and nuse from detector table %s", filename);
2960  return DAEstatus::Failure;
2961  }
2962  nlines = det_file->numLines();
2963  nuse = det_file->numUserTables();
2964  if ( (nuse < 0) || (nuse > ISISCRPT_MAX_USER) )
2965  {
2966  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid nuse = %d from detector table %s (too big?)", nuse, filename);
2967  return DAEstatus::Failure;
2968  }
2969  DETECTOR det;
2970  DETECTOR& det_ref = det;
2971  detector_insert_t insert_ret;
2972  int n_extra_dets = 0;
2973  for(i=0; i<nlines && det_file->good(); i++)
2974  {
2975  det_file->readLine(det_no, det);
2976  insert_ret = detector_map.insert(detector_map_t::value_type(det_no,det));
2977  if (!insert_ret.second)
2978  {
2979  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error duplicate near line %d, det number %d from detector table %s", i, det_no, filename);
2980  return DAEstatus::Failure;
2981  }
2982  if (udet_set.count(det_no) == 0)
2983  {
2984  ++n_extra_dets;
2985  }
2986  }
2987  if (n_extra_dets > 0)
2988  {
2989  status.addWarningVa(FAC_DAE, "%d detectors defined in detector table %s but not in wiring table", n_extra_dets, filename);
2990  }
2991  if (!det_file->good())
2992  {
2993  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error near line %d from detector table %s", i, filename);
2994  return DAEstatus::Failure;
2995  }
2996  if (detector_map.size() != nlines)
2997  {
2998  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Detector table %s does not specify enough values", filename);
2999  return DAEstatus::Failure;
3000  }
3001  ICPCritical cs(&m_crpt_cs);
3002  m_crpt->nuse = nuse;
3003  DETECTOR empty_det;
3004  for(i=0; i < m_crpt->ndet; i++)
3005  {
3006  detector_iterator = detector_map.find(m_crpt->udet[i]);
3007  if (detector_iterator != detector_map.end())
3008  {
3009  det_ref = detector_iterator->second;
3010  }
3011  else
3012  {
3013  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Detector %d missing from detector table %s", m_crpt->udet[i], filename);
3014  det_ref = empty_det;
3015  exit_status = DAEstatus::Failure;
3016  break; // exit early as ndet can be quite big and we may have a lot of errors
3017  }
3018  m_crpt->delt[i] = det_ref.offset;
3019  m_crpt->code[i] = det_ref.code;
3020  m_crpt->len2[i] = det_ref.l2;
3021  m_crpt->tthe[i] = det_ref.theta;
3022  for(j=0; j<nuse; j++)
3023  {
3024  m_crpt->ut[j*m_crpt->ndet + i] = det_ref.ut[j];
3025  }
3026  }
3027  if (exit_status == DAEstatus::Success)
3028  {
3029  // update wiring table information
3030  strncpy(detector_table.fname, filename, sizeof(detector_table.fname));
3031  NULL_TERMINATE(detector_table.fname);
3032  memcpy(detector_table.checksum, checksum, sizeof(detector_table.checksum));
3033  detector_table.mod_time = stat_struct.st_mtime;
3034  detector_table.file_size = stat_struct.st_size;
3035  status.addInfoVa(FAC_DAE, "Loaded %d detectors with %d user tables from detector table %s", m_crpt->ndet, nuse, filename);
3036  DetectorFileMantid* dfm = dynamic_cast<DetectorFileMantid*>(det_file.get());
3037  if (dfm != NULL)
3038  {
3039  if ( !Poco::icompare(dfm->instName(), static_cast<const char*>(m_crpt->inst_name)) )
3040  {
3041  status.addWarningVa(FAC_DAE, "Mismatch in instrument names for detector file: \"%s\" != \"%s\"", dfm->instName().c_str(), m_crpt->inst_name);
3042  LOGSTR_WARNING("Mismatch in instrument names for detector file: \"" << dfm->instName() << "\" != \"" << m_crpt->inst_name << "\"");
3043  }
3044  strncpy(m_crpt->instrument_xml_file, dfm->instXMLFileName().c_str(), sizeof(m_crpt->instrument_xml_file));
3046  std::fstream fs(m_instrument_xml_file, std::ios::out | std::ios::trunc);
3047  fs << dfm->instXML();
3048  fs.close();
3051  std::fstream fs1(m_instrument_parameter_map_file, std::ios::out | std::ios::trunc);
3052  fs1 << dfm->instParameterMap();
3053  fs1.close();
3054  }
3055  else
3056  {
3057  m_crpt->instrument_xml_file[0] = '\0';
3058  std::remove(m_instrument_xml_file.c_str());
3060  std::remove(m_instrument_parameter_map_file.c_str());
3061  }
3062  }
3063  else
3064  {
3065  detector_table.file_size = detector_table.mod_time = 0;
3066  memset(detector_table.checksum, 0, sizeof(detector_table.checksum));
3067  }
3068  return exit_status;
3069 }
3070 
3071 //NDET :
3072 // 73740
3073 //DETECTOR SPECTRUM
3074 // 1000001 577
3075 // 1000002 578
3076 // 1000003 579
3077 
3078 int ISISinstrumentControl::readSpectraTable(const char* filename, DAEstatus& status)
3079 {
3080  int i, nlines, spec_no, det_no, max_spec_no, exit_status = DAEstatus::Success;
3081  md5checksum_t checksum;
3082  struct stat stat_struct;
3083  typedef std::map<int,int> spectra_map_t;
3084  typedef std::pair<spectra_map_t::iterator,bool> spectra_insert_t;
3085  spectra_map_t spectra_map;
3086  std::set<unsigned> udet_set;
3087  spectra_map_t::const_iterator spectra_iterator;
3088  RUNTABLE& spectra_table = m_crpt->spectra_table;
3089  if ( stat(filename, &stat_struct) != 0 )
3090  {
3091  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot open spectra table %s", filename);
3092  return DAEstatus::Failure;
3093  }
3094  md5sumFile(filename, checksum, status);
3095  if ( (strncmp(spectra_table.fname, filename, sizeof(spectra_table.fname)) == 0) &&
3096  (spectra_table.mod_time == stat_struct.st_mtime) &&
3097  (spectra_table.file_size == stat_struct.st_size) &&
3098  compareChecksums(spectra_table.checksum, checksum) )
3099  {
3100  status.addInfoVa(FAC_DAE, "Spectra table %s is unchanged - reload skipped", filename);
3101  return DAEstatus::Success;
3102  }
3103  for(i=0; i<m_crpt->ndet; ++i)
3104  {
3105  udet_set.insert(m_crpt->udet[i]);
3106  }
3107  std::ifstream f;
3108  f.open(filename, std::ios::in);
3109  f.ignore(50000, '\n'); // skip line "number of detectors ..."
3110  f >> nlines;
3111  if (!f.good())
3112  {
3113  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error reading nlines from spectra table %s", filename);
3114  return DAEstatus::Failure;
3115  }
3116  f.ignore(50000, '\n'); // skip rest of line
3117  f.ignore(50000, '\n'); // skip next line
3118  spectra_insert_t insert_ret;
3119  for(i=0; i<nlines && f.good(); i++)
3120  {
3121  f >> det_no >> spec_no;
3122  f.ignore(50000, '\n'); // skip rest of line
3123  if (spec_no >= ISISCRPT_MAX_DETECTOR)
3124  {
3125  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid spectrum number %d >= %d from spectra table %s", spec_no, ISISCRPT_MAX_DETECTOR, filename);
3126  return DAEstatus::Failure;
3127  }
3128  if (udet_set.count(det_no) == 0)
3129  {
3130  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid detector number %d from spectra table %s", det_no, filename);
3131  return DAEstatus::Failure;
3132  }
3133  insert_ret = spectra_map.insert(spectra_map_t::value_type(det_no,spec_no));
3134  if (!insert_ret.second)
3135  {
3136  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error duplicate near line %d from spectra table %s", i, filename);
3137  return DAEstatus::Failure;
3138  }
3139  }
3140  if (!f.good())
3141  {
3142  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error near line %d from spectra table %s", i, filename);
3143  return DAEstatus::Failure;
3144  }
3145  if (spectra_map.size() != nlines)
3146  {
3147  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error near line %d from spectra table %s", i, filename);
3148  return DAEstatus::Failure;
3149  }
3150  ICPCritical cs(&m_crpt_cs);
3151  max_spec_no = 0;
3152  boost::array<int,ISISCRPT_MAX_NTRG>& spec_min = m_crpt->spec_min;
3153  boost::array<int,ISISCRPT_MAX_NTRG>& spec_max = m_crpt->spec_max;
3154  const int SPEC_MIN_FILLER=10000000, SPEC_MAX_FILLER=-1;
3155  spec_min.fill(SPEC_MIN_FILLER);
3156  spec_max.fill(SPEC_MAX_FILLER);
3157  int n_unassigned_detectors = 0;
3158  m_crpt->spec_to_index.fill(0);
3159  boost::array<std::set<int>,ISISCRPT_MAX_NTRG> spec_tr;
3160  for(i=0; i < m_crpt->ndet; i++)
3161  {
3162  spectra_iterator = spectra_map.find(m_crpt->udet[i]);
3163  int tr_index = m_crpt->timr_crpt[i] - 1;
3164  if (spectra_iterator != spectra_map.end())
3165  {
3166  spec_no = spectra_iterator->second;
3167  }
3168  else
3169  {
3170  spec_no = 0;
3171  n_unassigned_detectors++;
3172  }
3173  m_crpt->spec[i] = spec_no;
3174  max_spec_no = std::max(spec_no, max_spec_no);
3175  if (spec_no > 0)
3176  {
3177  spec_tr[tr_index].insert(spec_no);
3178  spec_min[tr_index] = std::min(spec_no, spec_min[tr_index]);
3179  spec_max[tr_index] = std::max(spec_no, spec_max[tr_index]);
3180  m_crpt->spec_to_index[spec_no] = i;
3181  }
3182  }
3183  // put spectrum 0 into same TR as spectrum 1
3184  int spec0_tr = m_crpt->spectrumCRPTTR(1);
3185  spec_min[spec0_tr-1] = 0;
3186  spec_tr[spec0_tr-1].insert(0);
3188  if (n_unassigned_detectors > 0)
3189  {
3190  status.addWarningVa(FAC_DAE, "%d detectors unassigned in spectra table and mapped to spectrum 0", n_unassigned_detectors);
3191  }
3192  // a CRPT time regime must have a contiguous set of spectra that do not overlap with anything else
3193  typedef std::map<int,int> minmax_map_t;
3194  minmax_map_t minmax_map;
3195  for(i=0; i < m_crpt->ntrg; ++i)
3196  {
3197  if ( (spec_min[i] != SPEC_MIN_FILLER) && (minmax_map.insert(minmax_map_t::value_type(spec_min[i],spec_max[i])).second == false) )
3198  {
3199  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "duplicate spec_min %d in tr %d", spec_min[i], i+1);
3200  exit_status = DAEstatus::Failure;
3201  }
3202  }
3203  std::vector< std::pair<int,int> > minmax_vec;
3204  for(minmax_map_t::const_iterator it = minmax_map.begin(); it != minmax_map.end(); ++it)
3205  {
3206  minmax_vec.push_back(*it);
3207  }
3208  for(i=0; i < (minmax_vec.size() - 1); ++i)
3209  {
3210  if ( (minmax_vec[i].second != SPEC_MAX_FILLER) && (minmax_vec[i+1].first != SPEC_MIN_FILLER)
3211  && ((minmax_vec[i+1].first - minmax_vec[i].second) != 1) )
3212  {
3213  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "spectra not contiguous between time regimes");
3214  exit_status = DAEstatus::Failure;
3215  }
3216  }
3217  int n = 0;
3218  for(i=0; i<m_crpt->ntrg; ++i)
3219  {
3220  int nsp = ( (spec_max[i] != SPEC_MAX_FILLER) ? (spec_max[i] - spec_min[i] + 1) : 0 );
3221  if ( nsp != spec_tr[i].size() )
3222  {
3223  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Spectra missing from tr %d", i+1);
3224  exit_status = DAEstatus::Failure;
3225  }
3226  m_crpt->nsp[i] = nsp;
3227  n += nsp;
3228  }
3229  --(m_crpt->nsp[spec0_tr-1]); // we do not count spectrum 0 here
3230  --n;
3231  if ( n != max_spec_no ) // numbers range from 0 to max_spec_no inclusive
3232  {
3233  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Total spec error %d != %d", n, max_spec_no);
3234  exit_status = DAEstatus::Failure;
3235  }
3236  if ( n != m_crpt->getHighestSpectrumNumber() )
3237  {
3238  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "High spec error %d != %d", n, m_crpt->getHighestSpectrumNumber());
3239  exit_status = DAEstatus::Failure;
3240  }
3241  // update wiring table information
3242  if (exit_status == DAEstatus::Success)
3243  {
3245  strncpy(spectra_table.fname, filename, sizeof(spectra_table.fname));
3246  NULL_TERMINATE(spectra_table.fname);
3247  spectra_table.mod_time = stat_struct.st_mtime;
3248  spectra_table.file_size = stat_struct.st_size;
3249  memcpy(spectra_table.checksum, checksum, sizeof(spectra_table.checksum));
3250  status.addInfoVa(FAC_DAE, "Assigned %d spectra from spectra table %s", max_spec_no, filename);
3251  }
3252  else
3253  {
3254  spectra_table.file_size = spectra_table.mod_time = 0;
3255  memset(spectra_table.checksum, 0, sizeof(spectra_table.checksum));
3256  }
3257  return exit_status;
3258 }
3259 
3260 static int getAttrIntegerValue(Poco::XML::NamedNodeMap* attrs, const char* name)
3261 {
3262  Poco::XML::Node* node = attrs->getNamedItem(name);
3263  int val = 0;
3264  if (node != NULL)
3265  {
3266  val = atoi(node->getNodeValue().c_str());
3267 // node->release();
3268  }
3269  return val;
3270 }
3271 
3272 static double getAttrFloatValue(Poco::XML::NamedNodeMap* attrs, const char* name)
3273 {
3274  Poco::XML::Node* node = attrs->getNamedItem(name);
3275  double val = 0.0;
3276  if (node != NULL)
3277  {
3278  val = atof(node->getNodeValue().c_str());
3279 // node->release();
3280  }
3281  return val;
3282 }
3283 
3284 int ISISinstrumentControl::readDataDaeTable(const char* filename, DAEstatus& status)
3285 {
3286  int i, exit_status = DAEstatus::Success;
3287  md5checksum_t checksum;
3288  struct stat stat_struct;
3289  RUNTABLE& data_dae_table = m_crpt->data_dae_table;
3290  if ( stat(filename, &stat_struct) != 0 )
3291  {
3292  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Cannot open data dae table %s", filename);
3293  m_crpt->n_data_dae = 0;
3294  return DAEstatus::Failure;
3295  }
3296  md5sumFile(filename, checksum, status);
3297  if ( (strncmp(data_dae_table.fname, filename, sizeof(data_dae_table.fname)) == 0) &&
3298  (data_dae_table.mod_time == stat_struct.st_mtime) &&
3299  (data_dae_table.file_size == stat_struct.st_size) &&
3300  compareChecksums(data_dae_table.checksum, checksum) )
3301  {
3302  status.addInfoVa(FAC_DAE, "Data DAE table %s is unchanged - reload skipped", filename);
3303  return DAEstatus::Success;
3304  }
3305  m_crpt->n_data_dae = 0;
3306  std::ifstream f;
3307  f.open(filename, std::ios::in);
3308  if (!f.good())
3309  {
3310  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Error reading data dae table %s", filename);
3311  return DAEstatus::Failure;
3312  }
3313  try
3314  {
3315  Poco::XML::InputSource xml_src(f);
3316  Poco::XML::DOMParser parser;
3317  Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parse(&xml_src);
3318  Poco::XML::NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ELEMENT);
3319  Poco::XML::Node* pNode = it.nextNode();
3320  for(i=0; i < ISISCRPT_MAX_DATADAE && pNode != NULL; )
3321  {
3322  if (pNode->nodeName() == "device")
3323  {
3324  Poco::XML::NamedNodeMap* attrs = pNode->attributes();
3325  m_crpt->data_dae[i].id = getAttrIntegerValue(attrs, "id");
3326  m_crpt->data_dae[i].crate = getAttrIntegerValue(attrs, "crate");
3327  m_crpt->data_dae[i].tr = getAttrIntegerValue(attrs, "time_regime");
3328  m_crpt->data_dae[i].data_bytes = getAttrIntegerValue(attrs, "data_bytes");
3329  m_crpt->data_dae[i].scale = getAttrFloatValue(attrs, "scale");
3330  m_crpt->data_dae[i].offset = getAttrFloatValue(attrs, "offset");
3331  Poco::XML::Node* node = attrs->getNamedItem("name");
3332  if (node != NULL)
3333  {
3334  std::string n = node->nodeValue();
3335  std::replace(n.begin(), n.end(), ' ', '_');
3336  strncpy(m_crpt->data_dae[i].name, n.c_str(), sizeof(m_crpt->data_dae[i].name));
3337  }
3339  node = attrs->getNamedItem("data_type");
3340  if (node != NULL)
3341  {
3342  if (node->nodeValue() == "int")
3343  {
3344  m_crpt->data_dae[i].data_type = 1;
3345  }
3346  else if (node->nodeValue() == "float")
3347  {
3348  m_crpt->data_dae[i].data_type = 2;
3349  }
3350  else
3351  {
3352  m_crpt->data_dae[i].data_type = 0; // unknown
3353  }
3354  }
3355  node = attrs->getNamedItem("raw_units");
3356  if (node != NULL)
3357  {
3358  strncpy(m_crpt->data_dae[i].raw_units, node->nodeValue().c_str(), sizeof(m_crpt->data_dae[i].raw_units));
3359  }
3361  node = attrs->getNamedItem("scaled_units");
3362  if (node != NULL)
3363  {
3364  strncpy(m_crpt->data_dae[i].scaled_units, node->nodeValue().c_str(), sizeof(m_crpt->data_dae[i].scaled_units));
3365  node->release();
3366  }
3368  attrs->release();
3369  ++i;
3370  }
3371  pNode = it.nextNode();
3372  }
3373  m_crpt->n_data_dae = i;
3374  }
3375  catch (const Poco::Exception& pex)
3376  {
3377  status.addWarning(FAC_DAE, pex.displayText());
3378  exit_status = DAEstatus::Failure;
3379  }
3380  catch (const std::exception& ex)
3381  {
3382  status.addWarning(FAC_DAE, ex.what());
3383  exit_status = DAEstatus::Failure;
3384  }
3385  ICPCritical cs(&m_crpt_cs);
3386  if (exit_status == DAEstatus::Success)
3387  {
3388  strncpy(data_dae_table.fname, filename, sizeof(data_dae_table.fname));
3389  NULL_TERMINATE(data_dae_table.fname);
3390  data_dae_table.mod_time = stat_struct.st_mtime;
3391  data_dae_table.file_size = stat_struct.st_size;
3392  memcpy(data_dae_table.checksum, checksum, sizeof(data_dae_table.checksum));
3393  status.addInfoVa(FAC_DAE, "Assigned %d items from data dae table %s", m_crpt->n_data_dae, filename);
3394  }
3395  else
3396  {
3397  m_crpt->n_data_dae = 0;
3398  data_dae_table.file_size = data_dae_table.mod_time = 0;
3399  memset(data_dae_table.checksum, 0, sizeof(data_dae_table.checksum));
3400  }
3401  return exit_status;
3402 }
3403 
3404 
3405 // this routine convert the required boundaries into clock pulses for the DAE
3406 // It work in a relative way i.e. if the boundaries are givien in microseconds
3407 // it assumes the clock frequency is in MHz; if time boundaries are nanosecond
3408 // the clock frequency must be in GHz etc (i.e. "cock_frequency is the number of clock
3409 // pulses in one unit of the TCB units
3410 //
3411 // need a CRPT lock already
3413 {
3414  struct stat stat_struct;
3415  int i, j, n;
3416  std::fstream fs;
3417  boost::array<double*,ISISCRPT_MAX_NTRG> rtcb_file;
3418  rtcb_file.fill(NULL);
3419  for(j=0; j<m_crpt->ntrg; j++)
3420  {
3421  TCBRANGE* tcr = m_crpt->tcr[j];
3422  int ntcr = m_crpt->ntcr[j];
3423  if (tcr[0].mode == TCBRANGE_FILE)
3424  {
3425  if ((m_crpt->ntrg != 1) || (m_crpt->ntcr[0] != 1))
3426  {
3428  "ntgr or ntrc error in tcb");
3429  return DAEstatus::Failure;
3430  }
3431  fs.open(tcr[0].tcb_file.fname, std::ios::in);
3432  if (fs.good())
3433  {
3434  n = 0;
3435  fs >> n;
3436  if (fs.good())
3437  {
3438  rtcb_file[j] = new double[n];
3439  for (i=0; i<n; i++)
3440  {
3441  fs >> rtcb_file[j][i];
3442  }
3443  tcr[0].start = static_cast<float>(rtcb_file[j][0]);
3444  tcr[0].end = static_cast<float>(rtcb_file[j][n-1]);
3445  }
3446  if (!fs.good()) // if read error the we should execute this
3447  {
3448  tcr[0].start = 0.0; // throw proper error?
3449  tcr[0].end = 0.0;
3450  }
3451  md5sumFile(tcr[0].tcb_file.fname, tcr[0].tcb_file.checksum, status);
3452  stat(tcr[0].tcb_file.fname, &stat_struct);
3453  tcr[0].tcb_file.mod_time = stat_struct.st_mtime;
3454  tcr[0].tcb_file.file_size = stat_struct.st_size;
3455  status.addInfoVa(FAC_TCB, "TCB read from %s\n", tcr[0].tcb_file.fname);
3456  }
3457  else
3458  {
3460  "Unable to read TCB file %s", tcr[0].tcb_file.fname);
3461  if (rtcb_file[j] != NULL)
3462  {
3463  delete[] rtcb_file[j];
3464  rtcb_file[j] = NULL;
3465  }
3466  return DAEstatus::Failure;
3467  }
3468  fs.close();
3469  }
3470  if (tcr[0].start < m_crpt->tcb_mintime)
3471  {
3472  status.addInfoVa(FAC_TCB, "Start channel %f < minimum allowed (%f); resetting to min allowed", tcr[0].start, m_crpt->tcb_mintime);
3473  tcr[0].start = m_crpt->tcb_mintime;
3474  }
3475  if (tcr[ntcr-1].end < m_crpt->tcb_mintime)
3476  {
3478  "End channel less than min time (%f < %f)",
3479  tcr[ntcr-1].end, m_crpt->tcb_mintime);
3480  return DAEstatus::Failure;
3481  }
3482  if (tcr[0].start > m_crpt->tcb_maxtime)
3483  {
3485  "Start channel greater than max time (%f > %f)",
3486  tcr[0].start, m_crpt->tcb_maxtime);
3487  return DAEstatus::Failure;
3488  }
3489  if (tcr[ntcr-1].end > m_crpt->tcb_maxtime)
3490  {
3492  "end channel greater than max time (%f > %f)",
3493  tcr[ntcr-1].end, m_crpt->tcb_maxtime);
3494  return DAEstatus::Failure;
3495  }
3496 // if a start or a finish value < 1 assume it means you want to join with the previous
3497 // range
3498  for(i=1; i<ntcr; i++)
3499  {
3500  if (tcr[i-1].end < 1.0)
3501  {
3502  tcr[i-1].end = tcr[i].start;
3503  }
3504  if (tcr[i].start < 1.0)
3505  {
3506  tcr[i].start = tcr[i-1].end;
3507  }
3508  }
3509  for(i=0; i<ntcr; i++)
3510  {
3511  if (tcr[i].end < tcr[i].start)
3512  {
3514  "end channel less than start time (%f < %f)",
3515  tcr[i].end, tcr[i].start);
3516  return DAEstatus::Failure;
3517  }
3518  if (tcr[i].mode == TCBRANGE_CONST_T)
3519  {
3520  if ( tcr[i].tcpar[0] > (tcr[i].end - tcr[i].start) )
3521  {
3523  "channel width too big for section %d (%f)", i,
3524  tcr[i].tcpar[0]);
3525  return DAEstatus::Failure;
3526  }
3527  if ( tcr[i].tcpar[0] < m_crpt->tcb_minwidth )
3528  {
3530  "channel width too small for section %d (%f)", i,
3531  tcr[i].tcpar[0]);
3532  return DAEstatus::Failure;
3533  }
3534  }
3535  }
3536  }
3537  int clock_delay = 0;
3538  float frame_delay = 0.0;
3539  float min_tcb = m_crpt->tcr[0][0].start;
3540  for(i=0; i<m_crpt->ntrg; i++)
3541  {
3542  min_tcb = std::min(min_tcb, m_crpt->tcr[i][0].start);
3543  }
3545  {
3546  // clock delay in 4us units
3547  clock_delay = (int)(min_tcb / 4.0);
3548  if (clock_delay * 4.0 > m_crpt->tcb_maxdelay)
3549  {
3550  clock_delay = (int)(m_crpt->tcb_maxdelay / 4.0);
3551  }
3552  frame_delay = 4.0f * clock_delay;
3553  // not less than (1.0 + m_crpt->electronics_delay / m_crpt->clock_frequency)
3554  if ( (min_tcb - frame_delay) < 1.4 ) // need to allow for electronics delay here, so 1.4 not 1.0
3555  {
3556  clock_delay--;
3557  frame_delay = 4.0f * clock_delay;
3558  }
3559  }
3560  float first_tcb = min_tcb - frame_delay; // first time channel boundary relative to any global frame_delay
3561 // we currently support multiple time remines, but only with
3562 // a global shift; hence only start may differ
3563 // for(i=0; i<m_crpt->ntrg; i++)
3564 // {
3565 // for(j=0; j<ISISCRPT_MAX_TCR; j++)
3566 // {
3567 // if (!tcbRangesPurelyShifted(m_crpt->tcr[0][j], m_crpt->tcr[i][j]))
3568 // {
3569 // status.addVa(FAC_TCB, SEV_ERROR, ERRTYPE_OUTOFMEM,
3570 // "time regimes 1 and %d are incompatible", i+1);
3571 // return DAEstatus::Failure;
3572 // }
3573 // }
3574 // }
3575  m_crpt->tcb_delay = static_cast<int>(frame_delay);
3576  for(j=0; j<m_crpt->ntrg; j++)
3577  {
3578  TCBRANGE* tcr = m_crpt->tcr[j];
3579 // we want (tcb_trdelay == 0) for the lowest time range
3580 // do not need to be multiple of 4us, but want this to be zero for lowest regime
3581 // need 1us for first channel min, multiple of 4us for delay
3582 // int tcb_trdelay = 4 * (int)((tcr[0].start - frame_delay - 1.0) / 4.0);
3583  int tcb_trdelay = (int)(tcr[0].start - frame_delay - first_tcb);
3584  if (tcb_trdelay < 0)
3585  {
3586  tcb_trdelay = 0;
3587  }
3588  m_crpt->tcb_trdelay[j] = tcb_trdelay;
3589  if (fabs((m_crpt->tcr[j][0].start - m_crpt->tcb_trdelay[j]) -
3590  (m_crpt->tcr[0][0].start - m_crpt->tcb_trdelay[0])) > 1e-5)
3591  {
3593  "time regimes 1 and %d are incompatible", j+1);
3594  return DAEstatus::Failure;
3595  }
3596  }
3597  // multiple TR not allowed on muons
3598  if ((m_dae_type == ISISDAE::MuonDAE2) && ((m_crpt->ntrg > 1) || (m_crpt->tcb_trdelay[0] != 0)) )
3599  {
3601  "%d time regimes not allowed on muons", m_crpt->ntrg);
3602  return DAEstatus::Failure;
3603  }
3604  // now calc tcb
3605  // last_time is last time channel boundary output
3606  // current_time is what we are thinking about for the nmext boundary
3607  // last_width is the width of the "last_time" channel output
3608 
3609  // one regime will have trdelay of zero - used for boundaries at the moment
3610 // bool zero_shift_regime_avaiable = false;
3611 // for(j=0; j < m_crpt->ntrg; j++)
3612 // {
3613 // TCBRANGE* tcr = m_crpt->tcr[j];
3614 // if (tcr[0].mode != TCBRANGE_SHIFTED && m_crpt->tcb_trdelay[j] == 0)
3615 // {
3616 // zero_shift_regime_avaiable = true;
3617 // }
3618 // }
3619  for(j=0; j < m_crpt->ntrg; j++)
3620  {
3621  TCBRANGE* tcr = m_crpt->tcr[j];
3622  if (tcr[0].mode == TCBRANGE_SHIFTED) // shifted from another regime
3623  {
3624  continue;
3625  }
3626 // if (zero_shift_regime_avaiable && m_crpt->tcb_trdelay[j] > 0) // set up tc for first tr until we do things properly
3627 // {
3628 // continue;
3629 // }
3630  int* tcb = m_crpt->tcb[j];
3631  float* rtcb = m_crpt->rtcb[j];
3632  int ntcr = m_crpt->ntcr[j];
3633  int nchan = 0;
3634  frame_delay = static_cast<float>(m_crpt->tcb_delay + m_crpt->tcb_trdelay[j]);
3635  double last_time = tcr[0].start - frame_delay;
3636  tcb[nchan] = (int)(0.5 + last_time * m_crpt->clock_frequency);
3637  last_time = (double)tcb[0] / m_crpt->clock_frequency;
3638  i = 0;
3639  nchan++;
3640  double current_time = last_time;
3641  double last_width = 0.0;
3642  int num_iterations = 0;
3643  while(i<ntcr)
3644  {
3645  if (++num_iterations > 20 * ISISCRPT_MAX_TIMECHANB)
3646  {
3647  status.addVa(FAC_TCB, SEV_ERROR, ERRTYPE_OUTOFMEM, "Infinite loop detected while calculating time channels");
3648  return DAEstatus::Failure;
3649  }
3650  if ( last_time >= (tcr[i].end - frame_delay) )
3651  {
3652  i++;
3653  last_width = 0.0;
3654  if (i < ntcr)
3655  {
3656  current_time = tcr[i].start - frame_delay;
3657  }
3658  else
3659  {
3660  continue; // will exit as i >= ntcr
3661  }
3662  }
3663  else
3664  {
3665  switch(tcr[i].mode)
3666  {
3667  case TCBRANGE_FILE:
3668  current_time = rtcb_file[j][nchan] - frame_delay;
3669  break;
3670  case TCBRANGE_CONST_T:
3671  current_time = last_time + tcr[i].tcpar[0];
3672  break;
3673  case TCBRANGE_INC_T:
3674  current_time = last_time + (last_time+frame_delay)*tcr[i].tcpar[0];
3675  break;
3676  case TCBRANGE_INC_T_2:
3677  current_time = last_time + (last_time+frame_delay)*(last_time+frame_delay)*tcr[i].tcpar[0];
3678  break;
3679  default:
3681  "unknown time channel mode %d", tcr[i].mode);
3682  return DAEstatus::Failure;
3683  break;
3684  }
3685  if ( (current_time - last_time) < m_crpt->tcb_minwidth )
3686  {
3687  current_time = last_time + m_crpt->tcb_minwidth;
3688  }
3689  if ( current_time > (tcr[i].end - frame_delay) )
3690  {
3691  current_time = tcr[i].end - frame_delay;
3692  if ( ((current_time - last_time) < (last_width / 4.0)) ||
3693  ((current_time - last_time) < m_crpt->tcb_minwidth) )
3694  {
3695  // combine with previous channel
3696  nchan--;
3697  last_time = last_time - last_width;
3698  }
3699  }
3700  }
3701  if ( (current_time - last_time) >= m_crpt->tcb_minwidth )
3702  {
3703  tcb[nchan] = (int)(0.5 + current_time * m_crpt->clock_frequency);
3704  current_time = (double)tcb[nchan] / m_crpt->clock_frequency;
3705  last_width = current_time - last_time;
3706  last_time = current_time;
3707  nchan++;
3708  }
3709  if (nchan >= ISISCRPT_MAX_TIMECHANB)
3710  {
3712  "too many time channels (> %d)", ISISCRPT_MAX_TIMECHANB);
3713  return DAEstatus::Failure;
3714  }
3715  }
3716  for(i=0; i<nchan; i++)
3717  {
3718  rtcb[i] = (float)tcb[i] / m_crpt->clock_frequency + frame_delay;
3719  }
3720  // nchan boundaries, hence nchan-1 channels
3721  m_crpt->ntc[j] = nchan - 1;
3722  }
3723  for(j=0; j<m_crpt->ntrg; j++)
3724  {
3725  frame_delay = static_cast<float>(m_crpt->tcb_delay + m_crpt->tcb_trdelay[j]);
3726  int nchan = m_crpt->ntc[j] + 1;
3727  for(i=0; i<nchan; i++)
3728  {
3729  m_crpt->rtcb[j][i] = (float)m_crpt->tcb[j][i] / m_crpt->clock_frequency + frame_delay;
3730  }
3731  if (rtcb_file[j] != NULL)
3732  {
3733  delete[] rtcb_file[j];
3734  }
3735  }
3737  m_crpt->calculateCRPTOffsets(); // these depend on tcbs so also need to be recalculated when they change
3738  return DAEstatus::Success;
3739 // status.addVa(FAC_TCB, SEV_ERROR, ERRTYPE_OUTOFMEM, "Not done tcb");
3740 // return DAEstatus::Failure;
3741 }
3742 
3743 int ISISinstrumentControl::setLinearTimeChannelRange(int range_number, float start, float end, float step, DAEstatus& status)
3744 {
3745  return setTimeChannelRange(range_number, TCBRANGE_CONST_T, start, end, step, status);
3746 }
3747 
3748 int ISISinstrumentControl::setLogTimeChannelRange(int range_number, float start, float end, float step, DAEstatus& status)
3749 {
3750  return setTimeChannelRange(range_number, TCBRANGE_INC_T, start, end, step, status);
3751 }
3752 
3753 int ISISinstrumentControl::setTimeChannelRange(int range_number, int range_type, float start, float end, float step, DAEstatus& status)
3754 {
3755  if (range_number < 0 || range_number >= ISISCRPT_MAX_TCR)
3756  {
3758  "invalid range %d", range_number);
3759  return DAEstatus::Failure;
3760  }
3761  ICPCritical cs(&m_crpt_cs);
3762  TCBRANGE& tcr = m_crpt->tcr[0][range_number];
3763  tcr.mode = range_type;
3764  tcr.start = start;
3765  tcr.end = end;
3766  tcr.tcpar[0] = step;
3767  tcr.npar = 1;
3768  m_crpt->ntcr[0] = range_number + 1;
3769  m_crpt->ntrg = 1;
3770  tcbcalc(status);
3771  return DAEstatus::Success;
3772 }
3773 
3774 // beam current is calculated by the update thread
3776 {
3777  return m_crpt->beam_current;
3778 }
3779 
3780 // This is called every "poll_time" seconds by a separate thread
3781 // from the updateThread() function
3782 int ISISinstrumentControl::updateFunc(int poll_time, bool only_refresh_cache)
3783 {
3784  static unsigned long ncalls = 0;
3785  static unsigned long update_duration_total = 0; // number of seconds running
3786  static bool disable_monitoring_in_event_mode = m_app->config().getBool("isisicp.monitoring.disableineventmode", false);
3787  bool skip_monitoring = (disable_monitoring_in_event_mode & m_crpt->usingEventMode());
3788  ncalls++;
3789  ++(m_crpt->update_num_polls);
3790  update_duration_total += poll_time;
3791  struct timeb new_update_time;
3792  if (!m_crpt.isValid())
3793  {
3794  return DAEstatus::Failure;
3795  }
3796  ICPCritical cs(&m_crpt_cs);
3797  time_t now;
3798  time(&now);
3799  time_t this_dur = (now - m_crpt->resume_time);
3800  ftime(&new_update_time);
3801  float tdiff = (float)(new_update_time.time - (m_crpt->update_time).time) +
3802  (float)(new_update_time.millitm - (m_crpt->update_time).millitm) / 1e6f;
3803  // beam current
3804  float raw_uamph = getRawUAmpH(m_status);
3805  float good_uamph = getGoodUAmpH(m_status);
3806 
3807  float good_uamp_diff = good_uamph - m_crpt->update_good_uamph;
3808 
3809 // m_crpt->beam_current = 3600.0 * (raw_uamph - m_crpt->update_raw_uamph) / tdiff;
3810  m_crpt->beam_current = 3600.0f * (good_uamph - m_crpt->update_good_uamph) / tdiff;
3811  m_crpt->update_raw_uamph = raw_uamph;
3812  m_crpt->update_good_uamph = good_uamph;
3813 
3818 
3819  // count rate (units of million counts per hour)
3820  int64_t total_counts, total_counts_diff;
3821  getTotalCounts(total_counts, m_status);
3822  if (total_counts < 0)
3823  {
3824  total_counts = 0;
3825  }
3826  total_counts_diff = total_counts - m_crpt->update_total_counts;
3827  m_crpt->count_rate = 3600.0f * total_counts_diff / (1.0e6f * tdiff);
3828  if (m_crpt->count_rate < 0.0)
3829  {
3830  m_crpt->count_rate = 0.0;
3831  }
3832  m_crpt->update_total_counts = total_counts;
3833 
3834  // monitor integral
3835  long integral, max_value;
3836  int period, daq_period;
3837  getCurrentPeriodNumber(period, daq_period, m_status);
3838  getSpectrumIntegral(m_crpt->monitor_spectrum, period, m_crpt->monitor_range[0][0], m_crpt->monitor_range[0][1], integral, max_value, m_status);
3839  long integral_diff = integral - m_crpt->monitor_sum[0];
3840  m_crpt->monitor_sum[0] = integral;
3841 
3842  // frames
3843  isisU32_t good_frames, raw_frames, good_frames_diff, raw_frames_diff;
3844  m_dae->getGoodFrames(&good_frames, m_status);
3845  m_dae->getRawFrames(&raw_frames, m_status);
3846  good_frames_diff = good_frames - m_crpt->update_good_frames;
3847  raw_frames_diff = raw_frames - m_crpt->update_raw_frames;
3848  m_crpt->update_good_frames = good_frames;
3849  m_crpt->update_raw_frames = raw_frames;
3850 
3851  m_crpt->update_period = period;
3852  PERIOD& this_period = m_crpt->period[period];
3853  isisU32_t value32;
3855  m_crpt->update_period_sequence = value32;
3856  if (isRunning())
3857  {
3859  {
3862  }
3863  else
3864  {
3867  }
3868  m_crpt->update_duration = m_crpt->duration + this_dur;
3869  m_crpt->update_duration_period = this_period.duration + this_dur;
3870  }
3871  else
3872  {
3874  {
3877  }
3878  else
3879  {
3882  }
3884  m_crpt->update_duration_period = this_period.duration;
3885  }
3886 
3887  // n/p ratio
3888  if ( !only_refresh_cache && !skip_monitoring && (m_crpt->monitoring.enabled != 0) )
3889  {
3890  float tdiff_mon = (float)(new_update_time.time - (m_crpt->monitoring.calc_last_time).time) +
3891  (float)(new_update_time.millitm - (m_crpt->monitoring.calc_last_time).millitm) / 1e6f;
3892  if ( (m_crpt->monitoring.calc_freq > 0) && (tdiff_mon >= m_crpt->monitoring.calc_freq) )
3893  {
3894  char buffer[20];
3895  std::map<std::string,double> values;
3896  std::vector<long> spectra_used(m_crpt->monitoring.n);
3897  for(int i=0; i<m_crpt->monitoring.n; i++)
3898  {
3899  monitoring_par& par = m_crpt->monitoring.v[i];
3900  spectra_used[i] = par.spectrum;
3901  }
3902  std::sort(spectra_used.begin(), spectra_used.end());
3903  std::vector<long>::iterator new_end = std::unique(spectra_used.begin(), spectra_used.end());
3904  updateCRPTSpectra(period, &(spectra_used[0]), distance(spectra_used.begin(), new_end), m_status);
3905  for(int i=0; i<m_crpt->monitoring.n; i++)
3906  {
3907  monitoring_par& par = m_crpt->monitoring.v[i];
3908  getCRPTSpectrumIntegral(par.spectrum, period, par.t_low, par.t_high, integral, max_value, m_status);
3909  par.last_change = ((double)integral - par.last_value);
3910  par.last_value = integral;
3911  sprintf(buffer, "V%d", i+1);
3912  values[buffer] = par.last_change;
3913  sprintf(buffer, "_V%d", i+1);
3914  values[buffer] = par.last_value;
3915  }
3916  values["T"] = tdiff_mon;
3917  values["_T"] = difftime(now, m_crpt->start_time);
3918  values["GF"] = m_crpt->update_good_frames - m_crpt->monitoring.last_gf;
3919  values["_GF"] = m_crpt->update_good_frames;
3920  values["UA"] = m_crpt->update_good_uamph - m_crpt->monitoring.last_ua;
3921  values["_UA"] = m_crpt->update_good_uamph;
3922  values["MEV"] = (m_crpt->update_total_counts - m_crpt->monitoring.last_tc) / 1.0e6;
3923  values["_MEV"] = m_crpt->update_total_counts / 1.0e6;
3927  double result = 0.0;
3928  if ( !only_refresh_cache && isRunning() && (values["GF"] >= 1.0) && evaluateExpression(values, m_crpt->monitoring.expression, result, m_status) == DAEstatus::Success)
3929  {
3930  //std::string sender = std::string("isisicp@") + m_crpt->comp_name + ".isis.cclrc.ac.uk";
3931  std::string sender = "isisicp@shadow.nd.rl.ac.uk";
3932  std::string alert_sms, line;
3933  std::fstream fs;
3934  fs.open(m_icp_dir+"\\sms_send.txt"); // one number per line, # for comments
3935  while(fs.good())
3936  {
3937  line.clear();
3938  std::getline(fs, line, '\n');
3939  int i = line.find('#');
3940  if (i != std::string::npos)
3941  {
3942  line.erase(i);
3943  }
3944  alert_sms.append(",");
3945  alert_sms.append(line);
3946  }
3947  fs.close();
3948  alert_sms.erase(std::remove(alert_sms.begin(), alert_sms.end(), ' '), alert_sms.end()); // remove spaces
3949  m_crpt->update_npratio_current = result;
3950  int oldper = m_crpt->software_period;
3951  int newper = -1;
3952  if (result < m_crpt->monitoring.valid_low || result > m_crpt->monitoring.valid_high)
3953  {
3954  switch(m_crpt->monitoring.action)
3955  {
3956  case 0:
3957  break;
3958 
3959  case 1:
3960  newper = m_crpt->monitoring.action_period - 1;
3961  break;
3962 
3963  case 2:
3964  newper = m_crpt->nper - 1;
3965  break;
3966  }
3967  if (newper != -1 && newper != oldper)
3968  {
3969  logEventVa(m_crpt, m_status, "NPRATIO OUT_OF_RANGE %g", result);
3970  changePeriodWhileRunning(newper, true, m_status); // this does not call refreshCache()
3971  m_crpt->monitoring.return_period = oldper;
3972  if (m_crpt->monitoring.alerts > 0)
3973  {
3974 // std::string sender = std::string("isisicp@") + m_crpt->comp_name + ".isis.cclrc.ac.uk";
3975  sendEmail(sender, m_crpt->alert_email, std::string(m_crpt->comp_name)+" overcounting problem",
3976  std::string(m_crpt->comp_name)+" overcounting problem", m_status);
3977  sendSMS(alert_sms, std::string(m_crpt->comp_name)+" overcounting problem", m_status);
3978  }
3979  }
3980  }
3981  else
3982  {
3983  switch(m_crpt->monitoring.action)
3984  {
3985  case 0:
3986  break;
3987 
3988  case 1:
3989  case 2:
3990  if (m_crpt->monitoring.return_period != -1)
3991  {
3993  {
3994  logEventVa(m_crpt, m_status, "NPRATIO IN_RANGE %g", result);
3996  if (m_crpt->monitoring.alerts > 0)
3997  {
3998  sendEmail(sender, m_crpt->alert_email, std::string(m_crpt->comp_name)+" overcounting now OK",
3999  std::string(m_crpt->comp_name)+" overcounting now OK", m_status);
4000  sendSMS(alert_sms, std::string(m_crpt->comp_name)+" overcounting now OK", m_status);
4001  }
4002  }
4004  }
4005  break;
4006  }
4007  }
4008  }
4010  m_crpt->monitoring.calc_last_time = new_update_time;
4011  }
4012  if ( isRunning() /* && (m_crpt->beam_current > 0.0) */ && (m_crpt->monitoring.log_freq > 0) && ((now - m_crpt->monitoring.log_last_time) >= m_crpt->monitoring.log_freq) )
4013  {
4016  }
4017  }
4018 
4019  if ( !only_refresh_cache && (update_duration_total % 30 == 0) )
4020  {
4021  updateStatusLog();
4023  }
4024  if ( only_refresh_cache || (update_duration_total % 15 == 0) )
4025  {
4026  seblock_map_t seblocks;
4027  if (se_get_block_values(seblocks) == 0)
4028  {
4031  }
4032  else
4033  {
4034  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
4035  }
4036  }
4037  m_crpt->update_time = new_update_time;
4038  if (!only_refresh_cache)
4039  {
4040 // autosaves
4041  bool write_autosave = false;
4042  switch(m_crpt->auto_save_type)
4043  {
4044  case 0: // frames
4046  {
4048  write_autosave = true;
4049  }
4050  break;
4051 
4052  case 1: // events
4054  {
4056  write_autosave = true;
4057  }
4058  break;
4059 
4060  case 2: // dashboard polls
4062  {
4064  write_autosave = true;
4065  }
4066  break;
4067 
4068  case 3: // uamph
4070  {
4072  write_autosave = true;
4073  }
4074  break;
4075 
4076  default:
4077  break;
4078  }
4079  // check we are not in setup before writing an autosave file, update thread may have got
4080  // queued after a run ended and so will write the wrong run number
4081  if ( write_autosave && (m_crpt->run_status != RUNSTATUS_SETUP) && (m_icp_options & AutoSave) )
4082  {
4084  }
4086  {
4088  {
4089  endRun(m_status);
4090  }
4091  }
4092  }
4093  static int nagios_poll = m_app->config().getInt("isisicp.nagios.poll", 60);
4094  static double veto_warn = m_app->config().getDouble("isisicp.nagios.veto.warn", 80.0);
4095  static double veto_critical = m_app->config().getDouble("isisicp.nagios.veto.critical", 90.0);
4096  static double wait_warn = m_app->config().getDouble("isisicp.nagios.wait.warn", 120.0);
4097  static double wait_critical = m_app->config().getDouble("isisicp.nagios.wait.critical", 180.0);
4098  static double shutter_warn = m_app->config().getDouble("isisicp.nagios.shutter.warn", 5.0);
4099  if ( !only_refresh_cache && (update_duration_total % nagios_poll == 0) )
4100  {
4101  // nagios stuff
4102  nagios_t& nagios = m_crpt->nagios;
4103  nagios.veto_percent = 0.0;
4104  if (raw_frames_diff > 0)
4105  {
4106  nagios.veto_percent = 100.0 * (1.0 - (double)good_frames_diff / (double)raw_frames_diff);
4107  }
4108 // std::string veto_message = Poco::format("Vetoing %.1f%% of data;|'veto'=%f%%;%f;%f\n", veto_percent, veto_percent, veto_warn, veto_critical);
4109 // veto_message += Poco::format("Vetoing %.1f%%\n", veto_percent);
4110 // veto_message += Poco::format("Effective beam current %.1f uA\n", (double)m_crpt->beam_current);
4111 // veto_message += Poco::format("Good proton charge %.1f uAh\n", (double)m_crpt->update_good_uamph);
4112 // veto_message += Poco::format("Good frames %ld\n", m_crpt->update_good_frames);
4113 // veto_message += Poco::format("Raw frames %ld\n", m_crpt->update_raw_frames);
4114 // veto_message += Poco::format("Run duration %ld seconds|'duration'=%lds\n", m_crpt->update_duration, m_crpt->update_duration);
4115 // veto_message += Poco::format("'beamcurrent'=%f\n", (double)m_crpt->beam_current);
4116 // veto_message += Poco::format("'gooduah'=%f\n", (double)m_crpt->update_good_uamph);
4117 // veto_message += Poco::format("'goodframes'=%ld\n", m_crpt->update_good_frames);
4118 // veto_message += Poco::format("'rawframes'=%ld", m_crpt->update_raw_frames);
4119  std::string veto_message = Poco::format("Vetoing %.1f%% of data;|'veto'=%f%%;%f;%f", nagios.veto_percent, nagios.veto_percent, veto_warn, veto_critical);
4120  Poco::format(veto_message, " 'beamcurrent'=%f", (double)m_crpt->beam_current);
4121  Poco::format(veto_message, " 'gooduah'=%f", (double)m_crpt->update_good_uamph);
4122  Poco::format(veto_message, " 'goodframes'=%ld", m_crpt->update_good_frames);
4123  Poco::format(veto_message, " 'rawframes'=%ld", m_crpt->update_raw_frames);
4124  Poco::format(veto_message, " 'duration'=%lds", m_crpt->update_duration);
4125  if (beamOn(1))
4126  {
4127  if (nagios.veto_percent > veto_critical)
4128  {
4129  nagios.dae_status = 2;
4130  }
4131  else if (nagios.veto_percent > veto_warn)
4132  {
4133  nagios.dae_status = 1;
4134  }
4135  else
4136  {
4137  nagios.dae_status = 0;
4138  }
4139  }
4140  sendNagios(nagios.dae_status, "DAE STATUS", veto_message, m_status);
4141  nagios.wait_mins = difftime(now, m_crpt->stop_time) / 60.0;
4142  if (!isWaiting())
4143  {
4144  nagios.wait_mins = 0;
4145  }
4146  std::string wait_message = Poco::format("Waiting for %.1f minutes;|'data'=%fs;%f;%f", nagios.wait_mins, nagios.wait_mins * 60.0, wait_warn * 60.0, wait_critical * 60.0);
4147  if (isWaiting() && nagios.wait_mins > wait_warn)
4148  {
4149  if (beamOn(1))
4150  {
4151  if (nagios.wait_mins > wait_critical)
4152  {
4153  nagios.wait_status = 2;
4154  }
4155  else
4156  {
4157  nagios.wait_status = 1;
4158  }
4159  }
4160  }
4161  else
4162  {
4163  nagios.wait_status = 0;
4164  }
4165  sendNagios(nagios.wait_status, "DAE WAITING", wait_message, m_status);
4166  if ( isRunning() && m_crpt->update_duration > shutter_warn * 60 )
4167  {
4168  if ( beamOn(1) )
4169  {
4170  if ( m_crpt->beamlogger.shutter == 0 || (total_counts_diff == 0 && integral_diff == 0) )
4171  {
4172  nagios.shutter_status = 1;
4173  }
4174  else
4175  {
4176  nagios.shutter_status = 0;
4177  }
4178  }
4179  }
4180  else
4181  {
4182  nagios.shutter_status = 0;
4183  }
4184  if ( m_crpt->dae_type == ISISDAE::MuonDAE2 && beamOn(10) && !muonKickerOK() )
4185  {
4186  nagios.shutter_status = 1;
4187  }
4188  if (nagios.shutter_status > 0)
4189  {
4190  nagios.shutter_val = 0;
4191  }
4192  else
4193  {
4194  nagios.shutter_val = 1 + m_crpt->beamlogger.shutter; // 0 for closed plus running (or muon kicker not working), 1 for closed, 2 for open
4195  }
4196  std::string shutter_message;
4197  if ( m_crpt->dae_type == ISISDAE::MuonDAE2 )
4198  {
4199  shutter_message = Poco::format("KICKER %s COLLECTING %s;|'data'=%d;1:;0:", std::string(m_crpt->beamlogger.muonkicker ? "ON" : "OFF"),
4200  std::string(nagios.shutter_status ? "NO" : "YES"), nagios.shutter_val);
4201  }
4202  else
4203  {
4204  shutter_message = Poco::format("SHUTTER %s%s;|'data'=%d;1:;0:", std::string(m_crpt->beamlogger.shutter ? "OPEN" : "CLOSED"),
4205  std::string(nagios.shutter_status ? " and running" : ""), nagios.shutter_val);
4206  }
4207  sendNagios(nagios.shutter_status, "BEAMLINE", shutter_message, m_status);
4208  }
4210  return DAEstatus::Success;
4211 }
4212 
4213 
4215 {
4216 // float run_dur = difftime(time(NULL), m_crpt->start_time);
4217 // m_status.addInfoVa(FAC_DAE, "Runtime = %.0f s, Frame timer drift (icp - dae) = %f ms", run_dur, m_dae->frameTimerDrift(m_status) / 1000.0);
4218 // m_status.addInfoVa(FAC_DAE, "Runtime = %.0f s, System timer drift (icp - system) = %f ms", run_dur, diffFileTimesInMilliSec(system_ft, icp_ft));
4219 // if (update_duration_total > 0)
4220 // {
4221 // m_status.addInfoVa(FAC_DAE, "Frame timer drift / run time = %f", m_dae->frameTimerDrift(m_status) / update_duration_total);
4222 // }
4223  static bool write_tdiff_file = m_app->config().getBool("isisicp.logfiles.writetdiff", false);
4224  bool file_exists = false;
4225  struct stat stat_struct;
4226  char time_buffer[128];
4227  FILETIME icp_ft, system_ft;
4228  g_icp_clock.get()->getCurrentTimeAsFiletime(icp_ft);
4229  GetSystemTimeAsFileTime(&system_ft);
4230  ISOtime(time(NULL), time_buffer, sizeof(time_buffer));
4231  double icp_dae_td = m_dae->frameTimerDrift(m_status) / 1000.0;
4232  double icp_sys_td = diffFileTimesInMilliSec(system_ft, icp_ft);
4233  if (se_log_value_async(m_crpt->run_number, "ISISICP", time_buffer, "ICP_DAE_TD", Poco::format("%f", icp_dae_td).c_str()) != 0)
4234  {
4235  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
4236  }
4237  if (se_log_value_async(m_crpt->run_number, "ISISICP", time_buffer, "ICP_SYS_TD", Poco::format("%f", icp_sys_td).c_str()) != 0)
4238  {
4239  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
4240  }
4241  if (write_tdiff_file)
4242  {
4243  if (stat(m_crpt.timeDiffLog().c_str(), &stat_struct) == 0)
4244  {
4245  file_exists = true;
4246  }
4247  std::stringstream f;
4248  if (!file_exists)
4249  {
4250  f << "# iso time, Frame timer drift (icp - dae) ms, System timer drift (icp - system) ms\r\n";
4251  }
4252  f << time_buffer << " " << icp_dae_td << " " << icp_sys_td << "\r\n";
4253  appendToFileAsync(m_crpt.timeDiffLog().c_str(), f.str().c_str());
4254  }
4255 }
4256 
4258 {
4259  bool file_exists = false;
4260  struct stat stat_struct;
4261  char time_buffer[128], buffer[128];
4262  if (stat(m_crpt.monitoringLog().c_str(), &stat_struct) == 0)
4263  {
4264  file_exists = true;
4265  }
4266  std::stringstream f;
4267  ISOtime(m_crpt->monitoring.calc_last_time.time, time_buffer, sizeof(time_buffer));
4268  if (!file_exists) // start of file
4269  {
4270  f << "# time expression_value";
4271  for(int i=1; i<=m_crpt->monitoring.n; i++)
4272  {
4273  f << " V" << i; // << " dV" << i;
4274  }
4275  f << "\r\n";
4276  }
4277  f << time_buffer << " " << m_crpt->update_npratio_current;
4278  for(int i=0; i<m_crpt->monitoring.n; i++)
4279  {
4280  monitoring_par& par = m_crpt->monitoring.v[i];
4281  f << " " << par.last_value; // << " " << par.last_change;
4282  }
4283  f << "\r\n";
4284  appendToFileAsync(m_crpt.monitoringLog().c_str(), f.str().c_str());
4285  std::vector<std::string> iso_times;
4286  std::vector<std::string> block_names;
4287  std::vector<std::string> block_values;
4288  for(int i=0; i<m_crpt->monitoring.n; i++)
4289  {
4290  monitoring_par& par = m_crpt->monitoring.v[i];
4291  sprintf(buffer, "monitoring_v%d", i+1);
4292  block_names.push_back(buffer);
4293  sprintf(buffer, "%g", par.last_value);
4294  block_values.push_back(buffer);
4295  }
4296  block_names.push_back("monitoring_expression");
4297  sprintf(buffer, "%g", m_crpt->update_npratio_current);
4298  block_values.push_back(buffer);
4299  iso_times.resize(block_names.size());
4300  std::fill(iso_times.begin(), iso_times.end(), time_buffer);
4301  if (se_log_values_async(m_crpt->run_number, "ISISICP", iso_times, block_names, block_values) != 0)
4302  {
4303  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
4304  }
4305  return DAEstatus::Success;
4306 }
4307 
4309 {
4310  static bool write_status_file = m_app->config().getBool("isisicp.logfiles.writestatus", false);
4311  bool file_exists = false;
4312  char time_buffer[128];
4313  struct stat stat_struct;
4314  time_t unix_time = 0;
4315 // isisU32_t igf, irf;
4316 // m_dae->getGoodFrames(&igf, m_status);
4317 // m_dae->getRawFrames(&irf, m_status);
4318  time(&unix_time);
4319  ISOtime(unix_time, time_buffer, sizeof(time_buffer));
4320  if (se_log_run(m_crpt->run_number, "ISISICP", time_buffer, m_crpt->update_period + 1,
4321  m_crpt->run_status, (isRunning() ? 1 : 0), (isWaiting() ? 1 : 0),
4326  {
4327  m_status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
4328  }
4329  if (write_status_file)
4330  {
4331  if (stat(m_crpt.statusLog().c_str(), &stat_struct) == 0)
4332  {
4333  file_exists = true;
4334  }
4335  std::stringstream f;
4336  if (!file_exists) // start of file
4337  {
4338  f << "# time period is_running is_waiting good_frames raw_frames good_uamps raw_uamph monitor1_sum dae_beam_current total_counts count_rate np_ratio\r\n";
4339  }
4340  f << time_buffer << " " <<
4341  m_crpt->update_period + 1 << " " <<
4342  (isRunning() ? 1 : 0) << " " <<
4343  (isWaiting() ? 1 : 0) << " " <<
4344  m_crpt->update_good_frames << " " << m_crpt->update_raw_frames << " " <<
4345  m_crpt->update_good_uamph << " " << m_crpt->update_raw_uamph << " " <<
4346  m_crpt->monitor_sum[0] << " " <<
4347  m_crpt->beam_current << " " <<
4348  m_crpt->update_total_counts << " " <<
4349  m_crpt->count_rate << " " <<
4350  m_crpt->update_npratio_current << " " <<
4351  "\r\n";
4352  appendToFileAsync(m_crpt.statusLog().c_str(), f.str().c_str());
4353  }
4354  return DAEstatus::Success;
4355 }
4356 
4358 {
4359  ISISinstrumentControl* the_icp = static_cast<ISISinstrumentControl*>(arg);
4360  if (the_icp != NULL)
4361  {
4362  return the_icp->allReportFuncMain(mess);
4363  }
4364  else
4365  {
4366  return 0;
4367  }
4368 }
4369 
4371 {
4372  debug_report_arg_t params;
4373  params.filename = m_crpt.debugLog();
4374  if (m_crpt.isValid())
4375  {
4376  params.run_number = m_crpt->run_number;
4377  }
4378  else
4379  {
4380  params.run_number = 0;
4381  }
4382  if (m_report_func != NULL)
4383  {
4384  (*m_report_func)(mess, m_report_arg);
4385  }
4386  debugReportFunction(mess, &params);
4387 // would be nice to put these in the database, but if there is a problem
4388 // on the instrument the size gets too big
4389 // sqliteReportFunction(mess, &params);
4390  return 0;
4391 }
4392 
4393 //int ISISinstrumentControl::logStatus(DAEstatus& status)
4394 //{
4395 // debug_report_arg_t params;
4396 // params.filename = m_debug_log;
4397 // params.run_number = m_crpt->run_number;
4398 // status.reportAll(m_report_func, m_report_arg, false, false);
4399 // status.reportAll(debugReportFunction, &params, false, false);
4400 // status.reportAll(sqliteReportFunction, &params, false, false);
4401 // return 0;
4402 //}
4403 
4404 int ISISinstrumentControl::logEventVa(const CRPTProxy& crpt, DAEstatus& status, const char* event, ... )
4405 {
4406  va_list ap;
4407  va_start(ap, event);
4408  int ret = logEventVaImp(time(NULL), crpt, status, event, ap);
4409  va_end(ap);
4410  return ret;
4411 }
4412 
4413 int ISISinstrumentControl::logEventVa(time_t the_time, const CRPTProxy& crpt, DAEstatus& status, const char* event, ... )
4414 {
4415  va_list ap;
4416  va_start(ap, event);
4417  int ret = logEventVaImp(the_time, crpt, status, event, ap);
4418  va_end(ap);
4419  return ret;
4420 }
4421 
4422 int ISISinstrumentControl::logEventVaImp(time_t the_time, const CRPTProxy& crpt, DAEstatus& status, const char* event, va_list ap)
4423 {
4424  char buffer[1024];
4425  vsnprintf(buffer, sizeof(buffer)-1, event, ap);
4426  NULL_TERMINATE(buffer);
4427  return logEvent(the_time, crpt, buffer, status);
4428 }
4429 
4430 int ISISinstrumentControl::logEvent(const CRPTProxy& crpt, const std::string& event, DAEstatus& status)
4431 {
4432  return logEvent(time(NULL), crpt, event, status);
4433 }
4434 
4435 int ISISinstrumentControl::logEvent(time_t the_time, const CRPTProxy& crpt, const std::string& event, DAEstatus& status)
4436 {
4437  char time_buffer[128];
4438  std::stringstream s;
4439  ISOtime(the_time, time_buffer, sizeof(time_buffer));
4440  s << time_buffer << ' ' << event << "\r\n";
4441  appendToFileAsync(crpt.eventLog().c_str(), s.str().c_str());
4442 #if 0
4443  FILE* f = fopen(m_event_log.c_str(), "a+t");
4444  if (f != NULL)
4445  {
4446  fputs(s.str().c_str(), f);
4447  fclose(f);
4448  }
4449 #endif
4450  if (crpt.isValid())
4451  {
4452  if (se_log_value_async(crpt->run_number, "ISISICP", time_buffer, "ICPEVENT", event.c_str()) != 0)
4453  {
4454  status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
4455  }
4456  }
4457  return DAEstatus::Success;
4458 }
4459 
4460 int ISISinstrumentControl::ISOtime(const struct timeb& tb, char* buffer, int len)
4461 {
4462  return ISOtime(tb.time, buffer, len);
4463 }
4464 
4465 int ISISinstrumentControl::ISOtime(time_t time, char* buffer, int len)
4466 {
4467  struct tm *tm_struct;
4468  buffer[0] = '\0';
4469  tm_struct = localtime(&time);
4470  if (tm_struct != 0)
4471  {
4472  strftime(buffer, len, "%Y-%m-%dT%H:%M:%S", tm_struct);
4473  }
4474  else
4475  {
4476  strncpy(buffer, "<UNKNOWN>", len);
4477  }
4478  buffer[len-1] = '\0';
4479  return DAEstatus::Success;
4480 }
4481 
4482 int ISISinstrumentControl::prettyTime(const struct timeb& tb, char* buffer, int len)
4483 {
4484  return prettyTime(tb.time, buffer, len);
4485 }
4486 
4487 int ISISinstrumentControl::prettyTime(time_t time, char* buffer, int len)
4488 {
4489  struct tm *tm_struct;
4490  buffer[0] = '\0';
4491  tm_struct = localtime(&time);
4492  if (tm_struct != 0)
4493  {
4494  strftime(buffer, len, "%a %d-%b-%Y %H:%M:%S", tm_struct);
4495  }
4496  else
4497  {
4498  strncpy(buffer, "<UNKNOWN>", len);
4499  }
4500  buffer[len-1] = '\0';
4501  return DAEstatus::Success;
4502 }
4503 
4504 // 0 is first period
4505 int ISISinstrumentControl::getCurrentPeriodNumber(int& period, int& daq_period, DAEstatus& status)
4506 {
4507  isisU32_t value;
4509  {
4510  period = daq_period = m_crpt->software_period; // daq and dwell are the same
4511  return DAEstatus::Success;
4512  }
4513  // hardware periods
4514  ICPCritical cs(&m_crpt_cs);
4515  m_dae->getCurrentHardwarePeriod(&value, status);
4516  period = value;
4517  m_dae->getCurrentDAQHardwarePeriod(&value, status);
4518  daq_period = value;
4519  if (period < 0 || period >= m_crpt->nper)
4520  {
4521  status.addWarningVa(FAC_DAE, "Total period number out of range (1 <= %d <= %d)", period+1, m_crpt->nper);
4522  period = m_crpt->nper - 1;
4523  }
4524  if (daq_period < 0 || daq_period >= m_crpt->nper_daq)
4525  {
4526  status.addWarningVa(FAC_DAE, "DAQ (detector card) period number out of range (1 <= %d <= %d)", daq_period+1, m_crpt->nper_daq);
4527  daq_period = m_crpt->nper_daq - 1;
4528  }
4529  if (m_crpt->period[period].daq_period >= 0)
4530  {
4531  if (daq_period != m_crpt->period[period].daq_period)
4532  {
4533  m_period_error = true;
4534  status.addInfoVa(FAC_DAE, "DAQ period mismatch for period %d: actual %d != CRPT %d", period+1, 1+daq_period, 1+m_crpt->period[period].daq_period);
4535  }
4536  else if (m_period_error)
4537  {
4538  m_period_error = false;
4539  status.addInfoVa(FAC_DAE, "DAQ period OK for period %d (=%d)", period+1, 1+daq_period);
4540  }
4541  }
4542  return DAEstatus::Success;
4543  }
4544 
4546  {
4547  ICPCritical cs(&m_crpt_cs);
4548  float f = m_dae->getGoodUAmpHours(status);
4549  return f;
4550  }
4551 
4553  {
4554  ICPCritical cs(&m_crpt_cs);
4555  float f = m_dae->getRawUAmpHours(status);
4556  return f;
4557  }
4558 
4560  {
4561  isisU32_t irf;
4562  ICPCritical cs(&m_crpt_cs);
4563  m_dae->getRawFrames(&irf, status);
4564  return irf;
4565  }
4566 
4568  {
4569  isisU32_t irf;
4570  int p, daq_p;
4571  getCurrentPeriodNumber(p, daq_p, status);
4572  ICPCritical cs(&m_crpt_cs);
4573  m_dae->getRawFramesPeriod(&irf, p, status);
4574  return irf;
4575  }
4576 
4578  {
4579  int p, daq_p;
4580  getCurrentPeriodNumber(p, daq_p, status);
4581  ICPCritical cs(&m_crpt_cs);
4582  float f = m_dae->getGoodUAmpHoursPeriod(p, status);
4583  return f;
4584  }
4585 
4587  {
4588  int p, daq_p;
4589  getCurrentPeriodNumber(p, daq_p, status);
4590  ICPCritical cs(&m_crpt_cs);
4591  float f = m_dae->getRawUAmpHoursPeriod(p, status);
4592  return f;
4593  }
4594 
4596  {
4597  isisU32_t igf;
4598  int p, daq_p;
4599  getCurrentPeriodNumber(p, daq_p, status);
4600  ICPCritical cs(&m_crpt_cs);
4601  m_dae->getGoodFramesPeriod(&igf, p, status);
4602  return igf;
4603  }
4604 
4606  {
4607  isisU32_t igf;
4608  ICPCritical cs(&m_crpt_cs);
4609  m_dae->getGoodFrames(&igf, status);
4610  return igf;
4611  }
4612 
4613  int ISISinstrumentControl::updateStatusXML(std::string& status_xml, DAEstatus& status)
4614  {
4615  if (!m_crpt.isValid())
4616  {
4617  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "CRPT is NULL");
4618  return status.result();
4619  }
4620  char buffer[64];
4621  isisU32_t value32;
4622  ICPCritical cs(&m_crpt_cs);
4623  LabviewXML lvxml(status);
4627  lvxml.loadFromString(status_xml.c_str(), status);
4628 
4629  lvxml.setValue("BeamCurrent", m_crpt->beam_current, status);
4630  lvxml.setValue("TotalUAmps", m_crpt->update_good_uamph, status);
4631  lvxml.setValue("RunStatus", m_crpt->run_status, status);
4632 
4633  sprintf(buffer, "%0*d", m_run_number_digits, m_crpt->run_number);
4634  lvxml.setValue("RunNumber", buffer, status);
4640  lvxml.setValue("GoodFramesTotal", m_crpt->update_good_frames, status);
4641  lvxml.setValue("RawFramesTotal", m_crpt->update_raw_frames, status);
4644  int period = m_crpt->update_period;
4645  PERIOD& this_period = m_crpt->period[period];
4646  lvxml.setValue("Period Type", m_crpt->period_type, status);
4647  lvxml.setValue("PeriodLabel", this_period.label, status);
4650  lvxml.setValue("PeriodSequence", m_crpt->update_period_sequence, status);
4651 
4652 #if 0
4653  if (isRunning())
4654  {
4656  {
4657  lvxml.setValue("GoodFramesPeriod", this_period.good_frames + (igf - m_crpt->good_frames), status);
4658  lvxml.setValue("RawFramesPeriod", this_period.total_frames + (irf - m_crpt->total_frames), status);
4659  }
4660  else
4661  {
4662  m_dae->getRawFramesPeriod(&irf, period, status);
4663  m_dae->getGoodFramesPeriod(&igf, period, status);
4664  lvxml.setValue("GoodFramesPeriod", igf, status);
4665  lvxml.setValue("RawFramesPeriod", irf, status);
4666  }
4667  lvxml.setValue("RunDurationTotal", m_crpt->duration + this_dur, status);
4668  lvxml.setValue("RunDurationPeriod", this_period.duration + this_dur, status);
4669  }
4670  else
4671  {
4673  {
4674  lvxml.setValue("GoodFramesPeriod", this_period.good_frames, status);
4675  lvxml.setValue("RawFramesPeriod", this_period.total_frames, status);
4676  }
4677  else
4678  {
4679  m_dae->getRawFramesPeriod(&irf, period, status);
4680  m_dae->getGoodFramesPeriod(&igf, period, status);
4681  lvxml.setValue("GoodFramesPeriod", igf, status);
4682  lvxml.setValue("RawFramesPeriod", irf, status);
4683  }
4684  lvxml.setValue("RunDurationTotal", m_crpt->duration, status);
4685  lvxml.setValue("RunDurationPeriod", this_period.duration, status);
4686  }
4687 #endif
4688  lvxml.setValue("RunDurationTotal", m_crpt->update_duration, status);
4689  lvxml.setValue("RunDurationPeriod", m_crpt->update_duration_period, status);
4690  lvxml.setValue("GoodFramesPeriod", m_crpt->update_good_frames_period, status);
4691  lvxml.setValue("RawFramesPeriod", m_crpt->update_raw_frames_period, status);
4692 
4693  lvxml.setValue("CurrentPeriod", period+1, status);
4694  prettyTime(m_crpt->start_time, buffer, sizeof(buffer));
4695  lvxml.setValue("StartTime", buffer, status);
4696  lvxml.setValue("DAETimingSource", m_crpt->tcb_sync, status);
4697  lvxml.setValue("NumberOfSpectra", m_crpt->getNumSpectra(), status);
4698  lvxml.setValue("NumberOfTimeChannels", m_crpt->ntc[0], status); // time regime 1 only
4699  lvxml.setValue("NumberOfPeriods", m_crpt->nper, status);
4700  lvxml.setValue("MonitorSpectrum", m_crpt->monitor_spectrum, status);
4701  lvxml.setValue("MonitorFrom", m_crpt->monitor_range[0][0], status);
4702  lvxml.setValue("MonitorTo", m_crpt->monitor_range[0][1], status);
4703  lvxml.setValue("MonitorCounts", m_crpt->monitor_sum[0], status);
4704  lvxml.setValue("CountRate", m_crpt->count_rate, status);
4705  lvxml.setValue("TotalDAECounts", (float)m_crpt->update_total_counts / (float)1e6, status);
4706  lvxml.setValue("InstName", m_crpt->inst_name, status);
4707 // lvxml.setValue("InstAbrv", m_crpt->inst_abrv, status);
4708  std::string run_title;
4709  if (m_simulation_mode)
4710  {
4711  run_title = "(DAE SIMULATION MODE) ";
4712  }
4713  run_title.append(m_crpt->long_title);
4714  lvxml.setValue("RunTitle", run_title.c_str(), status);
4715  lvxml.setValue("UserName", m_crpt->user_name, status);
4716  lvxml.setValue("RBNumber", m_crpt->rb_number, status);
4717  lvxml.setValue("UserTelephone", m_crpt->user_telephone, status);
4718  value32 = m_crpt->getPeriodSize() * m_crpt->nper_daq / 256; // in Kb
4719  lvxml.setValue("DAEMemoryUsed", value32, status);
4720  prettyTime(m_crpt->update_time, buffer, sizeof(buffer));
4721  lvxml.setValue("Last Refresh Time", buffer, status);
4722  lvxml.setValue("Refresh Frequency", m_crpt->update_poll_time, status);
4723  lvxml.setValue("N/P Ratio", m_crpt->update_npratio_current, status);
4724  lvxml.setValue("ISISCycle", m_crpt->isis_cycle, status);
4725  lvxml.setValue("LocalContact", m_crpt->local_contact, status);
4726  lvxml.setValue("EventModeCardFraction", m_crpt->eventModeCardFraction(), status);
4727 
4728  lvxml.saveToString(status_xml, status);
4729  return 0;
4730  }
4731 
4732 // -1 on error or DWELL period, else DAQ period number
4733 // if period < 0 return current daq period
4735  {
4736  int daq_period;
4737  if (period < 0)
4738  {
4739  getCurrentPeriodNumber(period, daq_period, status);
4740  return daq_period;
4741  }
4742  if (period < 0 || period >= m_crpt->nper)
4743  {
4744  return -1;
4745  }
4746  return m_crpt->period[period].daq_period;
4747  }
4748 
4749  // sum is total counts excluding channel 0
4750  int ISISinstrumentControl::getSpectrum(long spectrum_number, long period, double* time_array, double* signal_array, double* error_array,
4751  bool as_histogram, bool as_distribution, long& sum, DAEstatus& status)
4752  {
4753  unsigned long i;
4754  float tr_shift;
4755  ICPCritical cs(&m_crpt_cs);
4756 // m_dae->getNTimeChannels(&ntcdae, status);
4757  int ntc = m_crpt->spectrumNTC(spectrum_number);
4758  unsigned long* buffer = new unsigned long[ntc+1];
4759  int perspec = m_crpt->getNumSpectra(true); // number of spectra in a period
4760  sum = 0;
4761 // allow for periods
4762  int daq_period = getDAQPeriod(period, status);
4763  if (daq_period >= 0)
4764  {
4765  if (m_crpt->isEventSpectrum(spectrum_number))
4766  {
4767  memcpy(buffer, &(m_crpt.rawData()[ m_crpt.spectrumCRPTOffset(spectrum_number, daq_period) ]) ,(ntc+1)*sizeof(uint32_t));
4768  }
4769  else
4770  {
4771  m_dae->readDAE1Spectrum(spectrum_number + daq_period * perspec, buffer, ntc+1, status);
4772  }
4773  }
4774  else
4775  {
4776  memset(buffer, 0, (ntc+1) * sizeof(unsigned long)); // DWELL period; no data
4777  }
4778  int tr_index = m_crpt->spectrumCRPTTR(spectrum_number) - 1;
4779  tr_shift = m_crpt->tcr[tr_index][0].start - m_crpt->rtcb[tr_index][0];
4780  if (as_histogram)
4781  {
4782  for(i=0; i<ntc+1; i++)
4783  {
4784  time_array[i] = m_crpt->rtcb[tr_index][i] + tr_shift;
4785  }
4786  for(i=0; i<ntc; i++)
4787  {
4788  if (as_distribution)
4789  {
4790  signal_array[i] = (double)buffer[i+1] / (time_array[i+1] - time_array[i]);
4791  error_array[i] = sqrt((double)buffer[i+1]) / (time_array[i+1] - time_array[i]);
4792  }
4793  else
4794  {
4795  signal_array[i] = (double)buffer[i+1];
4796  error_array[i] = sqrt((double)buffer[i+1]);
4797  }
4798  sum += buffer[i+1];
4799  }
4800  }
4801  else
4802  {
4803  for(i=0; i<ntc; i++)
4804  {
4805  time_array[i] = tr_shift + (m_crpt->rtcb[tr_index][i] + m_crpt->rtcb[tr_index][i+1]) / 2.0;
4806  if (as_distribution)
4807  {
4808  signal_array[i] = (double)buffer[i+1] / (m_crpt->rtcb[tr_index][i+1] - m_crpt->rtcb[tr_index][i]);
4809  error_array[i] = sqrt((double)buffer[i+1]) / (m_crpt->rtcb[tr_index][i+1] - m_crpt->rtcb[tr_index][i]);
4810  }
4811  else
4812  {
4813  signal_array[i] = buffer[i+1];
4814  error_array[i] = sqrt((double)buffer[i+1]);
4815  }
4816  sum += buffer[i+1];
4817  }
4818  }
4819  delete[] buffer;
4820  return 0;
4821  }
4822 
4824  {
4825 // isisU32_t ntc;
4826 // lockCRPT();
4827 // m_dae->getNTimeChannels(&ntc, status);
4828 // unlockCRPT();
4829 // return ntc;
4830  return m_crpt->spectrumNTC(spectrum);
4831  }
4832 
4833  // nsp1 i.e. excluding specytrum 0
4835  {
4836  return m_crpt->getNumSpectra(false);
4837  }
4838 
4840  {
4841  return m_crpt->nper;
4842  }
4843 
4844  int ISISinstrumentControl::getSpectrumIntegral(long spec_no, long period, float t_low, float t_high, long& integral, long& max_val, DAEstatus& status)
4845  {
4846  return getSpectrumIntegral(1, &spec_no, period, &t_low, &t_high, &integral, &max_val, status);
4847  }
4848 
4849  int ISISinstrumentControl::getCRPTSpectrumIntegral(long spec_no, long period, float t_low, float t_high, long& integral, long& max_val, DAEstatus& status)
4850  {
4851  return getCRPTSpectrumIntegral(1, &spec_no, period, &t_low, &t_high, &integral, &max_val, status);
4852  }
4853 
4854  int ISISinstrumentControl::getCRPTSpectrumIntegral(long spec_start, int nspectra, long period, float t_low,
4855  float t_high, long integral[], long max_val[], DAEstatus& status)
4856  {
4857  long j, k;
4858  for(long i=0; i < nspectra; ++i)
4859  {
4860  j = i + spec_start;
4861  getCRPTSpectrumIntegral(1, &j, period, &t_low, &t_high, integral + i, (max_val != NULL ? max_val + i : &k), status);
4862  }
4863  return status.result();
4864  }
4865 
4866 
4867  int ISISinstrumentControl::getCRPTSpectrumIntegral(long n, const long spec_no[], long period, const float t_low[],
4868  const float t_high[], long integral[], long max_val[], DAEstatus& status)
4869  {
4870  bool full_range;
4871  int i, j, ntc, tr_index;
4872  ICPCritical cs(&m_crpt_cs);
4873 // allow for periods
4874  int daq_period = getDAQPeriod(period, status);
4875  for(i=0; i<n; i++)
4876  {
4877  tr_index = m_crpt->spectrumCRPTTR(spec_no[i]) - 1;
4878  const float* rtcb = m_crpt->rtcb[tr_index];
4879  ntc = m_crpt->ntc[tr_index];
4880  integral[i] = 0;
4881  max_val[i] = 0;
4882  if (t_high[i] > t_low[i])
4883  {
4884  full_range = false;
4885  }
4886  else
4887  {
4888  full_range = true;
4889  }
4890  if (daq_period >= 0)
4891  {
4892  const isisU32_t* raw_base = m_crpt.rawData() + m_crpt.spectrumCRPTOffset(spec_no[i], daq_period);
4893  for(j=0; j<ntc; j++)
4894  {
4895  float contrib = 0.0;
4896  float width = rtcb[j+1] - rtcb[j];
4897  if (full_range)
4898  {
4899  contrib = 1.0;
4900  }
4901  else if ( (rtcb[j] >= t_low[i]) && (rtcb[j+1] <= t_high[i]) )
4902  {
4903  contrib = 1.0;
4904  }
4905  else if ( (rtcb[j] < t_low[i]) && (rtcb[j+1] >= t_low[i]) && (rtcb[j+1] <= t_high[i]) )
4906  {
4907  contrib = (rtcb[j+1] - t_low[i]) / width;
4908  }
4909  else if ( (rtcb[j] >= t_low[i]) && (rtcb[j] <= t_high[i]) && (rtcb[j+1] > t_high[i]) )
4910  {
4911  contrib = (t_high[i] - rtcb[j]) / width;
4912  }
4913  else if ( (rtcb[j] < t_low[i]) && (rtcb[j+1] > t_high[i]) )
4914  {
4915  contrib = (t_high[i] - t_low[i]) / width;
4916  }
4917  if (contrib > 0.0)
4918  {
4919  integral[i] += ( contrib == 1.0 ? raw_base[j+1] : (int)floor(0.5 + contrib * raw_base[j+1]) );
4920  if (raw_base[j+1] > max_val[i])
4921  {
4922  max_val[i] = raw_base[j+1];
4923  }
4924  }
4925  }
4926  }
4927  }
4928  return status.result();
4929  }
4930 
4932  int ISISinstrumentControl::getCRPTSpectrumIntegral(long spec_start, int nspectra, long period, long integral[], DAEstatus& status)
4933  {
4934  int i, j, spec_no;
4935  unsigned long* buffer;
4936  ICPCritical cs(&m_crpt_cs);
4937  int perspec = m_crpt->getNumSpectra(true);
4938 // allow for periods
4939  int daq_period = getDAQPeriod(period, status);
4940  const isisU32_t* spec_integrals = m_crpt.spectrumIntegrals();
4941  for(i=0; i<nspectra; i++)
4942  {
4943  integral[i] = 0;
4944  spec_no = spec_start + i;
4945  if (daq_period >= 0)
4946  {
4947  if (m_crpt->isEventSpectrum(spec_no))
4948  {
4949  integral[i] = spec_integrals[spec_no];
4950  }
4951  }
4952  }
4953  return status.result();
4954  }
4955 
4956  int ISISinstrumentControl::getSpectrumIntegral(long n, const long spec_no[], long period, const float t_low[],
4957  const float t_high[], long integral[], long max_val[], DAEstatus& status)
4958  {
4959  bool full_range;
4960  int i, j, ntc, tr_index;
4961  unsigned long* buffer;
4962  ICPCritical cs(&m_crpt_cs);
4963  int perspec = m_crpt->getNumSpectra(true);
4964 // allow for periods
4965  int daq_period = getDAQPeriod(period, status);
4966  for(i=0; i<n; i++)
4967  {
4968  tr_index = m_crpt->spectrumCRPTTR(spec_no[i]) - 1;
4969  const float* rtcb = m_crpt->rtcb[tr_index];
4970  ntc = m_crpt->ntc[tr_index];
4971  buffer = new unsigned long[ntc+1];
4972  integral[i] = 0;
4973  max_val[i] = 0;
4974  if (t_high[i] > t_low[i])
4975  {
4976  full_range = false;
4977  }
4978  else
4979  {
4980  full_range = true;
4981  }
4982  if (daq_period >= 0)
4983  {
4984  if (m_crpt->isEventSpectrum(spec_no[i]))
4985  {
4986  memcpy(buffer, &(m_crpt.rawData()[ m_crpt.spectrumCRPTOffset(spec_no[i], daq_period) ]) ,(ntc+1)*sizeof(uint32_t));
4987  }
4988  else
4989  {
4990  m_dae->readDAE1Spectrum(spec_no[i] + daq_period * perspec, buffer, ntc+1, status);
4991  }
4992  for(j=0; j<ntc; j++)
4993  {
4994  if ( full_range || ((rtcb[j] >= t_low[i]) && (rtcb[j+1] <= t_high[i])) )
4995  {
4996  integral[i] += buffer[j+1];
4997  if (buffer[j+1] > max_val[i])
4998  {
4999  max_val[i] = buffer[j+1];
5000  }
5001  }
5002  }
5003  }
5004  delete[] buffer;
5005  }
5006  return status.result();
5007  }
5008 
5009 // given a monitor number rather than a spectrum
5010  int ISISinstrumentControl::getMonitorIntegral(long monitor, long period, float t_low, float t_high, long& integral, DAEstatus& status)
5011  {
5012  long i, max_val;
5013  integral = 0;
5014  if ((monitor > 0) && (monitor <= m_crpt->nmon))
5015  {
5016  i = m_crpt->mdet[monitor-1] - 1; // mdet starts at 1 for historical reasons
5017  if (i >=0 && i < m_crpt->ndet)
5018  {
5019  return getSpectrumIntegral(m_crpt->spec[i], period, t_low, t_high, integral, max_val, status);
5020  }
5021  }
5022  else
5023  {
5024  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Invalid monitor number %d", monitor);
5025  }
5026  return status.result();
5027  }
5028 
5029  int ISISinstrumentControl::getMonitorIntegral(long n, const long monitor[], long period, const float t_low[], const float t_high[], long integral[], DAEstatus& status)
5030  {
5031  long i;
5032  for(i=0; i<n; i++)
5033  {
5034  getMonitorIntegral(monitor[i], period, t_low[i], t_high[i], integral[i], status);
5035  }
5036  return 0;
5037  }
5038 
5039 
5040 int ISISinstrumentControl::getUpdateSettingsXML(const std::string& update_xml_in, std::string& update_xml_out, DAEstatus& status)
5041 {
5042  ICPCritical cs(&m_crpt_cs);
5043  LabviewXML lvxml(status);
5044  lvxml.loadFromString(update_xml_in.c_str(), status);
5045  if (m_crpt->lvxml_update[0] != '\0')
5046  {
5047  lvxml.updateFromString(m_crpt->lvxml_update, status);
5048  }
5049 
5050  lvxml.setValue("Frequency", m_crpt->auto_save_value, status);
5051  lvxml.setValue("Units", m_crpt->auto_save_type, status);
5052  lvxml.setValue("Dashboard Update Interval", m_crpt->update_poll_time, status);
5053 
5054  lvxml.saveToString(update_xml_out, status);
5055  return status.result();
5056 }
5057 
5058 int ISISinstrumentControl::changeUpdateSettingsXML(const std::string& update_xml, DAEstatus& status)
5059 {
5060  if (!m_crpt.isValid())
5061  {
5062  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "CRPT is NULL");
5063  return status.result();
5064  }
5065  LabviewXML lvxml(status);
5066  if ((update_xml.size() == 0) || (lvxml.loadFromString(update_xml.c_str(), status) != 0))
5067  {
5068  status.addWarning(FAC_CRPT, "UPDATE XML invalid - ignored");
5069  return status.result();
5070  }
5071  ICPCritical cs(&m_crpt_cs);
5072  strncpy(m_crpt->lvxml_update, update_xml.c_str(), sizeof(m_crpt->lvxml_update));
5074  m_recovery_map["update"] = update_xml;
5075 
5076  lvxml.getValue("Frequency", m_crpt->auto_save_value, status);
5077  lvxml.getValue("Units", m_crpt->auto_save_type, status);
5078  lvxml.getValue("Dashboard Update Interval", m_crpt->update_poll_time, status);
5079 
5080  return status.result();
5081 }
5082 
5084 int ISISinstrumentControl::getTCBXML(const std::string& tcb_xml_in, std::string& tcb_xml_out, DAEstatus& status)
5085 {
5086  ICPCritical cs(&m_crpt_cs);
5087  LabviewXML lvxml(status);
5088  lvxml.loadFromString(tcb_xml_in.c_str(), status);
5089  if (m_crpt->lvxml_tcb[0] != '\0')
5090  {
5091  lvxml.updateFromString(m_crpt->lvxml_tcb, status);
5092  }
5093  char buffer[256];
5094  int i, j;
5096  {
5097  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many time regimes");
5098  return status.result();
5099  }
5100  if (m_crpt->tcr[0][0].mode == TCBRANGE_FILE)
5101  {
5102  lvxml.setValue("Time Channel File", m_crpt->tcr[0][0].tcb_file.fname, status);
5103  lvxml.setValue("Calculation Method", 1, status);
5104  }
5105  else
5106  {
5107  lvxml.setValue("Calculation Method", 0, status);
5108  for(j=0; j<LV_NUM_TIME_REGIMES; j++)
5109  {
5110  for(i=0; i<5; i++)
5111  {
5112  TCBRANGE& tcr = m_crpt->tcr[j][i];
5113  sprintf(buffer, "TR%d From %d", j+1, i+1);
5114  lvxml.setValue(buffer, tcr.start, status);
5115  sprintf(buffer, "TR%d To %d", j+1, i+1);
5116  lvxml.setValue(buffer, tcr.end, status);
5117  sprintf(buffer, "TR%d In Mode %d", j+1, i+1);
5118  lvxml.setValue(buffer, tcr.mode, status);
5119  sprintf(buffer, "TR%d Steps %d", j+1, i+1);
5120  lvxml.setValue(buffer, tcr.tcpar[0], status);
5121  }
5122  }
5123  }
5124 
5125  lvxml.saveToString(tcb_xml_out, status);
5126  return status.result();
5127 }
5128 
5129 
5130  int ISISinstrumentControl::updateTCBXML(const std::string& tcb_xml, DAEstatus& status)
5131  {
5132  int i, j;
5133  md5checksum_t csum;
5134  md5sumString((const unsigned char*)tcb_xml.c_str(), tcb_xml.length(), csum, status);
5136  {
5138  {
5139  status.addInfo(FAC_CRPT, "TCB not updated (as RUNNING)");
5140  }
5141  else
5142  {
5143  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change TCB in SETUP state");
5144  }
5145  return status.result();
5146  }
5148  {
5149  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many time regimes");
5150  return status.result();
5151  }
5152  char buffer[256];
5153  LabviewXML lvxml(status);
5154  if ((tcb_xml.size() == 0) || (lvxml.loadFromString(tcb_xml.c_str(), status) != 0))
5155  {
5156  status.addWarning(FAC_CRPT, "TCB XML invalid - ignored");
5157  return status.result();
5158  }
5159  ICPCritical cs(&m_crpt_cs);
5161  strncpy(m_crpt->lvxml_tcb, tcb_xml.c_str(), sizeof(m_crpt->lvxml_tcb));
5163  lvxml.getValue("Calculation Method", i, status);
5164  if (i == 0)
5165  {
5166  m_crpt->ntrg = 0;
5167  for(j=0; j<LV_NUM_TIME_REGIMES; j++)
5168  {
5169  m_crpt->ntcr[j] = 0;
5170  for(i=0; i<5; i++)
5171  {
5172  TCBRANGE& tcr = m_crpt->tcr[j][i];
5173  sprintf(buffer, "TR%d From %d", j+1, i+1);
5174  lvxml.getValue(buffer, tcr.start, status);
5175  sprintf(buffer, "TR%d To %d", j+1, i+1);
5176  lvxml.getValue(buffer, tcr.end, status);
5177  sprintf(buffer, "TR%d In Mode %d", j+1, i+1);
5178  lvxml.getValue(buffer, tcr.mode, status);
5179  sprintf(buffer, "TR%d Steps %d", j+1, i+1);
5180  lvxml.getValue(buffer, tcr.tcpar[0], status);
5181  tcr.npar = 1;
5182  // is it a valid range
5183  if ( (tcr.start < tcr.end) && (tcr.tcpar[0] > 0.0) )
5184  {
5185  (m_crpt->ntcr[j])++;
5186  m_crpt->ntrg = j + 1;
5187  }
5188  }
5189  }
5190  }
5191  else
5192  {
5193  m_crpt->ntrg = 1;
5194  m_crpt->ntcr[0] = 1;
5195  m_crpt->tcr[0][0].mode = TCBRANGE_FILE;
5196  lvxml.getValue("Time Channel File", m_crpt->tcr[0][0].tcb_file.fname, sizeof(m_crpt->tcr[0][0].tcb_file.fname), true, status);
5197  }
5198  tcbcalc(status);
5199  return status.result();
5200  }
5201 
5202  int ISISinstrumentControl::updateUserXML(const std::string& user_xml, DAEstatus& status)
5203  {
5204  ICPCritical cs(&m_crpt_cs);
5205  LabviewXML lvxml(status);
5206  m_recovery_map["user"] = user_xml;
5207  lvxml.loadFromString(user_xml.c_str(), status);
5208 
5209  lvxml.getValue("ISIS User Number", m_crpt->user_id, sizeof(m_crpt->user_id), true, status);
5210  lvxml.getValue("User Name", m_crpt->user_name, sizeof(m_crpt->user_name), true, status);
5211  lvxml.getValue("Institute", m_crpt->institute, sizeof(m_crpt->institute), true, status);
5212  lvxml.getValue("Telephone", m_crpt->user_telephone, sizeof(m_crpt->user_telephone), true, status);
5213  lvxml.getValue("Email Address", m_crpt->user_email, sizeof(m_crpt->user_email), true, status);
5214  lvxml.getValue("RB (proposal) Number", m_crpt->rb_number, status);
5215 
5218 
5219  return status.result();
5220  }
5221 
5222 int ISISinstrumentControl::getHardwarePeriodsXML(const std::string& periods_xml_in, std::string& periods_xml_out, DAEstatus& status)
5223 {
5224  int i;
5225  char name[64];
5226  ICPCritical cs(&m_crpt_cs);
5227  LabviewXML lvxml(status);
5228  lvxml.loadFromString(periods_xml_in.c_str(), status);
5229  if (m_crpt->lvxml_periods[0] != '\0')
5230  {
5231  lvxml.updateFromString(m_crpt->lvxml_periods, status);
5232  }
5233  lvxml.setValue("Period Setup Source", m_crpt->period_source, status);
5234  lvxml.setValue("Period File", m_crpt->period_file, status);
5235  lvxml.setValue("Period Type", m_crpt->period_type, status);
5237  {
5238  lvxml.setValue("Number Of Software Periods", m_crpt->nper, status);
5239  }
5240  else
5241  {
5242  lvxml.setValue("Number Of Software Periods", 1, status);
5244  {
5245  for(i=0; i<8; i++)
5246  {
5247  sprintf(name, "Type %d", i+1);
5248  lvxml.setValue(name, m_crpt->period[i].type, status);
5249  sprintf(name, "Frames %d", i+1);
5250  lvxml.setValue(name, m_crpt->period[i].requested_frames, status);
5251  sprintf(name, "Output %d", i+1);
5252  lvxml.setValue(name, m_crpt->period[i].output, status);
5253  sprintf(name, "Label %d", i+1);
5254  lvxml.setValue(name, m_crpt->period[i].label, status);
5255  }
5256  }
5257  }
5258  lvxml.setValue("Output Delay (us)", m_crpt->period_output_delay, status);
5259  lvxml.setValue("Hardware Period Sequences", m_crpt->nperseq_request, status);
5260  lvxml.saveToString(periods_xml_out, status);
5261  return status.result();
5262 }
5263 
5264 int ISISinstrumentControl::updateHardwarePeriodsXML(const std::string& periods_xml, DAEstatus& status)
5265  {
5266  char name[64];
5267  int i, daq_period, nperiod;
5269  {
5270  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change Periods configuration in SETUP state");
5271  return status.result();
5272  }
5273  LabviewXML lvxml(status);
5274  if ((periods_xml.size() == 0) || (lvxml.loadFromString(periods_xml.c_str(), status) != 0))
5275  {
5276  status.addWarning(FAC_CRPT, "PERIODS XML invalid - ignored");
5277  return status.result();
5278  }
5279  ICPCritical cs(&m_crpt_cs);
5280  strncpy(m_crpt->lvxml_periods, periods_xml.c_str(), sizeof(m_crpt->lvxml_periods));
5282 
5283  lvxml.getValue("Period Setup Source", m_crpt->period_source, status);
5284  lvxml.getValue("Period File", m_crpt->period_file, sizeof(m_crpt->period_file), true, status);
5285 
5286  lvxml.getValue("Period Type", m_crpt->period_type, status);
5287  lvxml.getValue("Output Delay (us)", m_crpt->period_output_delay, status);
5288  lvxml.getValue("Hardware Period Sequences", m_crpt->nperseq_request, status);
5289 
5291  {
5292  lvxml.getValue("Number Of Software Periods", nperiod, status);
5293  changeNumberOfSoftwarePeriods(nperiod, status);
5294  status.addInfo(FAC_CRPT, "Hardware period table ignored as using software periods");
5295  return status.result();
5296  }
5297  daq_period = 0;
5298  int ndwell = 0;
5300  {
5301  FILE* periods_info = _fsopen(m_crpt->period_file, "rtN", _SH_DENYNO);
5302  if (periods_info == NULL)
5303  {
5304  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Unable to read periods file %s", m_crpt->period_file);
5305  return status.result();
5306  }
5307  for(i=0; (i < ISISCRPT_MAX_PERIOD) &&
5308  (fscanf(periods_info, "%s %d %d %s", name, &(m_crpt->period[i].requested_frames), &(m_crpt->period[i].output), m_crpt->period[i].label) == 4); i++)
5309  {
5310  NULL_TERMINATE(name);
5311  if (!stricmp(name, "DAQ"))
5312  {
5313  m_crpt->period[i].daq_period = daq_period++;
5314  }
5315  else if (!stricmp(name, "DWELL"))
5316  {
5317  m_crpt->period[i].daq_period = -1;
5318  ndwell++;
5319  }
5320  else
5321  {
5322  m_crpt->period[i].daq_period = -1; // unused or unknown
5323  }
5324  }
5325  fclose(periods_info);
5326  }
5327  else
5328  {
5329  for(i=0; i<8; i++)
5330  {
5331  sprintf(name, "Type %d", i+1);
5332  lvxml.getValue(name, m_crpt->period[i].type, status);
5333  sprintf(name, "Frames %d", i+1);
5334  lvxml.getValue(name, m_crpt->period[i].requested_frames, status);
5335  sprintf(name, "Output %d", i+1);
5336  lvxml.getValue(name, m_crpt->period[i].output, status);
5337  sprintf(name, "Label %d", i+1);
5338  lvxml.getValue(name, m_crpt->period[i].label, sizeof(m_crpt->period[i].label), true, status);
5339  switch(m_crpt->period[i].type)
5340  {
5341  case 0: // usused
5342  m_crpt->period[i].daq_period = -1;
5343  break;
5344  case 1: // DAQ
5345  m_crpt->period[i].daq_period = daq_period++;
5346  break;
5347  case 2: // DWELL
5348  m_crpt->period[i].daq_period = -1;
5349  ndwell++;
5350  break;
5351  default:
5353  "invalid period type");
5354  break;
5355  }
5356  }
5357  }
5358  if (daq_period + ndwell > ISISCRPT_MAX_PERIOD)
5359  {
5360  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "invalid number of hardware periods %d", daq_period + ndwell);
5361  return DAEstatus::Failure;
5362  }
5363  if (daq_period <= 0)
5364  {
5365  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "invalid number of daq hardware periods %d", daq_period);
5366  return DAEstatus::Failure;
5367  }
5368  m_crpt->nper = daq_period + ndwell;
5369  status.addInfoVa(FAC_CRPT, "Programmed %d periods (%d DAQ, %d DWELL) for %d sequences from %s",
5370  m_crpt->nper, daq_period, ndwell, m_crpt->nperseq_request,
5372  );
5373  m_crpt->nper_daq = daq_period;
5374  return status.result();
5375  }
5376 
5377 
5378  int ISISinstrumentControl::updateSampleXML(const std::string& sample_xml, DAEstatus& status)
5379  {
5380 // if (m_crpt->run_status != RUNSTATUS_SETUP)
5381 // {
5382 // status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change DAE in SETUP state");
5383 // return status.result();
5384 // }
5385  ICPCritical cs(&m_crpt_cs);
5386  LabviewXML lvxml(status);
5387  m_recovery_map["sample"] = sample_xml;
5388  lvxml.loadFromString(sample_xml.c_str(), status);
5389 
5390  lvxml.getValue("SampleName", m_crpt->sample_name, sizeof(m_crpt->sample_name), true, status);
5391  lvxml.getValue("SampleOrientation", m_crpt->sample_orientation, sizeof(m_crpt->sample_orientation), true, status);
5392  lvxml.getValue("FieldLabel", m_crpt->field_label, sizeof(m_crpt->field_label), true, status);
5393  lvxml.getValue("TemperatureLabel", m_crpt->temperature_label, sizeof(m_crpt->temperature_label), true, status);
5394  lvxml.getValue("Comments", m_crpt->comment, sizeof(m_crpt->comment), true, status);
5395  lvxml.getValue("InstrumentGeometry", m_crpt->instrument_geometry, sizeof(m_crpt->instrument_geometry), true, status);
5396  _snprintf(m_crpt->long_title, sizeof(m_crpt->long_title), "%s T=%s F=%s", m_crpt->sample_name, m_crpt->temperature_label, m_crpt->field_label);
5398  return status.result();
5399  }
5400 
5401 int ISISinstrumentControl::getDAEsettingsXML(const std::string& dae_xml_in, std::string& dae_xml_out, DAEstatus& status)
5402 {
5403  ICPCritical cs(&m_crpt_cs);
5404  LabviewXML lvxml(status);
5405  lvxml.loadFromString(dae_xml_in.c_str(), status);
5406  if (m_crpt->lvxml_dae[0] != '\0')
5407  {
5408  lvxml.updateFromString(m_crpt->lvxml_dae, status);
5409  }
5410 
5411  lvxml.setValue("DAETimingSource", m_crpt->tcb_sync, status);
5412 
5413  lvxml.setValue("Monitor Spectrum", m_crpt->monitor_spectrum, status);
5414  lvxml.setValue("from", m_crpt->monitor_range[0][0], status);
5415  lvxml.setValue("to", m_crpt->monitor_range[0][1], status);
5416  lvxml.setValue("SMP (Chopper) Veto", m_crpt->vetos[SMPVeto].enabled, status);
5417  lvxml.setValue("Veto 0", m_crpt->vetos[Ext0Veto].enabled, status);
5418  lvxml.setValue("Veto 1", m_crpt->vetos[Ext1Veto].enabled, status);
5419  lvxml.setValue("Veto 2", m_crpt->vetos[Ext2Veto].enabled, status);
5420  lvxml.setValue("Veto 3", m_crpt->vetos[Ext3Veto].enabled, status);
5421  lvxml.setValue("Wiring Table", m_crpt->wiring_table.fname, status);
5422  lvxml.setValue("Detector Table", m_crpt->detector_table.fname, status);
5423  lvxml.setValue("Spectra Table", m_crpt->spectra_table.fname, status);
5424 
5425  lvxml.setValue("Muon Cerenkov Pulse", m_crpt->muon_cerenkov_pulse, status);
5426  lvxml.setValue("Fermi Chopper Veto", m_crpt->vetos[FermiChopperVeto0].enabled, status);
5427  double fcdelay, fcwidth; // these are read in us
5428  fcdelay = m_crpt->fermi_chopper_delay[0] / 50.0; // convert from 20 ns bins
5429  fcwidth = m_crpt->fermi_chopper_width[0] / 50.0;
5430  lvxml.setValue("FC Delay", fcdelay, status);
5431  lvxml.setValue("FC Width", fcwidth, status);
5432 
5433  lvxml.setValue("TS2 Pulse Veto", m_crpt->vetos[TS2PulseVeto].enabled, status);
5434  lvxml.setValue("ISIS 50Hz Veto", m_crpt->vetos[ISIS50HzVeto].enabled, status);
5435 
5436  lvxml.saveToString(dae_xml_out, status);
5437  return status.result();
5438 }
5439 
5440  int ISISinstrumentControl::updateDAEsettingsXML(const std::string& dae_xml, DAEstatus& status)
5441  {
5442  md5checksum_t csum;
5443  md5sumString((const unsigned char*)dae_xml.c_str(), dae_xml.length(), csum, status);
5445  {
5447  {
5448  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change DAE in SETUP state");
5449 // status.addInfo(FAC_CRPT, "DAE info not updated (as RUNNING)");
5450  }
5451  else
5452  {
5453  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change DAE in SETUP state");
5454  }
5455  return status.result();
5456  }
5457  LabviewXML lvxml(status);
5458  if ((dae_xml.size() == 0) || (lvxml.loadFromString(dae_xml.c_str(), status) != 0))
5459  {
5460  status.addWarning(FAC_CRPT, "DAE XML invalid - ignored");
5461  return status.result();
5462  }
5463  std::string wiring_table, detector_table, spectra_table;
5464  ICPCritical cs(&m_crpt_cs);
5465  strncpy(m_crpt->lvxml_dae, dae_xml.c_str(), sizeof(m_crpt->lvxml_dae));
5468 
5469  int tcb_sync;
5470  lvxml.getValue("DAETimingSource", tcb_sync, status);
5471  m_crpt->tcb_sync = (FrameSync)tcb_sync;
5472 
5473  lvxml.getValue("Monitor Spectrum", m_crpt->monitor_spectrum, status);
5474  lvxml.getValue("from", m_crpt->monitor_range[0][0], status);
5475  lvxml.getValue("to", m_crpt->monitor_range[0][1], status);
5476  lvxml.getValue("SMP (Chopper) Veto", m_crpt->vetos[SMPVeto].enabled, status);
5477  lvxml.getValue("Veto 0", m_crpt->vetos[Ext0Veto].enabled, status);
5478  lvxml.getValue("Veto 1", m_crpt->vetos[Ext1Veto].enabled, status);
5479  lvxml.getValue("Veto 2", m_crpt->vetos[Ext2Veto].enabled, status);
5480  lvxml.getValue("Veto 3", m_crpt->vetos[Ext3Veto].enabled, status);
5481  lvxml.getValue("Wiring Table", wiring_table, status);
5482  lvxml.getValue("Detector Table", detector_table, status);
5483  lvxml.getValue("Spectra Table", spectra_table, status);
5484 
5485  lvxml.getValue("Muon Cerenkov Pulse", m_crpt->muon_cerenkov_pulse, status);
5486  lvxml.getValue("Fermi Chopper Veto", m_crpt->vetos[FermiChopperVeto0].enabled, status);
5487  double fcdelay, fcwidth; // these are read in us
5488  lvxml.getValue("FC Delay", fcdelay, status);
5489  lvxml.getValue("FC Width", fcwidth, status);
5490  m_crpt->fermi_chopper_delay[0] = (int)(fcdelay * 50.0 + 0.5); // convert to 20 ns bins
5491  m_crpt->fermi_chopper_width[0] = (int)(fcwidth * 50.0 + 0.5);
5492 
5493  lvxml.getValue("TS2 Pulse Veto", m_crpt->vetos[TS2PulseVeto].enabled, status);
5494  lvxml.getValue("ISIS 50Hz Veto", m_crpt->vetos[ISIS50HzVeto].enabled, status);
5495 
5496  readTables(wiring_table.c_str(), detector_table.c_str(), spectra_table.c_str(), status);
5497 
5499 
5500  return status.result();
5501  }
5502 
5503 int ISISinstrumentControl::getMonitoringXML(const std::string& monitor_xml_in, std::string& monitor_xml_out, DAEstatus& status)
5504 {
5505  ICPCritical cs(&m_crpt_cs);
5506  LabviewXML lvxml(status);
5507  char buffer[64];
5508  lvxml.loadFromString(monitor_xml_in.c_str(), status);
5509  if (m_crpt->lvxml_monitoring[0] != '\0')
5510  {
5511  lvxml.updateFromString(m_crpt->lvxml_monitoring, status);
5512  }
5513 
5514  lvxml.setValue("Lower Limit", m_crpt->monitoring.valid_low, status);
5515  lvxml.setValue("Higher Limit", m_crpt->monitoring.valid_high, status);
5516  lvxml.setValue("Calculation Frequency", m_crpt->monitoring.calc_freq, status);
5517  lvxml.setValue("File Logging Frequency", m_crpt->monitoring.log_freq, status);
5518  lvxml.setValue("Enable Monitoring", m_crpt->monitoring.enabled, status);
5519  lvxml.setValue("Enable Alerts", m_crpt->monitoring.alerts, status);
5520  lvxml.setValue("Out of range action", m_crpt->monitoring.action, status);
5521  lvxml.setValue("Specified Period", m_crpt->monitoring.action_period, status);
5522  lvxml.setValue("Expression", m_crpt->monitoring.expression, status);
5523  lvxml.setValue("Load Table From File", m_crpt->monitoring.file, status);
5524  std::vector<std::string> table;
5525  for(int i=0; i<m_crpt->monitoring.n; i++) // table has 3 columns
5526  {
5527  sprintf(buffer, "%d", m_crpt->monitoring.v[i].spectrum);
5528  table.push_back(buffer);
5529  sprintf(buffer, "%f", m_crpt->monitoring.v[i].t_low);
5530  table.push_back(buffer);
5531  sprintf(buffer, "%f", m_crpt->monitoring.v[i].t_high);
5532  table.push_back(buffer);
5533  }
5534  lvxml.setValue("Table", table, status);
5535 
5536  lvxml.saveToString(monitor_xml_out, status);
5537  return status.result();
5538 }
5539 
5540 int ISISinstrumentControl::updateMonitoringXML(const std::string& monitor_xml, DAEstatus& status)
5541 {
5542  int i;
5544  {
5545  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change monitoring configuration in SETUP state");
5546  return status.result();
5547  }
5548  LabviewXML lvxml(status);
5549  if ((monitor_xml.size() == 0) || (lvxml.loadFromString(monitor_xml.c_str(), status) != 0))
5550  {
5551  status.addWarning(FAC_CRPT, "Monitoring XML invalid - ignored");
5552  return status.result();
5553  }
5554  ICPCritical cs(&m_crpt_cs);
5555  strncpy(m_crpt->lvxml_monitoring, monitor_xml.c_str(), sizeof(m_crpt->lvxml_monitoring));
5557  lvxml.getValue("Lower Limit", m_crpt->monitoring.valid_low, status);
5558  lvxml.getValue("Higher Limit", m_crpt->monitoring.valid_high, status);
5559  lvxml.getValue("Calculation Frequency", m_crpt->monitoring.calc_freq, status);
5560  lvxml.getValue("File Logging Frequency", m_crpt->monitoring.log_freq, status);
5561  lvxml.getValue("Enable Monitoring", m_crpt->monitoring.enabled, status);
5562  lvxml.getValue("Enable Alerts", m_crpt->monitoring.alerts, status);
5563  lvxml.getValue("Out of range action", m_crpt->monitoring.action, status);
5564  lvxml.getValue("Specified Period", m_crpt->monitoring.action_period, status);
5565  lvxml.getValue("Expression", m_crpt->monitoring.expression, sizeof(m_crpt->monitoring.expression), true, status);
5566  lvxml.getValue("Load Table From File", m_crpt->monitoring.file, sizeof(m_crpt->monitoring.file), true, status);
5567 #define R_OK 4
5568  if (access(m_crpt->monitoring.file, R_OK) == 0)
5569  {
5570  std::fstream fs; // file has 3 columns
5571  fs.open(m_crpt->monitoring.file, std::ios::in);
5572  for(i=0; fs.good() && i < MAX_MONITORING_PAR; i++)
5573  {
5575  fs >> v[i].spectrum >> v[i].t_low >> v[i].t_high;
5576  }
5577  m_crpt->monitoring.n = i;
5578  status.addInfoVa(FAC_DAE, "Loaded %d monitoring parameters from file %s", m_crpt->monitoring.n, m_crpt->monitoring.file);
5579  }
5580  else
5581  {
5582  std::vector<std::string> table;
5583  m_crpt->monitoring.file[0] = '\0';
5584  lvxml.getValue("Table", table, status);
5585  m_crpt->monitoring.n = std::min<int>(MAX_MONITORING_PAR, table.size() / 3);
5586  for(i=0; i<m_crpt->monitoring.n; i++) // table has 3 columns
5587  {
5589  v[i].spectrum = atoi(table[i*3 + 0].c_str());
5590  v[i].t_low = atof(table[i*3 + 1].c_str());
5591  v[i].t_high = atof(table[i*3 + 2].c_str());
5592  }
5593  status.addInfoVa(FAC_DAE, "Loaded %d monitoring parameters from table", m_crpt->monitoring.n);
5594  }
5595 
5596  return status.result();
5597 }
5598 
5600 {
5601  int64_t value;
5602  ICPCritical cs(&m_crpt_cs);
5603  m_dae->getTotalCounts(&value, status);
5604  counts = value; // in millions
5605  return status.result();
5606 }
5607 
5608 int ISISinstrumentControl::getMEvents(double& mevents, DAEstatus& status)
5609 {
5610  int64_t counts;
5611  getTotalCounts(counts, status);
5612  mevents = (double)counts / 1.0e6;
5613  return status.result();
5614 }
5615 
5616 int ISISinstrumentControl::getMEventsPeriod(double& mevents, int period, DAEstatus& status)
5617 {
5618  long counts = 0, integral, max_val;
5619  for(int i=1; i <= m_crpt->getHighestSpectrumNumber(); ++i)
5620  {
5621  getSpectrumIntegral(i, period, 0.0, -1.0, integral, max_val, status);
5622  counts += integral;
5623  }
5624  mevents = (double)counts / 1.0e6;
5625  return status.result();
5626 }
5627 
5628 int ISISinstrumentControl::sumAllSpectra(long& counts, long& bin0_counts, DAEstatus& status)
5629 {
5630  int len = m_crpt->getPeriodSize() * m_crpt->nper_daq;
5631  int i;
5632  updateCRPTWithDAE(false, status);
5633  counts = 0;
5634  for(i=0; i<len; i++)
5635  {
5636  counts += m_crpt.rawData()[i];
5637  }
5638  bin0_counts = 0;
5639  for(int spec=0; spec <= m_crpt->getHighestSpectrumNumber(); ++spec)
5640  {
5641  for(int per=0; per < m_crpt->nper_daq; ++per)
5642  {
5643  uint32_t offset = m_crpt.spectrumCRPTOffset(spec, per);
5644  bin0_counts += m_crpt.rawData()[offset];
5645  }
5646  }
5647  return status.result();
5648 }
5649 
5651 {
5652  ICPCritical cs(&m_crpt_cs);
5653  counts = m_dae->sumAllHistogramMemory(status);
5654  return status.result();
5655 }
5656 
5658 {
5659  return m_crpt->count_rate;
5660 }
5661 
5663 {
5664  std::stringstream f;
5665  debug_report_arg_t* params = (debug_report_arg_t*)arg;
5666  mess.print(f, true, true); // printing mess to ostream adds time
5667  f << "\r\n";
5668  appendToFileAsync(params->filename.c_str(), f.str().c_str());
5669  return DAEstatus::Success;
5670 }
5671 
5673 {
5674  char time_buffer[128];
5675  debug_report_arg_t* params = (debug_report_arg_t*)arg;
5676  ISOtime(time(NULL), time_buffer, sizeof(time_buffer));
5677  se_log_value_async(params->run_number, "ISISICP", time_buffer, "ICPDEBUG", mess.str().c_str());
5678  return DAEstatus::Success;
5679 }
5680 
5681 std::ostream& ISISinstrumentControl::printStatus(std::ostream& os, DAEstatus& status)
5682 {
5683  os << "ICP status\n";
5684  m_dae->printStatus(os, status);
5685  return os;
5686 }
5687 
5688 int ISISinstrumentControl::VMEWriteValue(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long value, unsigned long mode, DAEstatus& status)
5689 {
5690  int stat;
5691  ICPCritical cs(&m_crpt_cs);
5693  {
5694  stat = m_dae->VMEWriteValue<DAE3CardPolicy>(card_id, card_address, sixteen_bit, value, mode, status);
5695  }
5696  else
5697  {
5698  stat = m_dae->VMEWriteValue<DAE2CardPolicy>(card_id, card_address, sixteen_bit, value, mode, status);
5699  }
5700  return stat;
5701 }
5702 
5703 int ISISinstrumentControl::VMEReadValuesToString(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long num_values, std::string& values, DAEstatus& status)
5704 {
5705  int i, stat = DAEstatus::Failure;
5706  std::ostringstream oss;
5707  ICPCritical cs(&m_crpt_cs);
5708  isisU32_t* data = new isisU32_t[num_values];
5709  for(i=0; i<num_values; i++)
5710  {
5711  stat = VMEReadValue(card_id, card_address + 4*i, sixteen_bit, &(data[i]), status);
5712  oss << Poco::format("0x%08lx = 0x%08lx\n", static_cast<unsigned long>(card_address + 4*i), static_cast<unsigned long>(data[i]));
5713  }
5714  values = oss.str();
5715  delete[] data;
5716  return stat;
5717 }
5718 
5719 int ISISinstrumentControl::VMEReadValue(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long* value, DAEstatus& status)
5720 {
5721  int stat;
5722  ICPCritical cs(&m_crpt_cs);
5724  {
5725  stat = m_dae->VMEReadValue<DAE3CardPolicy>(card_id, card_address, sixteen_bit, value, status);
5726  }
5727  else
5728  {
5729  stat = m_dae->VMEReadValue<DAE2CardPolicy>(card_id, card_address, sixteen_bit, value, status);
5730  }
5731  return stat;
5732 }
5733 
5734 int ISISinstrumentControl::VMEWriteArray(unsigned long card_id, unsigned long card_address, isisU32_t* values, unsigned long num_values, DAEstatus& status)
5735 {
5736  int stat;
5737  ICPCritical cs(&m_crpt_cs);
5738  ICPTimer icp_timer;
5740  {
5741  stat = m_dae->VMEWriteArray<DAE3CardPolicy>(card_id, card_address, values, num_values, status);
5742  }
5743  else
5744  {
5745  stat = m_dae->VMEWriteArray<DAE2CardPolicy>(card_id, card_address, values, num_values, status);
5746  }
5747  icp_timer.info("VMEWriteArray", status);
5748  return stat;
5749 }
5750 
5751 int ISISinstrumentControl::VMEReadArray(unsigned long card_id, unsigned long card_address, isisU32_t* values, unsigned long num_values, DAEstatus& status)
5752 {
5753  int stat;
5754  ICPCritical cs(&m_crpt_cs);
5755  ICPTimer icp_timer;
5757  {
5758  stat = m_dae->VMEReadArray<DAE3CardPolicy>(card_id, card_address, values, num_values, status);
5759  }
5760  else
5761  {
5762  stat = m_dae->VMEReadArray<DAE2CardPolicy>(card_id, card_address, values, num_values, status);
5763  }
5764  icp_timer.info("VMEReadArray", status);
5765  return stat;
5766 }
5767 
5768 int ISISinstrumentControl::exitProgram(const std::string& message, bool prompt)
5769 {
5770  logEvent(m_crpt, "ICP_EXIT", m_status);
5771  if (message.size() > 0)
5772  {
5774  if (prompt)
5775  {
5776  MessageBox(NULL,
5777  message.c_str(),
5778  "ISISICP.EXE", MB_SERVICE_NOTIFICATION | MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
5779  }
5780  }
5781  m_status.reportAll();
5782  exit(EXIT_FAILURE);
5783  return 0; /*NOTREACHED*/
5784 }
5785 
5786 
5787 int ISISinstrumentControl::writeISISNeXus(NeXusWriter& nxwriter, const CRPTProxy& crpt, const char* filename, bool logs_only, const seblock_map_t& blocks, const std::string& events_nxfile, DAEstatus& dstatus)
5788 {
5789 // dstatus.addInfoVa(FAC_DAE, "writeISISNeXus, thread id %u", Poco::Thread::currentTid());
5790  static bool incrementaleventnexus = Poco::Util::Application::instance().config().getBool("isisicp.incrementaleventnexus", false);
5791  static bool incrementaleventnexustest = Poco::Util::Application::instance().config().getBool("isisicp.incrementaleventnexustest", false);
5792  const ISISRAW* iraw = new ISISRAW(const_cast<ISISCRPT_STRUCT*>(crpt.CRPT()), const_cast<isisU32_t*>(crpt.rawData()));
5793  if ( incrementaleventnexus && events_nxfile.size() > 0 && Poco::File(events_nxfile).exists() )
5794  {
5795  if (incrementaleventnexustest)
5796  {
5797  nxwriter.writeISISNeXus(filename, logs_only, crpt.CRPT(), crpt.rawData(), crpt.rawDataSizeMax(), iraw, blocks, m_instrument_xml_file, m_instrument_parameter_map_file, dstatus);
5798  nxwriter.writeISISNeXus((std::string(filename)+".incr").c_str(), logs_only, crpt.CRPT(), crpt.rawData(), crpt.rawDataSizeMax(), iraw, blocks, events_nxfile, m_instrument_xml_file, m_instrument_parameter_map_file, dstatus);
5799  }
5800  else
5801  {
5802  nxwriter.writeISISNeXus(filename, logs_only, crpt.CRPT(), crpt.rawData(), crpt.rawDataSizeMax(), iraw, blocks, events_nxfile, m_instrument_xml_file, m_instrument_parameter_map_file, dstatus);
5803  }
5804  }
5805  else
5806  {
5807  nxwriter.writeISISNeXus(filename, logs_only, crpt.CRPT(), crpt.rawData(), crpt.rawDataSizeMax(), iraw, blocks, m_instrument_xml_file, m_instrument_parameter_map_file, dstatus);
5808  }
5809  delete iraw;
5810  return 0;
5811 }
5812 
5816 {
5817  bool done = false;
5818  while(!done)
5819  {
5820  if ( (WaitForSingleObject(m_async_complete_event, INFINITE) == WAIT_OBJECT_0) &&
5821  (m_num_async_requests == 0) )
5822  {
5823  done = true;
5824  }
5825  }
5826  return 0;
5827 }
5828 
5831 {
5832  InterlockedDecrement(&m_num_async_requests);
5833  SetEvent(m_async_complete_event);
5834  return 0;
5835 }
5836 
5838 {
5839  std::string filename;
5841  const CRPTProxy& crpt;
5843  isisraw_async_t(const CRPTProxy& crpt_, const char* filename_, ISISinstrumentControl* icp_, DAEstatus& status_) :
5844  crpt(crpt_), filename(filename_), icp(icp_), status(status_) {}
5845 };
5846 
5848 {
5849  isisraw_async_t* raw = (isisraw_async_t*)arg;
5850  raw->icp->writeISISRAW(raw->crpt, raw->filename.c_str(), raw->status);
5851  raw->icp->doneAsync();
5852  delete raw;
5853  return 0;
5854 }
5855 
5856 int ISISinstrumentControl::writeISISRAWasync(const CRPTProxy& crpt, const char* filename, DAEstatus& dstatus)
5857 {
5858  isisraw_async_t* arg = new isisraw_async_t(crpt, filename, this, dstatus);
5859  InterlockedIncrement(&m_num_async_requests);
5860  if (QueueUserWorkItem(writeISISRAWthread, arg, WT_EXECUTEDEFAULT) != 0)
5861  {
5862  return DAEstatus::Success;
5863  }
5864  else
5865  {
5866  InterlockedDecrement(&m_num_async_requests);
5867  return DAEstatus::Failure;
5868  }
5869 }
5870 
5871 int ISISinstrumentControl::writeISISRAW(const CRPTProxy& crpt, const char* filename, DAEstatus& dstatus)
5872 {
5873  ICPTimer timer1;
5874 #if 0
5875  writeMuonFile(filename, crpt, dstatus);
5876 #else
5877  const ISISRAW* iraw = new ISISRAW(const_cast<ISISCRPT_STRUCT*>(crpt.CRPT()), const_cast<isisU32_t*>(crpt.rawData()));
5878  remove(filename);
5879  if (const_cast<ISISRAW*>(iraw)->writeToFile(filename) < 0)
5880  {
5881  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Unable to write raw file %s", filename);
5882  }
5883  delete iraw;
5884 #endif
5885  timer1.info("Time to write ISISRAW", dstatus);
5886  return 0;
5887 }
5888 
5889 int ISISinstrumentControl::readISISRAW(const char* filename, DAEstatus& dstatus)
5890 {
5891  ISISRAW* iraw = new ISISRAW(m_crpt.CRPT(), m_crpt.rawData());
5892  FILE* input_file = _fsopen(filename,"r+bN", _SH_DENYWR);
5893  if (input_file != NULL)
5894  {
5895  iraw->ioRAW(input_file, true);
5896  fclose(input_file);
5897  }
5898  else
5899  {
5900  dstatus.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Unable to read raw file %s", filename);
5901  }
5902  delete iraw;
5903  return 0;
5904 }
5905 
5906 
5907 int ISISinstrumentControl::getOptions(std::string& options_xml, DAEstatus& status)
5908 {
5909  if (!m_crpt.isValid())
5910  {
5911  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "CRPT is NULL");
5912  return status.result();
5913  }
5914  ICPCritical cs(&m_crpt_cs);
5915  LabviewXML lvxml(status);
5916  lvxml.loadFromString(options_xml.c_str(), status);
5917 
5918 // lvxml.setValue("Dashboard Update Interval", m_crpt->update_poll_time, status);
5919 
5920 // lvxml.saveToString(options_xml, status);
5921  return status.result();
5922 }
5923 
5924 int ISISinstrumentControl::setOptions(const std::string& options_xml, DAEstatus& status)
5925 {
5926  if (!m_crpt.isValid())
5927  {
5928  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "CRPT is NULL");
5929  return status.result();
5930  }
5931  ICPCritical cs(&m_crpt_cs);
5932 // m_recovery_map["options"] = options_xml;
5933  LabviewXML lvxml(status);
5934  lvxml.loadFromString(options_xml.c_str(), status);
5935 
5936 // lvxml.getValue("Dashboard Update Interval", m_crpt->update_poll_time, status);
5937 
5938  return status.result();
5939 }
5940 
5942 {
5943  if (!m_crpt.isValid())
5944  {
5945  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "CRPT is NULL");
5946  return status.result();
5947  }
5948  ICPCritical cs(&m_crpt_cs);
5949  ICPTimer icp_timer;
5950  updateFunc(0, true);
5951  icp_timer.info("refreshCachedValues", status);
5952  return status.result();
5953 }
5954 
5955 int ISISinstrumentControl::getCharItem(const char* item_name, std::string& cvalue, DAEstatus& status)
5956 {
5957  return m_crpt->getCharItem(item_name, cvalue, status);
5958 }
5959 
5960 int ISISinstrumentControl::getIntItem(const char* item_name, long& lVal, DAEstatus& status)
5961 {
5962  return m_crpt->getIntItem(item_name, lVal, status);
5963 }
5964 
5965 int ISISinstrumentControl::getIntItem(const char* item_name, long* spec_array, int nspec, long* lVal, DAEstatus& status)
5966 {
5967  return m_crpt->getIntItem(item_name, spec_array, nspec, lVal, status);
5968 }
5969 
5970 int ISISinstrumentControl::getRealItem(const char* item_name, double& dblVal, DAEstatus& status)
5971 {
5972  return m_crpt->getRealItem(item_name, dblVal, status);
5973 }
5974 
5975 int ISISinstrumentControl::getRealItem(const char* item_name, long* spec_array, int nspec, double* dblVal, DAEstatus& status)
5976 {
5977  return m_crpt->getRealItem(item_name, spec_array, nspec, dblVal, status);
5978 }
5979 
5980 int ISISinstrumentControl::getIntArrayItemSize(const char* item_name, int* dims_array, int& ndims, DAEstatus& status)
5981 {
5982  return m_crpt->getIntArrayItemSize(item_name, dims_array, ndims, status);
5983 }
5984 
5985 int ISISinstrumentControl::getIntArrayItem(const char* item_name, long* larray, DAEstatus& status)
5986 {
5987  std::string sitem_name = item_name;
5988  int spec_from, spec_to;
5989  if (!strncmp(item_name, "SPECTRUM_", 9))
5990  {
5991  long spectrum_number = atol(sitem_name.substr(9, 1000).c_str());
5992  updateCRPTSpectra(-1, &spectrum_number, 1, status);
5993  }
5994  else if ( !strncmp(item_name, "CNT", 3) && (strlen(item_name) >= 5) && (item_name[4] == '[') ) // e.g. CNT1[53:789]
5995  {
5996  long tr = atol(item_name + 3);
5997  if (parseSpectraRange(sitem_name, spec_from, spec_to) == DAEstatus::Success)
5998  {
5999  updateCRPTSpectra(-1, spec_from, spec_to - spec_from + 1, status);
6000  }
6001  }
6002  else if ( !strncmp(item_name, "CNT", 3) ) // e.g. CNT1
6003  {
6004  long tr = atol(item_name + 3);
6005  long spec_min, spec_max;
6006  getSpectrumNumbersForTimeRegime(tr, spec_min, spec_max, status);
6007  updateCRPTSpectraAllPeriods(spec_min, spec_max - spec_min + 1, status);
6008 // updateCRPTWithDAE(false, status);
6009  }
6010  return m_crpt.getIntArrayItem(item_name, larray, status);
6011 }
6012 
6013 int ISISinstrumentControl::getIntArrayItem(const char* item_name, long* spec_array, int nspec, long* larray, DAEstatus& status)
6014 {
6015  if (!strcmp(item_name, "SPECTRUM"))
6016  {
6017  updateCRPTSpectra(-1, spec_array, nspec, status);
6018  }
6019  else if ( !strncmp(item_name, "CNT", 3) ) // e.g. CNT1
6020  {
6021  long tr = atol(item_name + 3);
6022  long spec_min, spec_max;
6023  getSpectrumNumbersForTimeRegime(tr, spec_min, spec_max, status);
6024  updateCRPTSpectraAllPeriods(spec_min, spec_max - spec_min + 1, status);
6025 // updateCRPTWithDAE(false, status);
6026  }
6027  return m_crpt.getIntArrayItem(item_name, spec_array, nspec, larray, status);
6028 }
6029 
6030 int ISISinstrumentControl::getRealArrayItemSize(const char* item_name, int* dims_array, int& ndims, DAEstatus& status)
6031 {
6032  return m_crpt->getRealArrayItemSize(item_name, dims_array, ndims, status);
6033 }
6034 
6035 int ISISinstrumentControl::getRealArrayItem(const char* item_name, long* spec_array, int nspec, double* darray, DAEstatus& status)
6036 {
6037  if (!strcmp(item_name, "RSPECTRUM") || !strcmp(item_name, "RSPECERR"))
6038  {
6039  updateCRPTSpectra(-1, spec_array, nspec, status);
6040  }
6041  return m_crpt.getRealArrayItem(item_name, spec_array, nspec, darray, status);
6042 }
6043 
6044 int ISISinstrumentControl::getRealArrayItem(const char* item_name, double* darray, DAEstatus& status)
6045 {
6046  std::string sitem_name = item_name;
6047  long spectrum_number, sum;
6048  if (!strncmp(item_name, "RSPECTRUM_", 10))
6049  {
6050  spectrum_number = atol(sitem_name.substr(10, 1000).c_str());
6051  int ntc = m_crpt->spectrumNTC(spectrum_number);
6052  double* time_array = new double[ntc+1];
6053  double* error_array = new double[ntc];
6054  // this is in counts per unit time
6055  getSpectrum(spectrum_number, 0, time_array, darray, error_array,
6056  true, true, sum, status);
6057  delete[] time_array;
6058  delete[] error_array;
6059  return DAEstatus::Success;
6060  }
6061  if (!strncmp(item_name, "RSPECERR_", 9))
6062  {
6063  spectrum_number = atol(sitem_name.substr(9, 1000).c_str());
6064  int ntc = m_crpt->spectrumNTC(spectrum_number);
6065  double* time_array = new double[ntc+1];
6066  double* signal_array = new double[ntc];
6067  // this is in counts per unit time
6068  getSpectrum(spectrum_number, 0, time_array, signal_array, darray,
6069  true, true, sum, status);
6070  delete[] time_array;
6071  delete[] signal_array;
6072  return DAEstatus::Success;
6073  }
6074  return m_crpt.getRealArrayItem(item_name, darray, status);
6075 }
6076 
6077 // if period < 0, assume spectra are absolute
6078 int ISISinstrumentControl::updateCRPTSpectra(int period, long* spectra_list, int nspectra, DAEstatus& status)
6079 {
6080  unsigned long i;
6081  long offset;
6082  ICPCritical cs(&m_crpt_cs);
6083  int len, spec, daq_period;
6084  int perspec = m_crpt->getNumSpectra(true); // number of spectra in a period
6085  if (period < 0)
6086  {
6087  daq_period = 0;
6088  }
6089  else
6090  {
6091  daq_period = getDAQPeriod(period, status);
6092  }
6093  if (daq_period < 0)
6094  {
6095  return DAEstatus::Success; // dwell period - nothing to do
6096  }
6097  for(i=0; i<nspectra; i++)
6098  {
6099  spec = spectra_list[i];
6100  offset = m_crpt.spectrumCRPTOffset(spec, daq_period);
6101  len = m_crpt->spectrumNTC(spec) + 1;
6102  if ( !m_crpt->isEventSpectrum(spec) )
6103  {
6104  m_dae->readDAE1Spectrum(spec + daq_period * perspec, &(m_crpt.rawData()[offset]), len, status);
6105  }
6106  }
6107  return DAEstatus::Success;
6108 }
6109 
6110 // if period < 0, assume spectra are absolute
6111 int ISISinstrumentControl::updateCRPTSpectra(int period, long spec_start, int nspectra, DAEstatus& status)
6112 {
6113  ICPCritical cs(&m_crpt_cs);
6114  int persize = m_crpt->getPeriodSize();
6115  int daq_period;
6116  if (period < 0)
6117  {
6118  daq_period = 0;
6119  }
6120  else
6121  {
6122  daq_period = getDAQPeriod(period, status);
6123  }
6124  if (daq_period < 0)
6125  {
6126  return DAEstatus::Success; // dwell period - nothing to do
6127  }
6128  m_dae->readDAE1Spectra(m_crpt.rawData(), m_crpt.rawDataSizeMax(), m_crpt->spec_to_crpt_offset.data(), spec_start, nspectra, daq_period, persize, status);
6129  return DAEstatus::Success;
6130 }
6131 
6132 int ISISinstrumentControl::updateCRPTSpectraAllPeriods(long spec_start, int nspectra, DAEstatus& status)
6133 {
6134  ICPCritical cs(&m_crpt_cs);
6135  int persize = m_crpt->getPeriodSize();
6136  for(int daq_period=0; daq_period < m_crpt->nper_daq; ++daq_period)
6137  {
6138  m_dae->readDAE1Spectra(m_crpt.rawData(), m_crpt.rawDataSizeMax(), m_crpt->spec_to_crpt_offset.data(), spec_start, nspectra, daq_period, persize, status);
6139  }
6140  return DAEstatus::Success;
6141 }
6142 
6143 int ISISinstrumentControl::notifyICP(long event_id, const char* param, DAEstatus& status)
6144 {
6145  switch(event_id)
6146  {
6147  case UserDetailsChanged:
6148  return updateUserDetailsFromFile(param, status);
6149  break;
6150 
6152  return updateSampleParametersFromFile(param, status);
6153  break;
6154 
6156  return updateBeamlineParametersFromFile(param, status);
6157  break;
6158 
6159  default:
6160  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Unknown event %d", event_id);
6161  return DAEstatus::Failure;
6162  break;
6163  }
6164 }
6165 
6167 {
6168  char sep = '\t';
6169  std::string s1, s2;
6170  std::fstream fs;
6171  fs.open(filename, std::ios::in);
6172  getline(fs, s1); // first line is RB
6173  if (fs.good())
6174  {
6175  m_crpt->rb_number = atol(s1.c_str());
6176  }
6177  else
6178  {
6179  m_crpt->rb_number = 0;
6180  }
6181  for(int i=0; i<1; i++)
6182  {
6183  std::fstream::pos_type pt = fs.tellg();
6184  getline(fs, s1, sep);
6185  getline(fs, s2); // read to end of line
6186  if (fs.fail()) // maybe short line with no tab
6187  {
6188  fs.clear();
6189  fs.seekg(pt);
6190  getline(fs, s1);
6191  s2 = "";
6192  }
6193  if (fs.good())
6194  {
6195  strncpy(m_crpt->user_name, s1.c_str(), sizeof(m_crpt->user_name));
6196  strncpy(m_crpt->institute, s2.c_str(), sizeof(m_crpt->institute));
6197  }
6198  else
6199  {
6200  m_crpt->user_name[0] = '\0';
6201  m_crpt->institute[0] = '\0';
6202  }
6203  }
6204  fs.close();
6205  return DAEstatus::Success;
6206 }
6207 
6209 {
6210  CRPTProxy::parameter_map_t sample_params;
6211  updateParametersFromFile(sample_params, filename, status);
6212  return DAEstatus::Failure;
6213 }
6214 
6216  CRPTProxy::parameter_map_t& param_map, DAEstatus& status)
6217 {
6218  std::pair<CRPTProxy::parameter_map_t::iterator, bool> insert_ret;
6219  param_map.clear();
6220  for(int i=0; i<string_table.size(); i++)
6221  {
6222  if (string_table[i].size() > 3)
6223  {
6224  insert_ret = param_map.insert(CRPTProxy::parameter_map_t::value_type(string_table[i][0],
6225  CRPTProxy::parameter_t(string_table[i][1], string_table[i][2], string_table[i][3])));
6226  }
6227  else
6228  {
6229  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Short string table");
6230  return DAEstatus::Failure;
6231  }
6232  }
6233  return DAEstatus::Success;
6234 }
6235 
6237 {
6238  char sep = '\t';
6239  param_map.clear();
6240  std::string s1, s2, s3, s4;
6241  std::fstream fs;
6242  std::pair<CRPTProxy::parameter_map_t::iterator, bool> insert_ret;
6243  fs.open(filename, std::ios::in);
6244  while(fs.good())
6245  {
6246  std::fstream::pos_type pt;
6247  pt = fs.tellg();
6248  getline(fs, s1, sep);
6249  getline(fs, s2, sep);
6250  getline(fs, s3, sep);
6251  getline(fs, s4);
6252  if (fs.fail()) // maybe a short line missing a sep?
6253  {
6254  fs.clear();
6255  fs.seekg(pt);
6256  getline(fs, s1, sep);
6257  getline(fs, s2, sep);
6258  getline(fs, s3);
6259  s4 = "";
6260  }
6261  if (fs.fail()) // maybe a short line missing a sep?
6262  {
6263  fs.clear();
6264  fs.seekg(pt);
6265  getline(fs, s1, sep);
6266  getline(fs, s2);
6267  s3 = s4 = "";
6268  }
6269  if (fs.fail()) // maybe a short line missing a sep?
6270  {
6271  fs.clear();
6272  fs.seekg(pt);
6273  getline(fs, s1);
6274  s2 = s3 = s4 = "";
6275  }
6276  if (fs.good())
6277  {
6278  insert_ret = param_map.insert(CRPTProxy::parameter_map_t::value_type(s1, CRPTProxy::parameter_t(s2, s3, s4)));
6279  }
6280  }
6281  fs.close();
6282  return DAEstatus::Success;
6283 }
6284 
6286 {
6287  CRPTProxy::parameter_map_t beamline_params;
6288  updateParametersFromFile(beamline_params, filename, status);
6289  return DAEstatus::Failure;
6290 }
6291 
6292 // replace @block@ in string with block actual value from se_blocks
6293 // replace @!block@ in string with block setpoint value from se_blocks
6294 int ISISinstrumentControl::replaceSEparameters(std::string& s, const seblock_map_t* se_blocks, DAEstatus& status)
6295 {
6296  int offset, count = 0;
6297  size_t p1, p2, start;
6298  bool setpoint;
6299  seblock_map_t::const_iterator se_iter;
6300  if (se_blocks == NULL)
6301  {
6302  return DAEstatus::Success;
6303  }
6304  start = 0;
6305  while(count < 20) // this is to stop an infinite loop
6306  {
6307  p1 = s.find("@", start);
6308  if (p1 == std::string::npos)
6309  {
6310  break;
6311  }
6312  if (p1 < s.size() && s[p1+1] == '!')
6313  {
6314  setpoint = true;
6315  offset = 2;
6316  }
6317  else
6318  {
6319  setpoint = false;
6320  offset = 1;
6321  }
6322  p2 = s.find("@", p1 + 1);
6323  if (p2 == std::string::npos)
6324  {
6325  break;
6326  }
6327  std::string block = s.substr(p1 + offset, p2 - p1 - offset);
6328  if ( (se_iter = se_blocks->find(block)) != se_blocks->end() )
6329  {
6330  std::string repstr = "NaN";
6331  if (se_iter->second.is_real)
6332  {
6333  std::stringstream sstr;
6334  if (setpoint && se_iter->second.fsetpoint_value.size() > 0)
6335  {
6336  sstr << se_iter->second.fsetpoint_value[0];
6337  repstr = sstr.str();
6338  }
6339  else if (!setpoint && se_iter->second.fcurrent_value.size() > 0)
6340  {
6341  sstr << se_iter->second.fcurrent_value[0];
6342  repstr = sstr.str();
6343  }
6344  }
6345  else
6346  {
6347  if (setpoint && se_iter->second.setpoint_value.size() > 0)
6348  {
6349  repstr = se_iter->second.setpoint_value[0];
6350  }
6351  else if (!setpoint && se_iter->second.current_value.size() > 0)
6352  {
6353  repstr = se_iter->second.current_value[0];
6354  }
6355  }
6356  s.replace(p1, p2 - p1 + 1, repstr);
6357  start = p1 + repstr.size();
6358  }
6359  else
6360  {
6361 // status.addWarningVa(FAC_DAE, "Unable to find block \"%s\" during @@ beamline/sample parameter substitution", block.c_str());
6362  start = p2 + 1;
6363  }
6364  ++count;
6365  }
6366  return DAEstatus::Success;
6367 }
6368 
6369 int ISISinstrumentControl::setRealParameter(const CRPTProxy::parameter_map_t& params, const seblock_map_t* se_blocks, const char* name,
6370  float& crpt_target, DAEstatus& status)
6371 {
6372  CRPTProxy::parameter_map_t::const_iterator iter;
6373  if ( (iter = params.find(name)) != params.end() )
6374  {
6375  std::string s = iter->second.value;
6376  replaceSEparameters(s, se_blocks, status);
6377  crpt_target = atof(s.c_str());
6378  }
6379  else
6380  {
6381  ; // crpt_target = value_if_not_found;
6382  }
6383  return 0;
6384 }
6385 
6386 int ISISinstrumentControl::setStringParameter(const CRPTProxy::parameter_map_t& params, const seblock_map_t* se_blocks, const char* name, char* crpt_target,
6387  int size_crpt_target, bool null_terminate, DAEstatus& status)
6388 {
6389  CRPTProxy::parameter_map_t::const_iterator iter;
6390  if ( (iter = params.find(name)) != params.end() )
6391  {
6392  std::string s = iter->second.value;
6393  replaceSEparameters(s, se_blocks, status);
6394  strncpy(crpt_target, s.c_str(), size_crpt_target);
6395  }
6396  else
6397  {
6398  ; // strncpy(crpt_target, value_if_not_found, size_crpt_target);
6399  }
6400  if (null_terminate)
6401  {
6402  crpt_target[size_crpt_target-1] = '\0';
6403  }
6404  return 0;
6405 }
6406 
6408 {
6410  CRPTProxy::parameter_map_t::const_iterator it;
6411  seblock_map_t seblocks;
6412  for(it=m_crpt.sampleParameters().begin(); it != m_crpt.sampleParameters().end(); ++it)
6413  {
6414  if (it->second.value.find("@") != std::string::npos)
6415  {
6416  se_get_block_values(seblocks);
6417  break;
6418  }
6419  }
6420  updateSampleParameters(m_crpt.sampleParameters(), m_crpt, &seblocks, status);
6421  return DAEstatus::Success;
6422 }
6423 
6425 {
6426  setStringParameter(sample_parameters, se_blocks, "Run Title", crpt->long_title, sizeof(crpt->long_title), true, status);
6427  setRealParameter(sample_parameters, se_blocks, "Sample Thickness", crpt->sample_thickness, status);
6428  setRealParameter(sample_parameters, se_blocks, "Sample Height", crpt->sample_height, status);
6429  setRealParameter(sample_parameters, se_blocks, "Sample Width", crpt->sample_width, status);
6430  setStringParameter(sample_parameters, se_blocks, "Sample Type", crpt->sample_type, sizeof(crpt->sample_type), true, status);
6431  setStringParameter(sample_parameters, se_blocks, "Sample Geometry", crpt->sample_geometry, sizeof(crpt->sample_geometry), true, status);
6432  setStringParameter(sample_parameters, se_blocks, "Sample Geometry", crpt->sample_orientation, sizeof(crpt->sample_orientation), true, status);
6433  setRealParameter(sample_parameters, se_blocks, "Angle of Incidence", crpt->angle_of_incidence, status);
6434  setRealParameter(sample_parameters, se_blocks, "Sample Phi Angle", crpt->sample_phi_angle, status);
6435 
6436  setStringParameter(sample_parameters, se_blocks, "Sample Name", crpt->sample_name, sizeof(crpt->sample_name), true, status);
6437  setStringParameter(sample_parameters, se_blocks, "Magnetic Field Label", crpt->field_label, sizeof(crpt->field_label), true, status);
6438  setStringParameter(sample_parameters, se_blocks, "Temperature Label", crpt->temperature_label, sizeof(crpt->temperature_label), true, status);
6439  setStringParameter(sample_parameters, se_blocks, "Comments", crpt->comment, sizeof(crpt->comment), true, status);
6440  setStringParameter(sample_parameters, se_blocks, "Script Name", crpt->script_name, sizeof(crpt->script_name), true, status);
6441 
6442  setStringParameter(sample_parameters, se_blocks, "Measurement ID", crpt->measurement_id, sizeof(crpt->measurement_id), true, status);
6443  setStringParameter(sample_parameters, se_blocks, "Measurement SubID", crpt->measurement_subid, sizeof(crpt->measurement_subid), true, status);
6444  setStringParameter(sample_parameters, se_blocks, "Measurement Type", crpt->measurement_type, sizeof(crpt->measurement_type), true, status);
6445  setStringParameter(sample_parameters, se_blocks, "Sample ID", crpt->sample_id, sizeof(crpt->sample_id), true, status);
6446 
6447  // we do not get "Measurement Label" as it is a derived quantity from Measuremtnt ID
6448 
6449  return DAEstatus::Success;
6450 }
6451 
6452 
6454 {
6456  CRPTProxy::parameter_map_t::const_iterator it;
6457  seblock_map_t seblocks;
6458  for(it=m_crpt.beamlineParameters().begin(); it != m_crpt.beamlineParameters().end(); ++it)
6459  {
6460  if (it->second.value.find("@") != std::string::npos)
6461  {
6462  se_get_block_values(seblocks);
6463  break;
6464  }
6465  }
6467  return DAEstatus::Success;
6468 }
6469 
6471 {
6472  setRealParameter(beamline_parameters, se_blocks, "FOE Mirror Angle", crpt->foe_mirror_angle, status);
6473  setRealParameter(beamline_parameters, se_blocks, "Beam Centre X", crpt->beam_centre_x, status);
6474  setRealParameter(beamline_parameters, se_blocks, "Beam Centre Y", crpt->beam_centre_y, status);
6475  setRealParameter(beamline_parameters, se_blocks, "Chopper Opening Angle", crpt->chopper_opening_angle, status);
6476  setRealParameter(beamline_parameters, se_blocks, "Aperture 1 Diameter", crpt->aperture1, status);
6477  setRealParameter(beamline_parameters, se_blocks, "Aperture 2 Diameter", crpt->aperture2, status);
6478 // setRealParameter(beamline_parameters, se_blocks, "Aperture 3 Diameter", crpt->aperture2, status);
6479  setStringParameter(beamline_parameters, se_blocks, "Beamstop Position", crpt->beamstop_position, sizeof(crpt->beamstop_position), true, status);
6480  setRealParameter(beamline_parameters, se_blocks, "Primary Flight Path (L1)", crpt->i_l1, status);
6481  setRealParameter(beamline_parameters, se_blocks, "Sample Detector Distance", crpt->sdd, status);
6482  setStringParameter(beamline_parameters, se_blocks, "Instrument Geometry", crpt->instrument_geometry, sizeof(crpt->instrument_geometry), true, status);
6483  setStringParameter(beamline_parameters, se_blocks, "Journal Blocks", crpt->journal_blocks, sizeof(crpt->journal_blocks), true, status);
6484  return DAEstatus::Success;
6485 }
6486 
6488 {
6489  return DAEstatus::Success;
6490 }
6491 
6493 {
6494  int nuser = 0, k;
6495  std::string user_names, last_user, user_tmp;
6496  m_crpt->rb_number = rbno;
6497  m_crpt->user_name[0] = '\0';
6498  m_crpt->institute[0] = '\0';
6499  m_crpt->local_contact[0] = '\0';
6500  for(int i=0; i<table.size(); i++)
6501  {
6502  if (table[i].size() > 0)
6503  {
6504  last_user = table[i][0];
6505  k = last_user.find(' ');
6506  if (k != last_user.npos)
6507  {
6508  user_tmp = last_user.substr(0, k);
6509  }
6510  else
6511  {
6512  user_tmp = last_user;
6513  }
6514  if (nuser == 0)
6515  {
6516  user_names = user_tmp;
6517  }
6518  else
6519  {
6520  user_names = user_names + "," + user_tmp;
6521  }
6522  strncpy(m_crpt->user_name, user_names.c_str(), sizeof(m_crpt->user_name));
6523  m_crpt->institute[0] = '\0';
6524  nuser++;
6525  }
6526  if (table[i].size() > 1)
6527  {
6528  strncpy(m_crpt->institute, table[i][1].c_str(), sizeof(m_crpt->institute));
6529  }
6530  if ( table[i].size() > 2 ) // Role is blank, "PI" or "Contact"
6531  {
6532  std::string role = table[i][2];
6533  std::transform(role.begin(), role.end(), role.begin(), tolower);
6534  if (role.find("contact") != role.npos)
6535  {
6536  strncpy(m_crpt->local_contact, last_user.c_str(), sizeof(m_crpt->local_contact));
6537  }
6538  }
6539  }
6540  if (nuser == 1) // for one user name, do not strip off initials
6541  {
6542  strncpy(m_crpt->user_name, last_user.c_str(), sizeof(m_crpt->user_name));
6543  }
6544  if (nuser > 1)
6545  {
6546  m_crpt->institute[0] = '\0';
6547  }
6551  return DAEstatus::Success;
6552 }
6553 
6554 // VMS compatible journal entry
6556 {
6557  char inst_abrv[3];
6558  char run_number[5];
6559  char user_name[20];
6560  char title[24];
6561  char date[20];
6562  char uamps[8];
6563 };
6564 
6565 // VMS compatible summary entry
6567 {
6569  char rb[8];
6570 };
6571 
6572 static const char* STR0(const char* str, const char* value = "UNSPECIFIED")
6573 {
6574  if (str == NULL || str[0] == '\0')
6575  {
6576  return value;
6577  }
6578  else
6579  {
6580  return str;
6581  }
6582 }
6583 
6584 class XMLJournalHandler : public Poco::XML::ContentHandler
6585 {
6589 public:
6590  XMLJournalHandler(int& first_run, int& last_run) : Poco::XML::ContentHandler(), m_first_run(first_run), m_last_run(last_run) { }
6591  void setDocumentLocator(const Poco::XML::Locator* loc) { }
6593  {
6594  m_first_run = m_last_run = 0;
6595  in_run_number = false;
6596  }
6597 
6598  void endDocument() { }
6599 
6600  void startElement(const Poco::XML::XMLString& uri, const Poco::XML::XMLString& localName, const Poco::XML::XMLString& qname,
6601  const Poco::XML::Attributes& attrList)
6602  {
6603  if (localName == "run_number")
6604  {
6605  in_run_number = true;
6606  }
6607  }
6608 
6609  void endElement(const Poco::XML::XMLString& uri, const Poco::XML::XMLString& localName, const Poco::XML::XMLString& qname)
6610  {
6611  if (localName == "run_number")
6612  {
6613  in_run_number = false;
6614  }
6615  }
6616 
6617  void characters(const Poco::XML::XMLChar ch[], int start, int length)
6618  {
6619  int run_number;
6620  if (in_run_number)
6621  {
6622  // we seem to get called multiple times, sometimes for bits of whitespace,
6623  // but just checking for number > 0 seems to work OK as space -> 0
6624  run_number = atoi(std::string(ch+start, length).c_str());
6625  if (run_number > 0)
6626  {
6627  m_last_run = run_number;
6628  if (m_first_run == 0)
6629  {
6630  m_first_run = m_last_run;
6631  }
6632  }
6633  }
6634  }
6635 
6636  void ignorableWhitespace(const Poco::XML::XMLChar ch[], int start, int length) { }
6637 
6638  void processingInstruction(const Poco::XML::XMLString& target, const Poco::XML::XMLString& data) { }
6639 
6640  void startPrefixMapping(const Poco::XML::XMLString& prefix, const Poco::XML::XMLString& uri) { }
6641 
6642  void endPrefixMapping(const Poco::XML::XMLString& prefix) { }
6643 
6644  void skippedEntity(const Poco::XML::XMLString& name) { }
6645 
6646 };
6647 
6649 {
6650  char c, buffer[80];
6651  int i;
6652  vms_journal_line jl;
6653  vms_summary_line sl;
6654  // journal line
6655  memset(&jl, ' ', sizeof(jl));
6656  spacePadCopy(jl.inst_abrv, crpt->inst_abrv, sizeof(jl.inst_abrv));
6657  // for VMS compatibility wrap run number at 99999
6658  spacePadCopyVa(jl.run_number, sizeof(jl.run_number), "%0*d", sizeof(jl.run_number), crpt->run_number % VMS_RUN_MASK);
6659  spacePadCopy(jl.user_name, crpt->user_name, sizeof(jl.user_name));
6660  spacePadCopy(jl.title, crpt->long_title, sizeof(jl.title));
6661  ISISRAW::vmstime(buffer, sizeof(buffer), crpt->start_time);
6662  spacePadCopy(jl.date, buffer, sizeof(jl.date));
6663  spacePadCopyVa(jl.uamps, sizeof(jl.uamps), "%*.1f", sizeof(jl.uamps), crpt->good_uamph);
6664  // summary line
6665  memset(&sl, ' ', sizeof(sl));
6666  memcpy(&(sl.jl), &jl, sizeof(sl.jl));
6667  spacePadCopyVa(sl.rb, sizeof(sl.rb), "%*d", sizeof(sl.rb), crpt->rb_number);
6668 
6669  std::fstream fsj;
6670  fsj.open(m_data_dir+"\\journal.txt", std::ios::app);
6671  if (fsj.good())
6672  {
6673  for(i=0; i<sizeof(jl); i++)
6674  {
6675  c = ((const char*)&jl)[i];
6676  if (isspace(c)) // change tabs, newlines etc to a single space
6677  {
6678  c = ' ';
6679  }
6680  fsj << c;
6681  }
6682  fsj << std::endl;
6683  fsj.close();
6684  }
6685  else
6686  {
6687  status.addWarning(FAC_CRPT, "Error appending to journal file");
6688  }
6689  std::fstream fss;
6690  fss.open(m_data_dir+"\\summary.txt", std::ios::app);
6691  if (fss.good())
6692  {
6693  for(i=0; i<sizeof(sl); i++)
6694  {
6695  c = ((const char*)&sl)[i];
6696  if (isspace(c)) // change tabs, newlines etc to a single space
6697  {
6698  c = ' ';
6699  }
6700  fss << c;
6701  }
6702  fss << std::endl;
6703  fss.close();
6704  }
6705  else
6706  {
6707  status.addWarning(FAC_CRPT, "Error appending to summary file");
6708  }
6709  // new XML version
6710  int nx_mode;
6711  std::stringstream file_buffer;
6712  file_buffer << m_data_dir << "\\journal";
6714  {
6715  file_buffer << "_" << crpt->isis_cycle;
6716  }
6717  file_buffer << ".xml";
6718  std::string file = file_buffer.str();
6719  if (access(file.c_str(), 0) == 0)
6720  {
6721  nx_mode = NXACC_RDWR;
6722  }
6723  else
6724  {
6725  nx_mode = NXACC_CREATEXML;
6726  }
6727  long first_run_number;
6728  if (se_get_measurement_first_run(crpt->measurement_id, first_run_number) != 0)
6729  {
6730  first_run_number = 0;
6731  }
6732  std::string measurement_label;
6733  if (se_get_measurement_label(crpt->measurement_id, measurement_label) != 0)
6734  {
6735  measurement_label = "";
6736  }
6737  std::vector<std::string> jblock_list;
6738  char* tmp_blocks = strdup(crpt->journal_blocks);
6739  const char* block = strtok(tmp_blocks, " \t,:;");
6740  while(block != NULL)
6741  {
6742  jblock_list.push_back(block);
6743  block = strtok(NULL, " \t,:;");
6744  }
6745  free(tmp_blocks);
6746  using namespace NeXus;
6747  using namespace NeXus::Stream;
6748  std::string seci_config;
6749  std::stringstream entry_name;
6750  se_get_seci_config(seci_config);
6751  sprintf(buffer, "%08d", crpt->run_number);
6752  entry_name << crpt->inst_name << buffer;
6753  std::string temp_file = m_data_dir + "\\journal_tmp.xml";
6754  try
6755  {
6756  if (nx_mode == NXACC_RDWR) // existing file
6757  {
6758  file = temp_file;
6759  nx_mode = NXACC_CREATEXML;
6760  }
6761  File journal(file, nx_mode);
6762  // fix schema version number to 3.0
6763  journal.putAttr("xmlns", "http://definition.nexusformat.org/schema/3.0");
6764  journal.putAttr("xsi:schemaLocation", "http://definition.nexusformat.org/schema/3.0");
6765  journal.makeGroup(entry_name.str(), "NXentry", true);
6766  // think it is more accurate to use convertWindows1252ToUTF8() rather than convertLatin1ToUTF8()
6767  journal.writeData("title", convertWindows1252ToUTF8(STR0(crpt->long_title)));
6768  journal.writeData("user_name", convertWindows1252ToUTF8(STR0(crpt->user_name)));
6769  journal.writeData("local_contact", convertWindows1252ToUTF8(STR0(crpt->local_contact)));
6770  journal.writeData("user_institute", convertWindows1252ToUTF8(STR0(crpt->institute)));
6771  sprintf(buffer, "%d", crpt->rb_number);
6772  journal.writeData("experiment_identifier", STR0(buffer));
6773  journal.writeData("instrument_name", STR0(crpt->inst_name));
6774  journal.writeData("run_number", crpt->run_number);
6775  journal.writeData("sample_id", STR0(crpt->sample_id));
6776  journal.writeData("measurement_first_run", (int)first_run_number);
6777  journal.writeData("measurement_id", STR0(crpt->measurement_id));
6778  journal.writeData("measurement_label", STR0(measurement_label.c_str()));
6779  journal.writeData("measurement_type", STR0(crpt->measurement_type));
6780  journal.writeData("measurement_subid", STR0(crpt->measurement_subid));
6781  ISOtime(crpt->start_time, buffer, sizeof(buffer));
6782  journal.writeData("start_time", buffer);
6783  ISOtime(crpt->stop_time, buffer, sizeof(buffer));
6784  journal.writeData("end_time", buffer);
6785  journal.writeData("duration", crpt->duration);
6786  journal.writeData("proton_charge", crpt->good_uamph);
6787  journal.writeData("raw_frames", crpt->total_frames);
6788  journal.writeData("good_frames", crpt->good_frames);
6789  journal.writeData("number_periods", crpt->nper);
6790  journal.writeData("number_spectra", crpt->getNumSpectra());
6791  journal.writeData("number_detectors", crpt->ndet);
6792  journal.writeData("number_time_regimes", crpt->ntrg);
6793  journal.writeData("frame_sync", FrameSyncNames[crpt->tcb_sync]);
6794  for(i=0; i<crpt->ntrg; i++)
6795  {
6796  const TCBRANGE* tcr = crpt->tcr[i];
6797  int ntcr = crpt->ntcr[i];
6798  sprintf(buffer, "time_regime_%d", i+1);
6799  journal.makeGroup(buffer, "IXtime_regime", true);
6800  journal.writeData("number_time_channels", crpt->ntc[i]); // all same at moment
6801 // if (tcr[0].mode == TCBRANGE_FILE)
6802  journal.writeData("time_channel_min", tcr[0].start);
6803  journal.writeData("time_channel_max", tcr[ntcr-1].end);
6804  journal.closeGroup();
6805  }
6806  journal.writeData("icp_version", STR0(crpt->icp_version));
6807  journal.writeData("detector_table_file", STR0(crpt->detector_table.fname));
6808  journal.writeData("spectra_table_file", STR0(crpt->spectra_table.fname));
6809  journal.writeData("wiring_table_file", STR0(crpt->wiring_table.fname));
6810  journal.writeData("monitor_spectrum", crpt->monitor_spectrum);
6811  journal.writeData("monitor_sum", crpt->monitor_sum[0]);
6812  journal.writeData("total_mevents", (float)crpt->update_total_counts / (float)1e6);
6813  journal.writeData("comment", STR0(crpt->comment));
6814  journal.writeData("field_label", STR0(crpt->field_label));
6815  journal.writeData("instrument_geometry", STR0(crpt->instrument_geometry));
6816  journal.writeData("script_name", STR0(crpt->script_name));
6817  journal.writeData("sample_name", STR0(crpt->sample_name));
6818  journal.writeData("sample_orientation", STR0(crpt->sample_orientation));
6819  journal.writeData("temperature_label", STR0(crpt->temperature_label));
6820  journal.writeData("npratio_average", crpt->update_npratio_average);
6821  journal.writeData("isis_cycle", STR0(crpt->isis_cycle));
6822  journal.writeData("seci_config", STR0(seci_config.c_str()));
6823  journal.writeData("event_mode", crpt->eventModeCardFraction());
6824  journal.makeGroup("selog", "IXselog", true);
6825  for(std::vector<std::string>::const_iterator it = jblock_list.begin(); it != jblock_list.end(); ++it)
6826  {
6827  seblock_map_t::const_iterator itb;
6828  if ( (Poco::trim(*it)).size() == 0 )
6829  {
6830  continue;
6831  }
6832  journal.makeGroup(*it, "IXseblock", true);
6833  if ( (itb = blocks.find(*it)) != blocks.end() )
6834  {
6835  const SEBLOCK& block = itb->second;
6836  if (block.is_real)
6837  {
6838  if (block.fcurrent_value.size() > 0)
6839  {
6840  journal.writeData("current_value", block.fcurrent_value[0]); // for all periods?
6841  journal.writeData("current_spread", block.fcurrent_spread[0]); // for all periods?
6842  }
6843  else
6844  {
6845  journal.writeData("current_value", "NaN"); // for all periods?
6846  }
6847  if (block.fsetpoint_value.size() > 0)
6848  {
6849  journal.writeData("setpoint_value", block.fsetpoint_value[0]); // for all periods?
6850  journal.writeData("setpoint_spread", block.fsetpoint_spread[0]); // for all periods?
6851  }
6852  else
6853  {
6854  journal.writeData("setpoint_value", "NaN"); // for all periods?
6855  }
6856 // journal.writeData("average_value", block.faverage_value[0]); // for all periods?
6857  journal.writeData("average_value", "NaN"); // for all periods?
6858  }
6859  else
6860  {
6861  if (block.current_value.size() > 0)
6862  {
6863  journal.writeData("current_value", STR0(block.current_value[0].c_str())); // for all periods?
6864  }
6865  else
6866  {
6867  journal.writeData("current_value", "UNKNOWN"); // for all periods?
6868  }
6869  if (block.setpoint_value.size() > 0)
6870  {
6871  journal.writeData("setpoint_value", STR0(block.setpoint_value[0].c_str())); // for all periods?
6872  }
6873  else
6874  {
6875  journal.writeData("setpoint_value", "UNKNOWN"); // for all periods?
6876  }
6877  journal.writeData("average_value", "NaN"); // for all periods?
6878  }
6879  }
6880  else
6881  {
6882  journal.writeData("current_value", "NaN"); // for all periods?
6883  journal.writeData("setpoint_value", "NaN"); // for all periods?
6884  journal.writeData("average_value", "NaN"); // for all periods?
6885  }
6886  journal.closeGroup();
6887  }
6888  journal.closeGroup();
6889  journal.closeGroup();
6890  journal.close();
6891  if (file == temp_file)
6892  {
6893  std::fstream journal_full;
6894  journal_full.open(file.c_str(), std::ios::in);
6895  char big_buffer[10000];
6896  journal_full.getline(big_buffer, sizeof(big_buffer), '\0');
6897  journal_full.close();
6898  remove(temp_file.c_str());
6899  std::string xml_entry = big_buffer;
6900  HANDLE h = CreateFile(file_buffer.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
6901  defaultNoInheritHandles(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
6902  if (h != INVALID_HANDLE_VALUE)
6903  {
6904  LARGE_INTEGER li;
6905  li.QuadPart = -20;
6906  SetFilePointerEx(h, li, NULL, FILE_END);
6907  DWORD nread;
6908  ReadFile(h, buffer, 20, &nread, NULL);
6909  buffer[nread] = '\0';
6910  const char* pos = strstr(buffer, "</NXroot>");
6911  if (pos != NULL)
6912  {
6913  int offset = (nread - (pos - buffer));
6914  li.QuadPart = -offset;
6915  SetFilePointerEx(h, li, NULL, FILE_END);
6916  int spos = xml_entry.find("<NXentry");
6917  if (spos != std::string::npos)
6918  {
6919  std::string spos_str = xml_entry.substr(spos);
6920  DWORD nwrite;
6921  if ( (WriteFile(h, spos_str.c_str(), spos_str.size(), &nwrite, NULL) == 0) ||
6922  (nwrite != spos_str.size()) )
6923  {
6924  status.addWarning(FAC_CRPT, "WriteFile error with xml journal");
6925  }
6926  }
6927  }
6928  CloseHandle(h);
6929  }
6931  }
6932  }
6933  catch(const std::exception& ex)
6934  {
6935  status.addWarningVa(FAC_CRPT, "Error appending to XML journal %s", ex.what());
6936  }
6937  std::vector<std::string> journal_list;
6938  std::string journal_main = m_data_dir + "\\journal_main.xml";
6939  SetFileAttributes(journal_main.c_str(), FILE_ATTRIBUTE_NORMAL);
6940  remove(journal_main.c_str());
6941  findFiles(m_data_dir.c_str(), "journal*.xml", journal_list, false);
6942  std::ofstream jmain;
6943  try
6944  {
6945  jmain.open(journal_main);
6946  jmain << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << std::endl;
6947  jmain << "<?xml-stylesheet type=\"text/xsl\" href=\"journal.xsl\" ?>" << std::endl;
6948  jmain << "<!-- DO NOT EDIT - recreated automatically by ICP at each END of run -->" << std::endl;
6949  jmain << "<journal>" << std::endl;
6950  Poco::XML::SAXParser parser;
6951  int first_run, last_run;
6952  XMLJournalHandler journal_handler(first_run, last_run);
6953  parser.setContentHandler(&journal_handler);
6954  for(std::vector<std::string>::const_iterator it = journal_list.begin(); it != journal_list.end(); ++it)
6955  {
6956  try
6957  {
6958  parser.parse(m_data_dir + "\\" + *it);
6959  }
6960  catch(const std::exception& ex)
6961  {
6962  status.addWarningVa(FAC_CRPT, "Error SAX parsing XML journal file \"%s\" : %s", it->c_str(), ex.what());
6963  first_run = last_run = 0;
6964  }
6965  jmain << " <file name=\"" << *it << "\" first_run=\"" << first_run << "\" last_run=\"" << last_run << "\" />" << std::endl;
6966  }
6967  jmain << "</journal>" << std::endl;
6968  jmain.close();
6969  SetFileAttributes(journal_main.c_str(), FILE_ATTRIBUTE_READONLY);
6970  }
6971  catch(const std::exception& ex)
6972  {
6973  status.addWarningVa(FAC_CRPT, "Error creating journal_main.xml %s", ex.what());
6974  }
6975  return DAEstatus::Success;
6976 }
6977 
6981 {
6984 }
6985 
6987 {
6988  m_crpt_run->zeroUsedRawData(m_status);
6989  m_crpt_run->rawDataUpdated();
6990 }
6991 
6992 //void ISISinstrumentControl::zeroCRPTRawData(void* arg)
6993 //{
6994 // ISISinstrumentControl* ic = (ISISinstrumentControl*)arg;
6995 // ic->zeroCRPTRawData();
6996 //}
6997 
6998 
6999 int ISISinstrumentControl::getNPRatio(float* current, float* average, DAEstatus& status)
7000 {
7001  *current = m_crpt->update_npratio_current;
7002  *average = m_crpt->update_npratio_average;
7003  return 0;
7004 }
7005 
7007 {
7008  int i;
7010  {
7011  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Can only change DAE in SETUP state");
7012  return status.result();
7013  }
7015  {
7016  status.add(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Not using software periods");
7017  return status.result();
7018  }
7019  ICPCritical cs(&m_crpt_cs);
7020  unsigned permax = m_crpt->getPeriodSize();
7021  unsigned len = permax * nperiod;
7022  if ( len > m_crpt.rawDataSizeMax() )
7023  {
7024  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "Not enough CRPT memory for requested %d periods", nperiod);
7025  return DAEstatus::Failure;
7026  }
7027  if ( nperiod >= ISISCRPT_MAX_PERIOD )
7028  {
7029  status.addVa(FAC_CRPT, SEV_ERROR, ERRTYPE_OUTOFMEM, "%d periods too large - only %d allowed by ICP", nperiod, ISISCRPT_MAX_PERIOD);
7030  return DAEstatus::Failure;
7031  }
7032  if (nperiod > 0)
7033  {
7034  m_crpt->nper = nperiod;
7035  }
7036  else
7037  {
7038  m_crpt->nper = 1;
7039  }
7040  for(i=0; i<m_crpt->nper; i++)
7041  {
7042  m_crpt->period[i].type = 1; // all DAQ periods
7043  m_crpt->period[i].daq_period = i; // all DAQ periods
7044  sprintf(m_crpt->period[i].label, "Period %d", i+1);
7045  }
7046  m_crpt->nper_daq = m_crpt->nper;
7048  return status.result();
7049 }
7050 
7051 int ISISinstrumentControl::fillWithTestPattern(unsigned long pattern, DAEstatus& status)
7052 {
7053  ICPCritical cs(&m_crpt_cs);
7054  m_dae->fillWithTestPattern(pattern, status);
7055  return status.result();
7056 }
7057 
7058 int ISISinstrumentControl::checkTestPattern(unsigned long pattern, DAEstatus& status)
7059 {
7060  ICPCritical cs(&m_crpt_cs);
7061 // m_dae->checkTestPattern(pattern, status);
7062  m_dae->checkTestPatternAsync(pattern, status);
7063  return status.result();
7064 }
7065 
7066 
7067 int ISISinstrumentControl::getVetoStatus(std::string& veto_text, DAEstatus& status)
7068 {
7069  ICPCritical cs(&m_crpt_cs);
7070  m_dae->getVetoStatus(veto_text, status);
7071  return status.result();
7072 }
7073 
7074 int ISISinstrumentControl::whichVeto(std::string& veto_text, DAEstatus& status)
7075 {
7076  ICPCritical cs(&m_crpt_cs);
7077  m_dae->whichVeto(veto_text, status);
7078  return status.result();
7079 }
7080 
7081 
7082 int ISISinstrumentControl::loadDAEWithNeXusData(const std::string& file_name, long options, DAEstatus& status)
7083 {
7084  Poco::SharedPtr<NeXus::File> nx_file;
7085  std::vector<int32_t> int32_vec;
7086  float good_uah;
7087  int good_frames;
7088  NeXus::Info info;
7090  {
7091  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Must be in PAUSED state to load data");
7092  return DAEstatus::Failure;
7093  }
7094  try
7095  {
7096  nx_file = new NeXus::File(file_name, NXACC_READ);
7097  nx_file->openPath("/entry/data");
7098  info = nx_file->getInfo();
7099  nx_file->getData(int32_vec);
7100  nx_file->openPath("/entry/good_frames");
7101  nx_file->getData(&good_frames);
7102  nx_file->openPath("/entry/proton_charge");
7103  nx_file->getData(&good_uah);
7104  nx_file->close();
7105  }
7106  catch(const std::exception& ex)
7107  {
7108  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "loadDAEWithNeXusData: %s", ex.what());
7109  return DAEstatus::Failure;
7110  }
7111  int period_offset;
7112  if ( info.dims.size() == 2 )
7113  {
7114  period_offset = 0;
7115  if ( 1 != m_crpt->nper )
7116  {
7117  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Number of periods mismatch 1 != %d", m_crpt->nper);
7118  return DAEstatus::Failure;
7119  }
7120  }
7121  else if ( info.dims.size() == 3 )
7122  {
7123  period_offset = 1;
7124  if ( info.dims[0] != m_crpt->nper )
7125  {
7126  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Number of periods mismatch %d != %d", info.dims[0], m_crpt->nper);
7127  return DAEstatus::Failure;
7128  }
7129  }
7130  else
7131  {
7132  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Array dimensionality mismatch in loaded data: must be 2 or 3 dimensional, not %d", info.dims.size());
7133  return DAEstatus::Failure;
7134  }
7135  if ( info.dims[0+period_offset] != m_crpt->nsp[0] )
7136  {
7137  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Number of spectra mismatch in loaded data: %d != %d", info.dims[0+period_offset], m_crpt->nsp[0]);
7138  return DAEstatus::Failure;
7139  }
7140  if ( info.dims[1+period_offset] != m_crpt->ntc[0] )
7141  {
7142  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Number of time channels mismatch in loaded data: %d != %d", info.dims[1+period_offset], m_crpt->ntc[0]);
7143  return DAEstatus::Failure;
7144  }
7145  int i, j, ndet, card, modn, mpos, nper, spec, spec_len, maxspec, maxcardspec;
7146  std::ostringstream oss;
7147  int maxmod = 16, maxpos = 4096, maxcrate = 16;
7148  ICPCritical cs(&m_crpt_cs);
7149  isisU32_t* new_poslut = new isisU32_t[maxcrate * maxmod * maxpos];
7150  int* last_card_spectrum = new int[maxcrate];
7151  memset(new_poslut, 0, maxcrate * maxmod * maxpos * sizeof(isisU32_t));
7152  memset(last_card_spectrum, 0, maxcrate * sizeof(int));
7153  spec_len = m_crpt->ntc[0] + 1; // +1 for time bin 0
7154  ndet = m_crpt->ndet;
7155  nper = m_crpt->nper;
7156  maxspec = m_crpt->nsp[0] + 1; // +1 for spectrum 0
7157  int* spec_lookup = new int[maxspec];
7158  memset(spec_lookup, 0, maxspec * sizeof(int));
7159  for(i=0; i < ndet; i++)
7160  {
7161  card = m_crpt->crat[i];
7162  modn = m_crpt->modn[i];
7163  mpos = m_crpt->mpos[i];
7164  spec = m_crpt->spec[i];
7165  if (card >= maxcrate)
7166  {
7167  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many crates");
7168  return DAEstatus::Failure;
7169  }
7170  if (spec > 0)
7171  {
7172  j = card * (maxmod * maxpos) + modn * (maxpos) + mpos;
7173  if (spec_lookup[spec] != 0)
7174  {
7175  new_poslut[j] = spec_lookup[spec];
7176  }
7177  else
7178  {
7179  new_poslut[j] = ++(last_card_spectrum[card]);
7180  spec_lookup[spec] = last_card_spectrum[card];
7181  }
7182  }
7183  }
7184  for(i=0; i < ndet; i++)
7185  {
7186  card = m_crpt->crat[i];
7187  spec = m_crpt->spec[i];
7188  if (spec > 0)
7189  {
7190  maxcardspec = last_card_spectrum[card] + 1;
7191  for(j=0; j<nper; j++)
7192  {
7193  // dae spectra are ntc+1, and there is also spectrum 0, so need to allow for this (compare with raw file code below)
7194  int array_offset = ((spec - 1) + (maxspec - 1) * j) * (spec_len - 1);
7195  m_dae->writeHistogramMemory(card, reinterpret_cast<isisU32_t*>(&(int32_vec[array_offset])),
7196  (spec_lookup[spec] + maxcardspec * j) * spec_len * 4 + 1, // + 1 to start writing after time bin 0
7197  spec_len - 1, status);
7198  }
7199  }
7200  }
7201  oss << "Loaded " << m_crpt->nsp[0] << " spectra, " << m_crpt->ntc[0] << " time channels, " << m_crpt->nper << " period(s)" << std::endl;
7202  for(i=0; i<maxcrate; i++)
7203  {
7204  if (last_card_spectrum[i] > 0)
7205  {
7206  oss << "Writing " << last_card_spectrum[i] << " spectra to detector card " << i << std::endl;
7207  m_dae->writePOSLUTMemory(i, &(new_poslut[i * (maxmod * maxpos)]), maxmod * maxpos, status);
7208  }
7209  }
7210  m_crpt->good_frames = m_crpt->total_frames = good_frames;
7211  m_crpt->good_uamph = m_crpt->total_uamph = good_uah;
7212  oss << "Set good_frames=" << good_frames << " and proton_charge=" << good_uah << std::endl;
7213  delete []new_poslut;
7214  delete []last_card_spectrum;
7215  delete []spec_lookup;
7216  status.addInfo(FAC_DAE, oss.str());
7217  return status.result();
7218 }
7219 
7221 int ISISinstrumentControl::loadDAEWithData(const std::string& file_name, long options, DAEstatus& status)
7222 {
7223  return loadDAEWithNeXusData(file_name, options, status);
7224 
7225  int i, j, ndet, card, modn, mpos, nper, spec, spec_len, maxspec, maxcardspec;
7226  std::ostringstream oss;
7227  int maxmod = 16, maxpos = 4096, maxcrate = 16;
7228  ISISRAW *ir = new ISISRAW;
7229  ir->readFromFile(file_name.c_str());
7230  ir->printInfo(oss);
7231  if (ir->t_nsp1 != m_crpt->nsp[0] ||
7232  ir->t_ntc1 != m_crpt->ntc[0] ||
7233  ir->t_nper != m_crpt->nper ||
7234  ir->i_det != m_crpt->ndet ||
7235  ir->i_use != m_crpt->nuse)
7236  {
7237  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Parameter mismatch");
7238  status.addInfo(FAC_DAE, oss.str());
7239  delete ir;
7240  return DAEstatus::Failure;
7241  }
7242  ICPCritical cs(&m_crpt_cs);
7243  isisU32_t* new_poslut = new isisU32_t[maxcrate * maxmod * maxpos];
7244  int* last_card_spectrum = new int[maxcrate];
7245  memset(new_poslut, 0, maxcrate * maxmod * maxpos * sizeof(isisU32_t));
7246  memset(last_card_spectrum, 0, maxcrate * sizeof(int));
7247  spec_len = ir->t_ntc1 + 1;
7248  ndet = ir->i_det;
7249  nper = ir->t_nper;
7250  maxspec = (ir->t_nsp1 + 1);
7251  int* spec_lookup = new int[maxspec];
7252  memset(spec_lookup, 0, maxspec * sizeof(int));
7253  for(i=0; i < ndet; i++)
7254  {
7255  card = ir->crat[i];
7256  modn = ir->modn[i];
7257  mpos = ir->mpos[i];
7258  spec = ir->spec[i];
7259  if (card >= maxcrate)
7260  {
7261  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "Too many crates");
7262  return DAEstatus::Failure;
7263  }
7264  if (spec > 0)
7265  {
7266  j = card * (maxmod * maxpos) + modn * (maxpos) + mpos;
7267  if (spec_lookup[spec] != 0)
7268  {
7269  new_poslut[j] = spec_lookup[spec];
7270  }
7271  else
7272  {
7273  new_poslut[j] = ++(last_card_spectrum[card]);
7274  spec_lookup[spec] = last_card_spectrum[card];
7275  }
7276  }
7277  }
7278  for(i=0; i < ndet; i++)
7279  {
7280  card = ir->crat[i];
7281  spec = ir->spec[i];
7282  if (spec > 0)
7283  {
7284  maxcardspec = last_card_spectrum[card] + 1;
7285  for(j=0; j<nper; j++)
7286  {
7287  m_dae->writeHistogramMemory(card, &(ir->dat1[(spec + maxspec * j) * spec_len]),
7288  (spec_lookup[spec] + maxcardspec * j) * spec_len * 4,
7289  spec_len, status);
7290  }
7291  }
7292  }
7293  for(i=0; i<maxcrate; i++)
7294  {
7295  if (last_card_spectrum[i] > 0)
7296  {
7297  oss << "Writing " << last_card_spectrum[i] << " spectra to detector card " << i << std::endl;
7298  m_dae->writePOSLUTMemory(i, &(new_poslut[i * (maxmod * maxpos)]), maxmod * maxpos, status);
7299  }
7300  }
7301  delete []new_poslut;
7302  delete []last_card_spectrum;
7303  delete[] spec_lookup;
7304  delete ir;
7305  status.addInfo(FAC_DAE, oss.str());
7306  return status.result();
7307 }
7308 
7309 int ISISinstrumentControl::setVeto(const std::string& name, long enable, DAEstatus& status)
7310 {
7311  ICPCritical cs(&m_crpt_cs);
7312  m_dae->setVeto(name, (enable != 0 ? true : false), status);
7313  return status.result();
7314 }
7315 
7316 int ISISinstrumentControl::evaluateExpression(std::map<std::string,double>& values, const std::string& expression, double& result, DAEstatus& status)
7317 {
7318  using namespace mu;
7319  if (expression.size() == 0)
7320  {
7321  result = 1e38;
7322  return DAEstatus::Failure;
7323  }
7324  try
7325  {
7326  Parser p;
7327  std::string sexp(expression);
7328 // std::transform(sexp.begin(), sexp.end(), sexp.begin(), tolower);
7329  for(std::map<std::string,double>::iterator it = values.begin(); it != values.end() ; ++it)
7330  {
7331  p.DefineVar(it->first.c_str(), &(it->second));
7332  }
7333  p.SetExpr(sexp);
7334  result = p.Eval();
7335  return DAEstatus::Success;
7336  }
7337  catch (Parser::exception_type& e)
7338  {
7339  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "mu parser error: %s", e.GetMsg().c_str());
7340  result = 1e38;
7341  return DAEstatus::Failure;
7342  }
7343 }
7344 
7345 int ISISinstrumentControl::getFramesAllPeriods(long* good_frames, long* raw_frames, int n, DAEstatus& status)
7346 {
7347  if (n != m_crpt->nper)
7348  {
7349  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "invalid number of periods");
7350  return DAEstatus::Failure;
7351  }
7352  isisU32_t igf, irf;
7354  {
7355  // totals up to last pause
7356  for(int i=0; i<m_crpt->nper; i++)
7357  {
7358  PERIOD& pi = m_crpt->period[i];
7359  good_frames[i] = pi.good_frames;
7360  raw_frames[i] = pi.total_frames;
7361  }
7362  // adjust for currrent running in period
7363  int period, daq_period;
7364  getCurrentPeriodNumber(period, daq_period, status);
7365  PERIOD* pc = &(m_crpt->period[period]);
7366  m_dae->getGoodFrames(&igf, status);
7367  m_dae->getRawFrames(&irf, status);
7368  good_frames[period] += (igf - m_crpt->good_frames);
7369  raw_frames[period] += (irf - m_crpt->total_frames);
7370  }
7371  else
7372  {
7373  for(int i=0; i<m_crpt->nper; i++)
7374  {
7375  m_dae->getRawFramesPeriod(&irf, i, status);
7376  m_dae->getGoodFramesPeriod(&igf, i, status);
7377  good_frames[i] = igf;
7378  raw_frames[i] = irf;
7379  }
7380  }
7381  return 0;
7382 }
7383 
7384 int ISISinstrumentControl::getUAmpHAllPeriods(float* good_uamph, float* raw_uamph, int n, DAEstatus& status)
7385 {
7386  if (n != m_crpt->nper)
7387  {
7388  status.addVa(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "invalid number of periods");
7389  return DAEstatus::Failure;
7390  }
7392  {
7393  // totals up to last pause
7394  for(int i=0; i<m_crpt->nper; i++)
7395  {
7396  PERIOD& pi = m_crpt->period[i];
7397  good_uamph[i] = pi.good_uamph;
7398  raw_uamph[i] = pi.total_uamph;
7399  }
7400  // adjust for currrent running in period
7401  int period, daq_period;
7402  getCurrentPeriodNumber(period, daq_period, status);
7403  PERIOD* pc = &(m_crpt->period[period]);
7404  float goodua = m_dae->getGoodUAmpHours(status);
7405  float totalua = m_dae->getRawUAmpHours(status);
7406  good_uamph[period] += (goodua - m_crpt->good_uamph);
7407  raw_uamph[period] += (totalua - m_crpt->total_uamph);
7408  }
7409  else
7410  {
7411  for(int i=0; i<m_crpt->nper; i++)
7412  {
7413  good_uamph[i] = m_dae->getGoodUAmpHoursPeriod(i, status);
7414  raw_uamph[i] = m_dae->getRawUAmpHoursPeriod(i, status);
7415  }
7416  }
7417  return 0;
7418 }
7419 
7420 
7421 boost::signals2::connection ISISinstrumentControl::registerOnRunStateChange(boost::function<void(BSTR)> func)
7422 {
7423  return m_state_sig.connect(func);
7424 }
7425 
7427 {
7428  Poco::NotificationCenter& nc = Poco::NotificationCenter::defaultCenter();
7429  nc.postNotification(new RunStateChangeNotification(state));
7430  m_state_sig(CT2OLE(state));
7431 }
7432 
7433 
7434 
7435 
7436 // append day name e.g. Mon, Tue to filename
7437 // also deletes next file in sequence to stop logs growing too much
7439 {
7440  Poco::Timespan one_day(1, 0, 0, 0, 0);
7441  std::string form = m_log_dir+"\\post_command_%s.log";
7442  Poco::LocalDateTime dateTime; // current date and time
7443  std::string file = Poco::format(form.c_str(), Poco::DateTimeFormatter::format(dateTime, "%w"));
7444  dateTime += one_day;
7445  std::string next_file = Poco::format(form.c_str(), Poco::DateTimeFormatter::format(dateTime, "%w"));
7446  if (_access(next_file.c_str(), 0) == 0)
7447  {
7448  remove(next_file.c_str());
7449  }
7450  return file;
7451 }
7452 
7453 int ISISinstrumentControl::updateSpecmapsFromDAE(const std::map<int,int>& trcn, DAEstatus& status)
7454 {
7455  const ISISDAE::dae2spec_map_t& dae2specmap = m_dae->getDAE2Specmap();
7456  if (dae2specmap.size() > ISISCRPT_MAX_DC)
7457  {
7458  status.addVa(FAC_DAE,SEV_ERROR,ERRTYPE_OUTOFMEM, "updateSpecmapsFromDAE: too many cards %d", dae2specmap.size());
7459  return DAEstatus::Failure;
7460  }
7461  m_crpt->ndetcard = dae2specmap.size();
7462  std::transform(dae2specmap.begin(), dae2specmap.end(), m_crpt->dae2cardpos.c_array(), boost::bind(&ISISDAE::dae2spec_map_t::value_type::first, _1));
7463  std::map<int,int>::const_iterator tr_it;
7464  std::fill(m_crpt->cardpos2index.begin(), m_crpt->cardpos2index.end(), -1);
7465  for(int i=0; i<m_crpt->ndetcard; ++i)
7466  {
7467  int pos = m_crpt->dae2cardpos[i];
7468  if (pos < 0 || pos >= m_crpt->cardpos2index.size())
7469  {
7470  throw std::runtime_error("cardpos2index - pos too high");
7471  }
7472  m_crpt->cardpos2index[pos] = i;
7473  tr_it = trcn.find(pos);
7474  if (tr_it != trcn.end())
7475  {
7476  m_crpt->dae2cardtr[i] = m_crpt->daeTR(tr_it->second);
7477  m_crpt->dae2cardmode[i] = (m_crpt->isEventTR(tr_it->second) ? 1 : 0);
7478  }
7479  else
7480  {
7481  m_crpt->dae2cardtr[i] = -1; // card not being used by current wiring tables, so no TR information available
7482  m_crpt->dae2cardmode[i] = -1;
7483  }
7484  }
7485  for(int i=0; i<m_crpt->ndetcard; ++i)
7486  {
7487  int pos = m_crpt->dae2cardpos[i];
7488  const ISISDAE::dae2spec_map_t::mapped_type& val = dae2specmap.find(pos)->second;
7489  if (val.size() > ISISCRPT_MAX_DC_DETECTOR)
7490  {
7491  status.addVa(FAC_DAE,SEV_ERROR,ERRTYPE_OUTOFMEM, "updateSpecmapsFromDAE: too many spectra %d", val.size());
7492  return DAEstatus::Failure;
7493  }
7494  m_crpt->dae2highspec[i] = val.size() - 1; // spectrum numbers start at 0
7495  std::copy(val.begin(), val.end(), m_crpt->dae2specmap[i]);
7496  }
7497  return DAEstatus::Success;
7498 }
7499 
7501 {
7502  if (isRunning())
7503  {
7505  }
7506  else
7507  {
7508  return DAEstatus::Success;
7509  }
7510 }
7511 
7513 {
7514  return m_dae->isFinalSequenceComplete(status);
7515 }
7516 
7517 int ISISinstrumentControl::getSpectrumNumbersForTimeRegime(long tr, long& spec_min, long& spec_max, DAEstatus& status)
7518 {
7519  spec_min = 1000000;
7520  spec_max = 0;
7521  if (tr >= 1 && tr <= m_crpt->ntrg)
7522  {
7523  spec_min = m_crpt->spec_min[tr-1];
7524  spec_max = m_crpt->spec_max[tr-1];
7525  }
7526  return DAEstatus::Success;
7527 }
7528 
7529 int ISISinstrumentControl::setRunStatusImp(long number, bool is_start, DAEstatus& status)
7530 {
7531  if (se_set_run_state(m_crpt->run_number, runstatus_names[number], (is_start ? 1 : 0)) != 0)
7532  {
7533  status.addInfoVa(FAC_DAE, "Error from SQLITE: %s", se_get_errmsg());
7534  }
7535  m_crpt->run_status = number;
7536  return DAEstatus::Success;
7537 }
7538 
7539 
7541 {
7542  ValueWithTimestamp<float> good_uamph;
7543 // static Poco::Timestamp last_call;
7544 // float good_uamph = getGoodUAmpH(m_status);
7545 // Poco::Timestamp now;
7546 // Poco::Timestamp::TimeDiff tdiff = now - last_call;
7547 // float good_uamp_diff = good_uamph - m_crpt->update_good_uamph;
7548 // m_crpt->beam_current = 3600.0 * (good_uamph - m_crpt->update_good_uamph) / tdiff;
7549 // m_crpt->update_good_uamph = good_uamph;
7550 // last_call = now;
7551 }
7552 
7553 
7554 Poco::Util::Application* InstrumentControlHolder::m_pApp = NULL;
7559 
7560 std::string ISISinstrumentControl::m_instrument_xml_file = "c:\\data\\instrument.xml";
7561 std::string ISISinstrumentControl::m_instrument_parameter_map_file = "c:\\data\\instrument_parameter_map.txt";
boost::array< int, ISISCRPT_MAX_DETECTOR > det_mode
Definition: isiscrpt.h:310
int VMEReadValue(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long *value, DAEstatus &status)
#define NULL_TERMINATE(__array)
null terminate a char[n] static array
Definition: isiscrpt.h:74
float l2
Definition: DetectorFile.h:14
int setSampleParameters(const string_table_t &table, DAEstatus &status)
int(ISISinstrumentControl::* xml_update_func_t)(const std::string &xml, DAEstatus &status)
int updateFunc(int poll_time, bool only_refresh_cache)
int md5sumFile(const char *filename, unsigned char *md5sum, DAEstatus &status)
Definition: icputils.cpp:253
void endPrefixMapping(const Poco::XML::XMLString &prefix)
char file[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:455
std::string filename()
int getVetoStatus(std::string &veto_text, DAEstatus &status)
Definition: isisdae.cpp:1950
int openGroup(const char *group_name, const char *group_class)
int loadFromString(BSTR xml_string, DAEstatus &status)
float uamp_scale
Definition: isiscrpt.h:479
static void histogramEventsToCRPT(const ISISCRPT_STRUCT *crpt1, const ISISCRPT_STRUCT *crpt2, ISISCRPT_DATA *crpt_data1, ISISCRPT_DATA *crpt_data2, const DAEEventHeader *head, const DetectorEvent32 *ev, int n, int event_source_id)
Definition: CRPTProxy.cpp:437
int electronics_delay
Definition: isiscrpt.h:263
boost::array< int, ISISCRPT_NUM_FC_VETO > fermi_chopper_delay
in 20ns
Definition: isiscrpt.h:390
int data_type
0=unknown, 1=int, 2=float
Definition: isiscrpt.h:182
int ioRAW(FILE *file, bool from_file)
Definition: isisraw.cpp:639
static void seTransFunction(unsigned int u, EXCEPTION_POINTERS *pExp)
static const char * muon_daes[]
int ts1_repr
for ts1
Definition: isiscrpt.h:193
int setPeriodType(ISISDAE::PeriodType type, bool single_daq_period, DAEstatus &status)
Definition: isisdae.cpp:1576
int refreshCachedValues(DAEstatus &status)
time_t stop_time
last time period paused
Definition: isiscrpt.h:160
char comment[512]
Definition: isiscrpt.h:400
float getCurrentPeriodRawUAmpH(DAEstatus &status)
#define FAC_DAE
int setValue(const char *name, const char *value, DAEstatus &status)
bool isMultiplePeriodSequenceComplete(DAEstatus &status)
Definition: isisdae.cpp:1777
int loadFromFile(const char *filename, DAEstatus &status)
char sample_geometry[80]
Definition: isiscrpt.h:416
#define ERRTYPE_OUTOFMEM
int timr_crpt[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:313
int getMEvents(double &mevents, DAEstatus &status)
int setVeto(const std::string &name, bool enable, DAEstatus &status)
Definition: isisdae.cpp:1447
int listEntries(std::list< std::string > &entries, bool groups_only=false)
int getNumberOfSpectra(DAEstatus &status)
int getHardwarePeriodsXML(const std::string &periods_xml_in, std::string &periods_xml_out, DAEstatus &status)
static int logEventVaImp(time_t the_time, const CRPTProxy &crpt, DAEstatus &status, const char *event, va_list ap)
int getPeriodSize() const
Definition: isiscrpt.h:658
int getNumSpectra(bool include_spectrum_zero=false) const
Definition: isiscrpt.cpp:926
int getRealArrayItem(const char *item_name, const long *spec_array, int nspec, double *darray, DAEstatus &status) const
Definition: CRPTProxy.h:382
long update_period_sequence
Definition: isiscrpt.h:379
float getGoodUAmpH(DAEstatus &status)
int getIntArrayItemSize(const char *item_name, int *dims_array, int &ndims, DAEstatus &status)
float getGoodUAmpHoursPeriod(int period, DAEstatus &status)
Definition: isisdae.cpp:1065
int code[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:304
SELOGGER_API int __stdcall se_log_run(int run_number, const char *source, const char *iso_time, int period, int run_status, int is_running, int is_waiting, int good_frames, int raw_frames, float good_uamph, float raw_uamph, int64_t monitor_sum0, float dae_beam_current, int64_t total_counts, float count_rate, float npratio_current)
Definition: selogger.cpp:701
static int logEventVa(time_t the_time, const CRPTProxy &crpt, DAEstatus &status, const char *event,...)
ISISCRPT_DATA * crptData()
Definition: CRPTProxy.h:284
int readData(const char *data_name, std::string &value)
int write_event_log_t(int sev, const char *message, void *arg)
int setLinearTimeChannelRange(int range_number, float start, float end, float step, DAEstatus &status)
int whichVeto(std::string &veto_text, DAEstatus &status)
Definition: isisdae.cpp:1958
int getRealItem(const char *item_name, double &dblVal, DAEstatus &status)
int addVa(int facility, int severity, int errtype, const char *format,...)
Definition: DAEstatus.cpp:54
int setDAE1Vetos(int vetos[], int n, DAEstatus &status)
Definition: isisdae.cpp:1362
#define SEV_WARNING
int udet[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:315
int getGoodPPPLower(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1043
int RIO(isis32_t bus_addr, isisU16_t &word, DAEstatus &status)
int getNumberOfPeriods(DAEstatus &status)
int writePOSLUTMemory(int card_id, isisU32_t *buffer, int len, DAEstatus &status)
Definition: isisdae.cpp:1970
int getCurrentPeriodRawFrames(DAEstatus &status)
int64_t update_total_counts
Definition: isiscrpt.h:375
static int ISOtime(time_t time, char *buffer, int len)
void stop(bool delete_file=false)
Poco::Net::ServerSocket * m_http_svs
md5checksum_t checksum
Definition: isiscrpt.h:80
float update_good_uamph
Definition: isiscrpt.h:372
int updateCycle(DAEstatus &dstatus)
#define ISISDAE_MAX_DAE2TIMECHAN
PeriodType
Definition: isisdae.h:67
int auto_save_count
Definition: isiscrpt.h:289
LONGLONG proc_freq
Definition: isiscrpt.h:486
float sample_phi_angle
Definition: isiscrpt.h:422
#define ISISCRPT_MAX_DC
Definition: isiscrpt.h:26
std::ostream & printStatus(std::ostream &os, DAEstatus &dstatus)
int writeAutosaveFile(DAEstatus &dstatus)
float getRawUAmpHoursPeriod(int period, DAEstatus &status)
Definition: isisdae.cpp:1053
double veto_percent
Definition: isiscrpt.h:208
float rtcb[ISISCRPT_MAX_NTRG][ISISCRPT_MAX_TIMECHANB]
Definition: isiscrpt.h:344
void setEventMode(bool value)
Definition: isisdae.h:254
int open(const char *filename, int mode, int type=IXNeXusFile::HDF5)
const std::string & eventLog() const
Definition: CRPTProxy.h:288
char field_label[256]
Definition: isiscrpt.h:398
float update_raw_uamph
Definition: isiscrpt.h:371
int modn[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:308
int flushCRPT(DAEstatus &status, bool flush_raw_data=false)
int updateFromString(const std::string &xml_string, DAEstatus &status)
ISISinstrumentControl * icp
int getRealArrayItem(const char *item_name, double *darray, DAEstatus &status)
int allReportFuncMain(const DAEstatus_message &mess)
int storeCRPT(DAEstatus &status)
int stopDataCollection(ISISDAE::StopRunMode mode, DAEstatus &status)
int updateUserXML(const std::string &user_xml, DAEstatus &status)
int updateXML(const char *name, xml_update_func_t func, DAEstatus &dstatus)
float offset
Definition: DetectorFile.h:13
static write_event_log_t * m_event_func
float beams
synchrottron
Definition: isiscrpt.h:190
unsigned total_frames
total up to last pause
Definition: isiscrpt.h:169
float sample_thickness
Definition: isiscrpt.h:412
float sample_height
Definition: isiscrpt.h:411
int stopRun(StopRunMode mode, DAEstatus &status)
Definition: isisdae.cpp:877
SELOGGER_API int __stdcall se_get_block_values(seblock_map_t &blocks)
Definition: selogger.cpp:1388
float last_change
Definition: isiscrpt.h:224
static int updateBeamlineParameters(const CRPTProxy::parameter_map_t &beamline_parameters, CRPTProxy &crpt, const seblock_map_t *se_blocks, DAEstatus &status)
int endSEWait(DAEstatus &dstatus)
int readTables(const char *wiring, const char *detector, const char *spectra, DAEstatus &status)
int getGoodPPPUpper(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1048
char label[ISISCRPT_PERIOD_LABEL_LEN]
Definition: isiscrpt.h:170
static bool getBeamlogInt64(Poco::XML::Document *pDoc, const std::string &path, int64_t &value)
bool isFinalSequenceComplete(DAEstatus &status)
Definition: isisdae.cpp:2074
StopRunMode
Definition: isisdae.h:154
beamlogger_t beamlogger
Definition: isiscrpt.h:490
void onFinished(Poco::TaskFinishedNotification *pNf)
int readDAE1Spectra(isisU32_t *buffer, int nbuffer, int spec_to_crpt_offset[], int spec_start, int nspec, int period, int persize, DAEstatus &status)
Definition: isisdae.cpp:535
int beginRunEx(bool start_paused, bool delayed_start, long period, DAEstatus &status)
ICPProgressHandler m_task_ph
RUNTABLE wiring_table
Definition: isiscrpt.h:274
int makeNewGroup(const char *name, const char *nxclass, bool open_group=true)
write_event_log_t * m_event_log_func
int setDAESpecificParameters()
Definition: isiscrpt.cpp:102
static int vmstime(char *timbuf, int len, time_t time_value)
Definition: isisraw.cpp:1192
int saveCRPTToFile(const CRPTProxy &crpt, const std::string &raw_filename, const std::string &nexus_filename, const seblock_map_t &blocks, const std::string &events_nxfile, DAEstatus &dstatus)
int updateMonitoringXML(const std::string &monitor_xml, DAEstatus &status)
bool is_real
Definition: selogger.h:92
bool compareChecksums(const unsigned char *md5sum1, const unsigned char *md5sum2)
Definition: icputils.cpp:313
char lvxml_monitoring[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:435
char lvxml_periods[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:434
#define ISISCRPT_MAX_NTRG
Definition: isiscrpt.h:20
static std::string getProcessName(DWORD processID)
boost::array< float, ISISCRPT_MAX_TCPAR > tcpar
Definition: isiscrpt.h:132
boost::array< int, ISISCRPT_MAX_NUM_DAE *100 > cardpos2index
reverse of dae2cardpos above - turns position into array index. 100 here is DAE2CardPolicy::CRATE_MOD...
Definition: isiscrpt.h:325
char lvxml_tcb[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:432
int endRunMain(DAEstatus &status)
time_t resume_time
Definition: isiscrpt.h:255
int setupDAE(int tables_only, DAEstatus &dstatus)
void clearDCEventMode(DAEstatus &status)
Definition: isisdae.cpp:2056
int DAEreport_func_t(const DAEstatus_message &mess, void *arg)
Definition: DAEstatus.h:119
int npar
length of tcpar used
Definition: isiscrpt.h:133
Poco::SharedPtr< CRPTProxy > m_crpt_run
used for fast ends
SELOGGER_API int __stdcall se_start_epics_thread(epics_thread_data_t *arg)
Definition: selogger.cpp:469
char epics_lastread_iso[64]
Definition: isiscrpt.h:492
double offset
Definition: isiscrpt.h:185
std::vector< float > fcurrent_spread
per period
Definition: selogger.h:91
void setDCEventMode(unsigned long card_id, bool value, DAEstatus &status)
Definition: isisdae.cpp:2029
int writeJournal(const CRPTProxy &crpt, seblock_map_t &blocks, DAEstatus &status)
float last_value
Definition: isiscrpt.h:223
time_t start_time
Definition: isiscrpt.h:254
float tcb_minwidth
Definition: isiscrpt.h:265
int getCurrentPeriodGoodFrames(DAEstatus &status)
int whichVeto(std::string &veto_text, DAEstatus &status)
RUNTABLE tcb_file
used if TCBRANGE_FILE
Definition: isiscrpt.h:134
const std::string & statusLog() const
Definition: CRPTProxy.h:287
static const char * star_line80
static const int CRATE_MOD
Definition: dae2_policy.h:17
void rawDataUpdated()
Definition: CRPTProxy.h:296
float sample_width
Definition: isiscrpt.h:410
void setDCCardMode(unsigned long card_id, bool neutron_data, DAEstatus &status)
Definition: isisdae.cpp:2043
bool isRunning() const
Definition: isiscrpt.h:507
unsigned long isisU32_t
Definition: isisvme_types.h:8
int getRawFramesPeriod(isisU32_t *value, int period, DAEstatus &status)
Definition: isisdae.cpp:1002
int readFromFile(const char *filename)
Definition: isisraw.cpp:1239
int sumAllSpectra(long &counts, long &bin0_counts, DAEstatus &status)
isis32_t open(const char *dae_name, DAEstatus &status)
Definition: isisdae.cpp:613
int period_output_delay
Definition: isiscrpt.h:403
static const int Failure
Definition: DAEstatus.h:141
void characters(const Poco::XML::XMLChar ch[], int start, int length)
int add(DAEstatus &dstatus, bool clear)
Definition: DAEstatus.cpp:131
int readDetectorTable(const char *filename, DAEstatus &status)
int getCurrentPeriodNumber(int &period, int &daq_period, DAEstatus &status)
struct timeb calc_last_time
Definition: isiscrpt.h:462
#define TCBRANGE_CONST_T
dt=c
Definition: isiscrpt.h:121
bool m_vms_raw_files
produce a VMS raw file
char period_file[ICP_NAME_LEN]
Definition: isiscrpt.h:253
time_t beam_on_time
Definition: isiscrpt.h:200
int getCharItem(const char *item_name, std::string &cvalue, DAEstatus &status) const
Definition: isiscrpt.cpp:228
const std::string & instXMLFileName() const
Definition: DetectorFile.h:88
std::vector< float > fsetpoint_value
per period
Definition: selogger.h:78
int stopEventWriter(bool wait, DAEstatus &status)
int shutter
0 = closed, 1 = open
Definition: isiscrpt.h:197
std::map< std::string, SEBLOCK > seblock_map_t
Definition: selogger.h:128
int changePeriod(int period, DAEstatus &status)
int setBeamlineParameters(const string_table_t &table, DAEstatus &status)
char alert_email[1024]
Definition: isiscrpt.h:478
int clock_frequency
Definition: isiscrpt.h:261
int clearHistogramMemory(DAEstatus &status)
Definition: isisdae.cpp:815
RUNTABLE spectra_table
Definition: isiscrpt.h:275
int clearCounters(DAEstatus &status)
Definition: isisdae.cpp:836
int mode
must be a TCBRANGE_* define
Definition: isiscrpt.h:129
#define ISISCRPT_MAX_DETECTOR
Definition: isiscrpt.h:14
int auto_save_type
Definition: isiscrpt.h:286
int getTotalCounts(int64_t *value, DAEstatus &status)
Definition: isisdae.cpp:1685
int fillWithTestPattern(unsigned long pattern, DAEstatus &status)
std::vector< std::vector< std::string > > string_table_t
time_t start_time
first time period started
Definition: isiscrpt.h:159
int updateChecksum(unsigned char *md5sum1, const unsigned char *md5sum2)
Definition: icputils.cpp:331
int getIntArrayItem(const char *item_name, const long *spec_array, int nspec, long *larray, DAEstatus &status) const
Definition: CRPTProxy.h:374
SECURITY_ATTRIBUTES * defaultNoInheritHandles()
Definition: icputils.cpp:1121
int getValue(const char *name, char *value, int max_len, bool write_null, DAEstatus &status)
int getOptions(std::string &options_xml, DAEstatus &status)
int mpos[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:309
int getDAEsettingsXML(const std::string &dae_xml_in, std::string &dae_xml_out, DAEstatus &status)
static int logEvent(time_t the_time, const CRPTProxy &crpt, const std::string &event, DAEstatus &status)
int printInfo(std::ostream &os)
Definition: isisraw.cpp:1284
int getExternalResetCommands(std::list< std::pair< std::string, std::string > > &commands, DAEstatus &status)
Definition: isisdae.cpp:2085
float total_uamph
Definition: isiscrpt.h:281
std::vector< std::string > setpoint_value
per period
Definition: selogger.h:77
int runPostCommand(const char *property_name, const std::string &arg, DAEstatus &status)
static const int Success
Definition: DAEstatus.h:140
int getGoodFrames(DAEstatus &status)
int muonkicker
0 = off, 1 = on
Definition: isiscrpt.h:198
#define LOGSTR_DEBUG(__arg)
Definition: IsisBase.h:71
unsigned good_frames
Definition: isiscrpt.h:278
bool isFinalSequenceComplete(DAEstatus &status)
int crate
Definition: isiscrpt.h:180
char scaled_units[64]
Definition: isiscrpt.h:179
int getRawPPPLower(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1033
char instrument_xml_file[ISISCRPT_MAX_FNAMELEN]
Definition: isiscrpt.h:445
int getSMPVetoedFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1647
boost::array< int, ISISCRPT_MAX_MONITOR > monp
Definition: isiscrpt.h:296
boost::array< int, ISISCRPT_MAX_DC > dae2cardpos
detector card positions, length ndetcard
Definition: isiscrpt.h:324
int importCRPT(const char *filename, DAEstatus &dstatus)
bool hasFileChanged(DAEstatus &status) const
Definition: isiscrpt.h:85
const std::string & debugLog() const
Definition: CRPTProxy.h:289
int setReportFunction(DAEreport_func_t *report_func, void *arg)
Definition: DAEstatus.h:178
#define SEV_FATAL
int spacePadCopyVa(char *output, int output_size, const char *format,...)
Definition: isiscrpt.cpp:142
static int size_check()
Definition: isisraw.cpp:1167
static int replaceSEparameters(std::string &s, const seblock_map_t *se_blocks, DAEstatus &status)
int killDatasvr(DAEstatus &dstatus)
#define RUNSTATUS_WAITING
Definition: isiscrpt.h:52
bool beamOn(int minutes=0) const
int tcbcalc(DAEstatus &status)
long update_period
Definition: isiscrpt.h:378
CRPTProxy m_crpt
pointer to CRPT
static std::string m_icp_service_dir
bool beam_on
Definition: isiscrpt.h:201
#define RUNSTATUS_SETUP
Definition: isiscrpt.h:49
int fileTR(int tr) const
file_tr same as crpt_tr for now
Definition: isiscrpt.h:762
int dae2specmap[ISISCRPT_MAX_DC][ISISCRPT_MAX_DC_DETECTOR]
give spectrum number from dae2 card and dae2 spec number
Definition: isiscrpt.h:328
float aperture2
Definition: isiscrpt.h:409
#define TCBRANGE_FILE
read from file
Definition: isiscrpt.h:119
double diffFileTimesInMilliSec(const FILETIME &start, const FILETIME &finish)
finish - start in milliseconds
Definition: icputils.cpp:624
float beam_centre_x
Definition: isiscrpt.h:406
int writeHistogramMemory(int card_id, isisU32_t *buffer, int start, int len, DAEstatus &status)
Definition: isisdae.cpp:1985
void startEventBroadcaster(const CRPTProxy &crpt)
Definition: isisdae.h:302
int compression_block_size
Definition: isiscrpt.h:481
int dae_status
Definition: isiscrpt.h:212
const std::string & instName() const
Definition: DetectorFile.h:87
#define SESTATUS_INRANGE
Definition: isiscrpt.h:62
static int updateCRPTwithSE(CRPTProxy &crpt, DAEstatus &dstatus)
char beamstop_position[16]
Definition: isiscrpt.h:414
int notifyICP(long event_id, const char *param, DAEstatus &status)
int changeNumberOfPeriods(int nperiod, DAEstatus &status)
Definition: isisdae.cpp:231
long update_raw_frames
Definition: isiscrpt.h:377
float beamt
for appropriate target
Definition: isiscrpt.h:192
float getRawUAmpH(DAEstatus &status)
void markInitialised()
Definition: isiscrpt.h:499
static int writeISISRAW(const CRPTProxy &crpt, const char *filename, DAEstatus &dstatus)
int startDataCollection(bool clear_counters, DAEstatus &status)
#define RUNSTATUS_PAUSED
Definition: isiscrpt.h:51
SELOGGER_API const char *__stdcall se_get_errmsg()
Definition: selogger.cpp:696
time_t time
update time
Definition: isiscrpt.h:203
const std::string & instParameterMapFileName() const
Definition: DetectorFile.h:90
SELOGGER_API int __stdcall se_set_period(int period)
Definition: selogger.cpp:734
std::string str() const
Definition: DAEstatus.h:82
#define LOGSTR_WARNING(__arg)
Definition: IsisBase.h:92
int timr_dae[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:312
isisU32_t rawDataSizeMax() const
Definition: CRPTProxy.h:298
int getSpectrumIntegral(long spec_no, long period, float t_low, float t_high, long &integral, long &max_val, DAEstatus &status)
static const char * FrameSyncNames[]
void ignorableWhitespace(const Poco::XML::XMLChar ch[], int start, int length)
static void nxErrorFunc(void *arg, char *text)
const std::string & monitoringLog() const
Definition: CRPTProxy.h:290
int assignLogFiles(const std::string &prefix)
Definition: CRPTProxy.cpp:388
std::string convertWindows1252ToUTF8(const std::string &win_string)
Definition: icputils.cpp:18
std::vector< std::string > current_value
per period
Definition: selogger.h:89
int setRunStatusImp(long number, bool is_start, DAEstatus &status)
#define TCBRANGE_SHIFTED
pure shift from an existing range
Definition: isiscrpt.h:124
#define ISISCRPT_MAX_DATADAE
Definition: isiscrpt.h:41
boost::array< int, ISISCRPT_MAX_NTRG > spec_min
range of spectrum numbers in CRPT time regime
Definition: isiscrpt.h:335
long update_duration
Definition: isiscrpt.h:382
float tthe[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:305
int * modn
Definition: isisraw.h:291
const std::string & instXML() const
Definition: DetectorFile.h:89
struct timeb update_time
Definition: isiscrpt.h:365
static void updateThread(void *arg)
int VMEWriteArray(unsigned long card_id, unsigned long card_address, isisU32_t *values, unsigned long num_values, DAEstatus &status)
Definition: isisdae.cpp:1865
int getFramesAllPeriods(long *good_frames, long *raw_frames, int n, DAEstatus &status)
boost::array< VETO, ISISCRPT_NUM_VETOS > vetos
Definition: isiscrpt.h:360
int monitor_spectrum
Definition: isiscrpt.h:298
int i_use
Definition: isisraw.h:271
static const char * DAEType_desc[]
Definition: isisdae.h:66
int closeGroup()
int updateCRPTSpectra(int period, long spec_start, int nspectra, DAEstatus &status)
int VMEReadValuesToString(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long num_values, std::string &values, DAEstatus &status)
bool repr_normal
running at 40/50Hz if TS1, or 10Hz or TS2
Definition: isiscrpt.h:195
void appendToFileAsync(HANDLE h, const char *message, bool close_after_write)
Definition: icputils.cpp:441
char lvxml_dae[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:431
char institute[ISISCRPT_INSTITUTE_NAME_LEN+1]
Definition: isiscrpt.h:354
#define ISISCRPT_MAX_MONITOR
Definition: isiscrpt.h:16
std::string padWithZeros(int number, int len)
Definition: icputils.h:265
int VMEWriteValue(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long value, unsigned long mode, DAEstatus &status)
static int getAttrIntegerValue(Poco::XML::NamedNodeMap *attrs, const char *name)
char user_id[128]
Definition: isiscrpt.h:357
isisU32_t update_good_frames_period
Definition: isiscrpt.h:380
int unloadCRPT(bool delete_crpt_file, bool delete_crpt_data_file, DAEstatus &status)
Definition: CRPTProxy.cpp:47
int getExternalVetoedFrames(int veto_number, isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1662
int getGoodFramesPeriod(isisU32_t *value, int period, DAEstatus &status)
Definition: isisdae.cpp:1015
static const char * hash_line80
static double getAttrFloatValue(Poco::XML::NamedNodeMap *attrs, const char *name)
size_t file_size
Definition: isiscrpt.h:79
isisU32_t good_ppp_high
Definition: isiscrpt.h:283
#define FAC_CRPT
int repr
for appropriate target
Definition: isiscrpt.h:194
int getCRPTSpectrumIntegral(long spec_no, long period, float t_low, float t_high, long &integral, long &max_val, DAEstatus &status)
int loadDAEWithNeXusData(const std::string &file_name, long options, DAEstatus &status)
data_dae_t data_dae[ISISCRPT_MAX_DATADAE]
Definition: isiscrpt.h:474
int startEventWriter(DAEstatus &status)
#define R_OK
void stop(bool immediate)
int readSpectraTable(const char *filename, DAEstatus &status)
char user_email[128]
Definition: isiscrpt.h:355
void unregisterStructuredExceptionHandler(_se_translator_function old_func)
int exitProgram(const std::string &message, bool prompt)
isisU32_t total_ppp_high
Definition: isiscrpt.h:285
char temperature_label[256]
Definition: isiscrpt.h:399
int saveRun(DAEstatus &status)
static int stringTableToParameterMap(const string_table_t &string_table, CRPTProxy::parameter_map_t &param_map, DAEstatus &status)
int VMEReadArray(unsigned long card_id, unsigned long card_address, isisU32_t *values, unsigned long num_values, DAEstatus &status)
int beginRun(DAEstatus &status)
int resetRunController(DAEstatus &status)
Definition: isisdae.cpp:987
int reportAll(bool reset_overall_severity=true, bool remove_messages=true)
Definition: DAEstatus.h:169
_se_translator_function registerStructuredExceptionHandler()
this needs to be called per thread
int buildTimeRegimeMap()
Definition: isiscrpt.cpp:968
void startPrefixMapping(const Poco::XML::XMLString &prefix, const Poco::XML::XMLString &uri)
std::list< boost::signals2::connection > m_crpt_signals
int saveToString(std::string &s, DAEstatus &status)
int auto_save_value
Definition: isiscrpt.h:287
float delt[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:302
static int updateSampleParameters(const CRPTProxy::parameter_map_t &sample_parameters, CRPTProxy &crpt, const seblock_map_t *se_blocks, DAEstatus &status)
int nperseq_request
Definition: isiscrpt.h:260
float beam_current
Definition: isiscrpt.h:374
#define ISISCRPT_NUM_VETOS
max number of vetos
Definition: isiscrpt.h:112
boost::array< int, ISISCRPT_MAX_MONITOR > save_monitor_events
whether to save monitor events in event mode (size NMON)
Definition: isiscrpt.h:297
#define SEV_ERROR
int getTS2PulseVetoedFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1652
int getRealItem(const char *item_name, double &dblVal, DAEstatus &status) const
Definition: isiscrpt.cpp:391
int dae_type
time CRPT unloaded (may not be set if program crashed)
Definition: isiscrpt.h:247
int updateCRPTWithDAE(CRPTProxy &crpt, bool pause_collection, DAEstatus &status)
bool isValid() const
Definition: CRPTProxy.h:351
ICPNotificationHandler m_nh
int t_nper
Definition: isisraw.h:299
int getSpectrumNumbersForTimeRegime(long tr, long &spec_min, long &spec_max, DAEstatus &status)
char long_title[ISISCRPT_TITLE_LEN+1]
Definition: isiscrpt.h:350
void calculateCRPTOffsets()
Definition: isiscrpt.h:665
std::ostream & print(std::ostream &str, bool format_with_T=false, bool add_cr=false) const
Definition: DAEstatus.cpp:273
int shutter_val
Definition: isiscrpt.h:210
int setDCFrameSyncDelay(int crat, isisU32_t delay, DAEstatus &status)
Definition: isisdae.cpp:1524
bool OK()
Definition: DAEstatus.h:143
isisU32_t * rawData()
Definition: CRPTProxy.h:302
long update_good_frames
Definition: isiscrpt.h:376
char measurement_id[ICP_NAME_LEN]
Definition: isiscrpt.h:437
int findFiles(const char *directory, const char *pattern, std::vector< std::string > &list, bool full_path)
Definition: icputils.cpp:477
static int setRealParameter(const CRPTProxy::parameter_map_t &params, const seblock_map_t *se_blocks, const char *name, float &crpt_target, DAEstatus &status)
static DAEreport_func_t * m_func
int getNumberOfTimeChannels(int spectrum, DAEstatus &status)
boost::array< unsigned, ISISCRPT_MAX_MONITOR > monitor_sum
Definition: isiscrpt.h:300
float getCountRate(DAEstatus &status)
float tcb_mintime
Definition: isiscrpt.h:266
char name[256]
Definition: isiscrpt.h:177
int readRecoveryFile(DAEstatus &dstatus)
time_t stop_time
Definition: isiscrpt.h:256
static int allReportFunc(const DAEstatus_message &mess, void *arg)
static const char * runstatus_names[]
Definition: isiscrpt.h:57
int setTimeChannels(int crat, isisU32_t *tcb, int ntc, DAEstatus &status)
Definition: isisdae.cpp:341
static int loadCRPTWithHistogrammedEvents(CRPTProxy &crpt, DAEstatus &dstatus)
void setDocumentLocator(const Poco::XML::Locator *loc)
int getVetoStatus(std::string &veto_text, DAEstatus &status)
const char *__stdcall se_version()
Definition: selogger.cpp:345
int pauseRun(DAEstatus &status)
bool isEventTR(int tr) const
Definition: isiscrpt.h:767
int i_det
Definition: isisraw.h:269
isisU32_t update_raw_frames_period
Definition: isiscrpt.h:381
#define TCBRANGE_INC_T
dt/t=c
Definition: isiscrpt.h:122
int getFIFOVetoedFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1667
void clearCallbacks(const std::list< boost::signals2::connection > &callback_list)
Definition: isisdae.h:285
#define MAX_RC_RETRY
static int spawnCommand(const std::string &program, const std::string &args, bool use_cmd_exe, bool console, HANDLE *suspended_thread_handle, const std::string &std_in_file, const std::string &std_out_file, const std::string &std_error_file, int wait_time, DAEstatus &dstatus)
char journal_blocks[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:443
std::list< boost::signals2::connection > addGoodEventCallback(const EventCallbackSlotType &slot)
void snapshot(const std::string &name)
SELOGGER_API int __stdcall se_get_measurement_label(const char *measurement_id, std::string &res)
Definition: selogger.cpp:905
int getISIS50HzVetoedFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1657
RUNTABLE detector_table
Definition: isiscrpt.h:273
float angle_of_incidence
Definition: isiscrpt.h:421
float ut[ISISCRPT_MAX_USER]
Definition: DetectorFile.h:17
#define LOGSTR_INFORMATION(__arg)
Definition: IsisBase.h:78
void fireOnRunStateChange(const char *state)
bool endHeaderSeen()
void printStatus(std::ostream &os, DAEstatus &status)
Definition: isisdae.cpp:241
int getTCBXML(const std::string &tcb_xml_in, std::string &tcb_xml_out, DAEstatus &status)
void setRunNumberDigits(int digits)
Definition: nexuswriter.h:184
int tcb[ISISCRPT_MAX_NTRG][ISISCRPT_MAX_TIMECHANB]
Definition: isiscrpt.h:343
void endElement(const Poco::XML::XMLString &uri, const Poco::XML::XMLString &localName, const Poco::XML::XMLString &qname)
isisU32_t * dat1
Definition: isisraw.h:317
int startRun(bool clear_counters, int run_number, time_t &start_time, DAEstatus &status)
Definition: isisdae.cpp:843
int readAllDAE1Spectra(isisU32_t *buffer, int nbuffer, int spec_to_crpt_offset[], int persize, DAEstatus &status)
@ todo specttrum 0 may have differet size for time regimes
Definition: isisdae.cpp:561
void setICPStartTime(time_t t)
Definition: CRPTProxy.h:324
#define LOGSTR_ERROR(__arg)
Definition: IsisBase.h:99
isis32_t openBackplane(const char *dae_name_bp, DAEstatus &status)
Definition: isisdae.cpp:604
Poco::TaskManager m_taskmgr
int VMEReadValue(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long *value, DAEstatus &status)
Definition: isisdae.cpp:1843
isisU32_t * spectrumIntegrals()
Definition: CRPTProxy.h:311
int getRawFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:997
int wait_status
Definition: isiscrpt.h:211
SELOGGER_API int __stdcall se_set_run_number(int run_number)
Definition: selogger.cpp:729
unsigned short isisU16_t
Definition: isisvme_types.h:7
int getRawFrames(DAEstatus &status)
isisU32_t update_good_ppp_high
Definition: isiscrpt.h:368
isisU32_t update_total_ppp_high
Definition: isiscrpt.h:370
static int killProcess(const char *process_name, DAEstatus &dstatus)
int loadDAEWithData(const std::string &file_name, long options, DAEstatus &status)
static int prettyTime(time_t time, char *buffer, int len)
#define SESTATUS_OUTOFRANGE
Definition: isiscrpt.h:63
static bool getBeamlogString(Poco::XML::Document *pDoc, const std::string &path, std::string &value)
int writeWinEventLog(int sev, const std::string &message)
int endRunTask(Poco::SharedPtr< CRPTProxy > crpt, NeXusWriter &nxwriter, bool keep_raw_events, bool keep_crpt, const std::string events_nxfile, DAEstatus &status)
int writeISISRAWasync(const CRPTProxy &crpt, const char *filename, DAEstatus &dstatus)
int updateDAEsettingsXML(const std::string &status_xml, DAEstatus &status)
const std::string & instParameterMap() const
Definition: DetectorFile.h:91
int enableDelayedStart(DAEstatus &status)
Definition: isisdae.cpp:2001
unsigned char md5checksum_t[16]
Definition: icputils.h:303
SELOGGER_API int __stdcall se_set_period_async(int period)
Definition: selogger.cpp:1356
LONGLONG perf_counter
Definition: isiscrpt.h:485
boost::array< int, ISISCRPT_MAX_NTRG > tcb_trdelay
Definition: isiscrpt.h:270
FrameSync
Definition: isiscrpt_types.h:5
boost::signals2::signal< void(BSTR)> m_state_sig
int sendEmail(const std::string &sender, const std::string &recipient, const std::string &subject, const std::string &content, DAEstatus &status)
Definition: icputils.cpp:582
int spec[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:301
float chopper_opening_angle
Definition: isiscrpt.h:415
unsigned total_frames
Definition: isiscrpt.h:279
char fname[ISISCRPT_MAX_FNAMELEN]
Definition: isiscrpt.h:81
int readISISRAW(const char *filename, DAEstatus &dstatus)
int updateSampleXML(const std::string &sample_xml, DAEstatus &status)
int addWarning(int facility, const std::string &text)
Definition: DAEstatus.cpp:101
int startSEWait(DAEstatus &dstatus)
double info(const char *title, std::ostream &os, bool add_nl=true)
Definition: icptimer.h:83
SELOGGER_API int __stdcall se_close()
Definition: selogger.cpp:691
int getIntItem(const char *item_name, long &lVal, DAEstatus &status)
void start(const char *title=NULL)
Definition: icptimer.h:64
void startElement(const Poco::XML::XMLString &uri, const Poco::XML::XMLString &localName, const Poco::XML::XMLString &qname, const Poco::XML::Attributes &attrList)
static int updateBeamlineParametersFromFile(const char *filename, DAEstatus &status)
char instrument_parameter_map_file[ISISCRPT_MAX_FNAMELEN]
Definition: isiscrpt.h:446
unsigned epics_lastread_nano
Definition: isiscrpt.h:493
#define ISISCRPT_MAX_DC_DETECTOR
Definition: isiscrpt.h:15
Poco::SingletonHolder< ICPClock > g_icp_clock
Definition: icputils.cpp:5
boost::array< int, ISISCRPT_MAX_NTRG > ntcr
Definition: isiscrpt.h:339
float update_npratio_current
Definition: isiscrpt.h:424
int addWarningVa(int facility, const char *format,...)
Definition: DAEstatus.cpp:106
int disablePeriodCard(DAEstatus &status)
Definition: isisdae.cpp:1755
int changeNumberOfSoftwarePeriods(long nperiod, DAEstatus &status)
int getRealArrayItemSize(const char *item_name, int *dims_array, int &ndims, DAEstatus &status) const
Definition: isiscrpt.cpp:519
int writeMuonFile(const char *filename, const ISISCRPT_STRUCT *crpt, const isisU32_t *raw_data, isisU32_t raw_data_size, const seblock_map_t &blocks, const Poco::Path &inst_settings_dir, const std::string &inst_xml_file, const std::string &inst_parameter_map_file, DAEstatus &dstatus)
boost::array< int, ISISCRPT_MAX_MONITOR > mdet
Definition: isiscrpt.h:295
isisU32_t good_ppp_low
Definition: isiscrpt.h:282
int requestEndRunAfterNextSequenceCompletes(DAEstatus &status)
#define RUNSTATUS_RUNNING
Definition: isiscrpt.h:50
static Poco::Util::Application * m_pApp
char isis_cycle[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:444
std::vector< float > fcurrent_value
per period
Definition: selogger.h:90
static void deleteOutputFile(int run_number, DAEstatus &status)
int t_nsp1
Definition: isisraw.h:301
int writeISISNeXus(const char *filename, bool logs_only, const ISISCRPT_STRUCT *crpt, const isisU32_t *raw_data, isisU32_t raw_data_size, const ISISRAW *iraw, const seblock_map_t &blocks, const std::string &inst_xml_file, const std::string &inst_parameter_map_file, DAEstatus &dstatus, bool update=false)
int shutter_status
Definition: isiscrpt.h:213
double eventModeCardFraction() const
Definition: isiscrpt.h:844
char sample_name[256]
Definition: isiscrpt.h:397
float ts_total
since midnight for appropriate target
Definition: isiscrpt.h:196
SELOGGER_API int __stdcall se_get_seci_config(std::string &seci_config)
Definition: selogger.cpp:739
parameter_map_t & sampleParameters()
Definition: CRPTProxy.h:292
static int updateParametersFromFile(CRPTProxy::parameter_map_t &param_map, const char *filename, DAEstatus &status)
float good_uamph
Definition: isiscrpt.h:280
volatile LONG m_num_async_requests
FILETIME filetime
Definition: isiscrpt.h:487
const char * runStatusName() const
Definition: isiscrpt.h:508
int disableDelayedStart(DAEstatus &status)
Definition: isisdae.cpp:2016
int snapshotCRPT(const char *filename, bool do_update, bool do_pause, DAEstatus &status)
float foe_mirror_angle
Definition: isiscrpt.h:413
int readWiringTable(const char *filename, DAEstatus &status)
int spectrumCRPTTR(int spec) const
Definition: isiscrpt.h:794
int update_poll_time
Definition: isiscrpt.h:366
unsigned good_frames
total up to last pause
Definition: isiscrpt.h:168
HANDLE launchDatasvr(DAEstatus &dstatus)
void setParameters(LONGLONG perf_counter, LONGLONG proc_freq, FILETIME filetime)
Definition: icputils.h:171
md5checksum_t tcb_xml_checksum
Definition: isiscrpt.h:388
isisU32_t update_good_ppp_low
Definition: isiscrpt.h:367
int getDAQPeriod(int period, DAEstatus &status)
char inst_abrv[ISISCRPT_INST_ABRV_LEN+1]
Definition: isiscrpt.h:352
void unlock()
Definition: icputils.h:354
char icp_version[ICP_NAME_LEN]
Definition: isiscrpt.h:241
char user_telephone[128]
Definition: isiscrpt.h:356
md5checksum_t dae_xml_checksum
Definition: isiscrpt.h:387
char comp_name[MAX_COMPUTERNAME_LENGTH+1]
Definition: isiscrpt.h:477
void setUAmpScale(float scale)
Definition: isisdae.h:250
double wait_mins
Definition: isiscrpt.h:209
int VMEWriteValue(unsigned long card_id, unsigned long card_address, bool sixteen_bit, unsigned long value, unsigned long mode, DAEstatus &status)
Definition: isisdae.cpp:1790
const CRPTProxy & crpt
int getMonitorIntegral(long monitor, long period, float t_low, float t_high, long &integral, DAEstatus &status)
std::vector< float > fsetpoint_spread
per period
Definition: selogger.h:79
#define MAX_MONITORING_PAR
Definition: isiscrpt.h:448
boost::array< PERIOD, ISISCRPT_MAX_PERIOD > period
Definition: isiscrpt.h:258
int crat[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:307
void setup(const ISISCRPT_STRUCT *crpt, ISISDAE *dae, int run_number_digits, DAEstatus &status)
int endRun(DAEstatus &status)
SELOGGER_API int __stdcall se_get_measurement_first_run(const char *measurement_id, long &run_number)
Definition: selogger.cpp:974
int md5sumString(const void *buffer, int len, unsigned char *md5sum, DAEstatus &status)
Definition: icputils.cpp:277
int * spec
Definition: isisraw.h:275
float good_uamph
total up to last pause
Definition: isiscrpt.h:162
time_t icp_start_time
Definition: isiscrpt.h:244
int getUAmpHAllPeriods(float *good_uamph, float *raw_uamph, int n, DAEstatus &status)
int pauseRunMain(bool refresh_cache, DAEstatus &dstatus)
float theta
Definition: DetectorFile.h:16
isis32_t check(DAEstatus &status)
Definition: isisdae.cpp:691
float getRawUAmpHours(DAEstatus &status)
Definition: isisdae.cpp:1557
int updateCRPTWithSEandSaveToFile(CRPTProxy &crpt, const std::string &raw_filename, const std::string &nexus_filename, DAEstatus &dstatus)
isisraw_async_t(const CRPTProxy &crpt_, const char *filename_, ISISinstrumentControl *icp_, DAEstatus &status_)
static std::string m_instrument_parameter_map_file
bool isInitialised()
Definition: isiscrpt.h:501
void skippedEntity(const Poco::XML::XMLString &name)
double scale
Definition: isiscrpt.h:184
SELOGGER_API int __stdcall se_get_blocks(int run_number, time_t ref_time, seblock_map_t &blocks)
Definition: selogger.cpp:1060
#define FAC_TCB
float getGoodUAmpHours(DAEstatus &status)
Definition: isisdae.cpp:1552
SELOGGER_API int __stdcall se_set_run_state(int run_number, const char *state, int is_start)
Definition: selogger.cpp:744
int beginRunMain(DAEstatus &status)
int beginRunMainEx(bool start_paused, bool delayed_start, long period, DAEstatus &status)
#define LOG_INFORMATION(__arg)
Definition: IsisBase.h:44
int timr_file[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:314
int t_ntc1
Definition: isisraw.h:302
float getBeamCurrent(DAEstatus &status)
boost::signals2::connection registerOnRunStateChange(boost::function< void(BSTR)> func)
#define ISISCRPT_MAX_PERIOD
Definition: isiscrpt.h:19
void reportImmediately(bool value)
Definition: DAEstatus.h:162
char sample_type[80]
Definition: isiscrpt.h:417
float getCurrentPeriodGoodUAmpH(DAEstatus &status)
Poco::Mutex & getDataLockRef()
Definition: CRPTProxy.h:286
unsigned lastread_nano
Definition: selogger.h:125
DAEreport_func_t * m_report_func
int doneAsync()
called by async worker thread when it has completed its work
int changePeriod(int period, int daq_period, DAEstatus &status)
Definition: isisdae.cpp:221
bool isEventSpectrum(int spec) const
Definition: isiscrpt.h:821
char measurement_type[ICP_NAME_LEN]
Definition: isiscrpt.h:439
char raw_units[64]
Definition: isiscrpt.h:178
TCBRANGE tcr[ISISCRPT_MAX_NTRG][ISISCRPT_MAX_TCR]
Definition: isiscrpt.h:338
boost::array< int, ISISCRPT_MAX_NTRG > ntc
number of time channels per CRPT time regime
Definition: isiscrpt.h:346
SELOGGER_API int __stdcall se_clear_values(int run_start, int run_finish)
Definition: selogger.cpp:1040
float monitor_range[ISISCRPT_MAX_MONITOR][2]
Definition: isiscrpt.h:299
int * mpos
Definition: isisraw.h:292
int fillWithTestPattern(unsigned long pattern, DAEstatus &status)
Definition: isisdae.cpp:1927
float count_rate
Definition: isiscrpt.h:385
bool usingEventMode() const
Definition: isiscrpt.h:858
boost::array< int, ISISCRPT_MAX_DC > dae2highspec
length ndetcard
Definition: isiscrpt.h:327
void handleNotification(ICPNotification *pNf)
int getMEventsPeriod(double &mevents, int period, DAEstatus &status)
int VMEWriteArray(unsigned long card_id, unsigned long card_address, isisU32_t *values, unsigned long num_values, DAEstatus &status)
void beamCurrentTimerCallback(Poco::Timer &t)
time_t duration
Definition: isiscrpt.h:257
int evaluateExpression(std::map< std::string, double > &values, const std::string &expression, double &result, DAEstatus &status)
std::map< std::string, parameter_t > parameter_map_t
Definition: CRPTProxy.h:248
ISISCRPT_STRUCT * CRPT()
Definition: CRPTProxy.h:348
char user_name[ISISCRPT_USER_NAME_LEN+1]
Definition: isiscrpt.h:353
int updateUserDetailsFromFile(const char *filename, DAEstatus &status)
boost::array< int, ISISCRPT_MAX_DETECTOR > spec_to_crpt_offset
maps spectrum number to offset in raw data of crpt
Definition: isiscrpt.h:317
char inst_name[ISISCRPT_INST_LEN+1]
Definition: isiscrpt.h:351
void processingInstruction(const Poco::XML::XMLString &target, const Poco::XML::XMLString &data)
static int updateSampleParametersFromFile(const char *filename, DAEstatus &status)
int readDataDaeTable(const char *filename, DAEstatus &status)
void zeroUsedRawData(DAEstatus &status)
Definition: CRPTProxy.h:335
#define LV_NUM_TIME_REGIMES
number of time regimes settable in labview DAE control Vi
bool valid
Definition: isiscrpt.h:202
int crptTR(int tr) const
Definition: isiscrpt.h:756
const std::string & timeDiffLog() const
Definition: CRPTProxy.h:291
int ts
1 for ts1, 2 for ts2
Definition: isiscrpt.h:191
boost::array< int, ISISCRPT_MAX_DC > dae2cardmode
-1 unused, 0 histogram, 1 event. length ndetcard
Definition: isiscrpt.h:323
isisU32_t sumAllHistogramMemory(DAEstatus &status)
Definition: isisdae.cpp:1323
isisU32_t total_ppp_low
Definition: isiscrpt.h:284
float t_high
Definition: isiscrpt.h:222
char lvxml_update[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:433
void setLoggerName(const std::string &logger_name)
Definition: IsisBase.h:17
char sample_id[ICP_NAME_LEN]
Definition: isiscrpt.h:440
SELOGGER_API int __stdcall se_log_value_async(long run_number, const char *source, const char *iso_time, const char *block_name, const char *block_value)
Definition: selogger.cpp:567
char sample_orientation[256]
Definition: isiscrpt.h:396
boost::array< int, ISISCRPT_MAX_DETECTOR > spec_to_index
maps spectrum number to index into spec,udet,timr etc arrays in crpt
Definition: isiscrpt.h:316
int getRawPPPUpper(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1038
int writeData(const char *data_name, const std::vector< T > &value)
Definition: nexuswriter.h:35
int setFrameSync(FrameSync fs, int muon_pulse, DAEstatus &status)
Definition: isisdae.cpp:1491
int changePeriodWhileRunning(int period, bool pause_first, DAEstatus &status)
static const char * STR0(const char *str, const char *value="UNSPECIFIED")
Monitoring monitoring
Definition: isiscrpt.h:472
int data_bytes
Definition: isiscrpt.h:183
bool m_nexus_files
produce a nexus file. If m_vms_raw_files is true, it is log only. If false, it has data too ...
static std::string m_instrument_xml_file
static int writeISISNeXus(NeXusWriter &nxwriter, const CRPTProxy &crpt, const char *filename, bool logs_only, const seblock_map_t &blocks, const std::string &events_nxfile, DAEstatus &dstatus)
int updateHardwarePeriodsXML(const std::string &periods_xml, DAEstatus &status)
int RCretry(const char *name, boost::function< int(ISISinstrumentControl *, DAEstatus &)> func, DAEstatus &status)
float end
Definition: isiscrpt.h:131
int requestEndRunAfterNextSequenceCompletes(DAEstatus &status)
Definition: isisdae.cpp:2062
this must have NO VIRTUAL FUNCTIONS as it is embedded inside the CRPT
Definition: icputils.h:222
void closeEventFiles(DAEstatus &status)
Definition: isisdae.cpp:872
#define VMS_RUN_MASK
need to wrap VMS run numbers to fit into 5 digits
Definition: isisraw.h:7
int changeUpdateSettingsXML(const std::string &update_xml, DAEstatus &status)
void getCurrentTimeAsFiletime(FILETIME &ft)
Definition: icputils.h:191
int programDAE1POSLUT(int crat[], int maxcrate, int modn[], int mpos[], int spec[], int ndet, int nper_daq, DAEstatus &status)
Definition: isisdae.cpp:365
RUNTABLE data_dae_table
Definition: isiscrpt.h:276
void setInstName(const std::string &comp_name)
Definition: isiscrpt.cpp:1068
int auto_save_last
Definition: isiscrpt.h:288
parameter_map_t & beamlineParameters()
Definition: CRPTProxy.h:293
int sendNagios(int status, const std::string &service, const std::string &message, DAEstatus &dstatus)
#define ISISCRPT_MAX_TIMECHANB
Definition: isiscrpt.h:17
char measurement_subid[ICP_NAME_LEN]
Definition: isiscrpt.h:438
void zeroEventRawData(DAEstatus &status)
Definition: CRPTProxy.cpp:487
float update_npratio_average
Definition: isiscrpt.h:425
char local_contact[ISISCRPT_USER_NAME_LEN+1]
Definition: isiscrpt.h:358
int readDAE1Spectrum(int dae1_spectrum, isisU32_t *buffer, int nbuffer, DAEstatus &status)
Definition: isisdae.cpp:498
long update_duration_period
Definition: isiscrpt.h:383
int programPeriodCard(PeriodType period_type, int nper, int nperseq_request, isisU32_t *outputs, isisU16_t *dwell_flags, isisU16_t *frames, int period_output_delay, DAEstatus &status)
Definition: isisdae.cpp:1710
isisU32_t update_total_ppp_low
Definition: isiscrpt.h:369
int flushCRPT(DAEstatus &status, bool flush_raw_data=false)
Definition: CRPTProxy.cpp:30
int getNPRatio(float *current, float *average, DAEstatus &status)
char instrument_geometry[5]
Definition: isiscrpt.h:401
float total_uamph
total up to last pause
Definition: isiscrpt.h:163
int addInfo(int facility, const std::string &text)
Definition: DAEstatus.cpp:86
int tcb_pulse_generator
Definition: isiscrpt.h:272
int setFrameSyncDelay(isisU32_t delay, DAEstatus &status)
Definition: isisdae.cpp:1501
int abortRun(DAEstatus &status)
int createLastrunFile(const CRPTProxy &crpt, DAEstatus &status)
static DWORD __stdcall writeISISRAWthread(void *arg)
float tcb_maxtime
Definition: isiscrpt.h:267
float aperture1
Definition: isiscrpt.h:408
FrameSync tcb_sync
Definition: isiscrpt.h:271
int parseSpectraRange(const std::string &spec_range, int &spec_from, int &spec_to)
Definition: icputils.cpp:338
int getHighestSpectrumNumber() const
Definition: isiscrpt.cpp:957
int resetSeverityToAtMost(int severity)
Definition: DAEstatus.cpp:167
void start()
float len2[ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:303
epics_thread_data_t m_epics_data
int setOptions(const std::string &options_xml, DAEstatus &status)
static int sqliteReportFunction(const DAEstatus_message &mess, void *arg)
int setBlockTable(const string_table_t &table, DAEstatus &status)
int getIntItem(const char *item_name, long &lVal, DAEstatus &status) const
Definition: isiscrpt.cpp:233
long isis32_t
Definition: isisvme_types.h:14
float ut[ISISCRPT_MAX_USER *ISISCRPT_MAX_DETECTOR]
Definition: isiscrpt.h:306
void onProgress(Poco::TaskProgressNotification *pNf)
time_t mod_time
Definition: isiscrpt.h:78
int getRealArrayItemSize(const char *item_name, int *dims_array, int &ndims, DAEstatus &status)
int setLogTimeChannelRange(int range_number, float start, float end, float step, DAEstatus &status)
#define ISISCRPT_MAX_USER
Definition: isiscrpt.h:18
int setUserParameters(long rbno, const string_table_t &table, DAEstatus &status)
int result()
Definition: DAEstatus.h:144
int spectrumNTC(int spec) const
Definition: isiscrpt.h:804
int getIntArrayItemSize(const char *item_name, int *dims_array, int &ndims, DAEstatus &status) const
Definition: isiscrpt.cpp:432
void addFileInputSource(int run_number, FileEventSourceInfo &info)
struct ISISCRPT_STRUCT::@9 icp_clock
int checkTestPattern(unsigned long pattern, DAEstatus &status)
int sendSMS(const std::string &phone, const std::string &message, DAEstatus &status)
Definition: icputils.cpp:569
std::map< int, std::vector< int > > dae2spec_map_t
Definition: isisdae.h:78
Poco::Util::Application * m_app
int addInfoVa(int facility, const char *format,...)
Definition: DAEstatus.cpp:91
int setTimeChannelRange(int range_number, int range_type, float start, float end, float step, DAEstatus &status)
uint32_t spectrumCRPTOffset(int spec, int daq_period) const
Definition: CRPTProxy.h:406
int daeTR(int tr) const
Definition: isiscrpt.h:749
char expression[ISISCRPT_MAX_LVXML_SIZE]
Definition: isiscrpt.h:454
time_t duration
total data collection time in periods (seconds)
Definition: isiscrpt.h:161
static int setStringParameter(const CRPTProxy::parameter_map_t &params, const seblock_map_t *se_blocks, const char *name, char *crpt_target, int size_crpt_target, bool null_terminate, DAEstatus &status)
int checkTestPatternAsync(unsigned long pattern, DAEstatus &status)
Definition: isisdae.cpp:1904
int getCurrentPeriodSequence(isisU32_t *period_sequence, DAEstatus &status)
Definition: isisdae.cpp:1764
const dae2spec_map_t & getDAE2Specmap() const
Definition: isisdae.h:80
double frameTimerDrift(DAEstatus &status)
frame timer drift (icp - dae)
Definition: isisdae.cpp:1507
int sumAllHistogramMemory(long &counts, DAEstatus &status)
int loadOrCreateCRPT(const std::string &crpt_file, const std::string &crpt_name, const std::string &crpt_data_file, const std::string &crpt_data_name, int crpt_data_size, ISISDAE::DAEType dae_type, const std::string &comp_name, boost::function< int(DAEstatus &)> readRecoveryFile, DAEstatus &status)
Definition: CRPTProxy.cpp:76
int VMEReadArray(unsigned long card_id, unsigned long card_address, isisU32_t *values, unsigned long num_values, DAEstatus &status)
Definition: isisdae.cpp:1873
int updateTCBXML(const std::string &status_xml, DAEstatus &status)
float beam_centre_y
Definition: isiscrpt.h:407
int getSpectrum(long spectrum_number, long period, double *time_array, double *signal_array, double *error_array, bool as_histogram, bool as_distribution, long &sum, DAEstatus &status)
int checkForNoncountingDetectors(const CRPTProxy &crpt, DAEstatus &dstatus)
the idea here is to look for any module (dim) that has no counts
boost::array< int, ISISCRPT_MAX_NTRG > nsp
number of spectra per CRPT time regime
Definition: isiscrpt.h:334
#define TCBRANGE_INC_T_2
dt/t^c=c
Definition: isiscrpt.h:123
int getCurrentHardwarePeriod(isisU32_t *period, DAEstatus &status)
Definition: isisdae.cpp:1597
int getCurrentDAQHardwarePeriod(isisU32_t *period, DAEstatus &status)
Definition: isisdae.cpp:1619
std::list< boost::signals2::connection > addGoodEventCallback(const EventCallbackSlotType &slot)
Definition: isisdae.h:265
char script_name[ICP_NAME_LEN]
Definition: isiscrpt.h:441
int * crat
Definition: isisraw.h:290
boost::array< int, ISISCRPT_MAX_DETECTOR > det_group
0 = monitor, else logical det number
Definition: isiscrpt.h:318
static int debugReportFunction(const DAEstatus_message &mess, void *arg)
static bool getBeamlogInt(Poco::XML::Document *pDoc, const std::string &path, int &value)
int getUpdateSettingsXML(const std::string &update_xml_in, std::string &update_xml_out, DAEstatus &status)
static bool getBeamlogFloat(Poco::XML::Document *pDoc, const std::string &path, float &value)
int update_num_polls
Definition: isiscrpt.h:373
boost::array< int, ISISCRPT_MAX_NTRG > spec_max
range of spectrum numbers in CRPT time regime
Definition: isiscrpt.h:336
int software_period
Definition: isiscrpt.h:250
int updateCRPTSpectraAllPeriods(long spec_start, int nspectra, DAEstatus &status)
int setVeto(const std::string &name, long enable, DAEstatus &status)
static int getSE(const CRPTProxy &crpt, seblock_map_t &blocks, DAEstatus &dstatus)
int getCharItem(const char *item_name, std::string &cvalue, DAEstatus &status)
void printComputerMemoryStats(DAEstatus &status)
Definition: icputils.cpp:1072
int spacePadCopy(char *output, const char *input, int output_size)
Definition: isiscrpt.cpp:127
boost::array< int, ISISCRPT_NUM_FC_VETO > fermi_chopper_width
in 20ns
Definition: isiscrpt.h:391
int muon_cerenkov_pulse
Definition: isiscrpt.h:402
#define ISISCRPT_MAX_TCR
Definition: isiscrpt.h:21
boost::array< int, ISISCRPT_MAX_DC > dae2cardtr
detector card DAE time regime (-1 if card not used), length ndetcard - individual spectra on card may...
Definition: isiscrpt.h:322
int sav_file_count
Definition: isiscrpt.h:363
int getMSModeVetoedFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1672
Poco::Net::HTTPServer * m_http_server
int compression_level
Definition: isiscrpt.h:480
XMLJournalHandler(int &first_run, int &last_run)
int writeRecoveryFile(DAEstatus &dstatus)
int getMonitoringXML(const std::string &monitor_xml_in, std::string &monitor_xml_out, DAEstatus &status)
int updateStatusXML(std::string &status_xml, DAEstatus &status)
int getTotalCounts(int64_t &counts, DAEstatus &status)
int getIntArrayItem(const char *item_name, long *larray, DAEstatus &status)
int getGoodFrames(isisU32_t *value, DAEstatus &status)
Definition: isisdae.cpp:1028
nagios_t nagios
Definition: isiscrpt.h:491
int updateSpecmapsFromDAE(const std::map< int, int > &trcn, DAEstatus &status)
SELOGGER_API int __stdcall se_log_values_async(long run_number, const char *source, const std::vector< std::string > &iso_times, const std::vector< std::string > &block_names, const std::vector< std::string > &block_values)
Definition: selogger.cpp:572
boost::array< monitoring_par, MAX_MONITORING_PAR > par_type
Definition: isiscrpt.h:452
time_t beam_off_time
Definition: isiscrpt.h:199
int fullTR(int index) const
Definition: isiscrpt.h:778
int resumeRun(DAEstatus &status)
DAEType
Definition: isisdae.h:63
float start
Definition: isiscrpt.h:130