source: trunk/FACT++/src/ratescan.cc@ 16791

Last change on this file since 16791 was 16785, checked in by tbretz, 12 years ago
Replaced kConfigured with kConfigured1 according to the recent change in the ftmctrl.
File size: 17.7 KB
Line 
1#include <valarray>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10
11#include "tools.h"
12
13#include "LocalControl.h"
14
15#include "HeadersFTM.h"
16#include "HeadersRateScan.h"
17
18namespace ba = boost::asio;
19namespace bs = boost::system;
20
21using namespace std;
22
23// ------------------------------------------------------------------------
24
25#include "DimDescriptionService.h"
26#include "DimState.h"
27
28// ------------------------------------------------------------------------
29
30class StateMachineRateScan : public StateMachineDim
31{
32private:
33 DimVersion fDim;
34
35 DimDescribedState fDimFTM;
36 DimDescribedService fDimData;
37 DimDescribedService fDimProc;
38
39 int fCounter;
40 int fCounterMax;
41
42 int fThreshold;
43 int fThresholdMin;
44 int fThresholdMax;
45 int fThresholdStep;
46 int fThresholdStepDyn;
47
48 double fRate;
49 double fRateBoard[40];
50 double fRatePatch[160];
51
52 double fOnTime;
53
54 uint64_t fStartTime;
55
56 float fResolution;
57
58 enum reference_t
59 {
60 kCamera,
61 kBoard,
62 kPatch
63 };
64
65 reference_t fReference;
66 uint16_t fReferenceIdx;
67
68 string fCommand;
69
70 void UpdateProc()
71 {
72 const array<uint32_t,3> v = {{ fThresholdMin, fThresholdMax, fThresholdStep }};
73 fDimProc.Update(v);
74 }
75
76 bool CheckEventSize(const EventImp &evt, size_t size)
77 {
78 if (size_t(evt.GetSize())==size)
79 return true;
80
81 if (evt.GetSize()==0)
82 return false;
83
84 ostringstream msg;
85 msg << evt.GetName() << " - Received event has " << evt.GetSize() << " bytes, but expected " << size << ".";
86 Fatal(msg);
87 return false;
88 }
89
90 int HandleTriggerRates(const EventImp &evt)
91 {
92 if (!CheckEventSize(evt, sizeof(FTM::DimTriggerRates)))
93 return GetCurrentState();
94
95 if (GetCurrentState()!=RateScan::State::kInProgress)
96 return GetCurrentState();
97
98 const FTM::DimTriggerRates &sdata = *static_cast<const FTM::DimTriggerRates*>(evt.GetData());
99
100 if (++fCounter<0)
101 return GetCurrentState();
102
103 if (fCounter==0)
104 {
105 fRate = 0;
106
107 memset(fRateBoard, 0, 40*sizeof(double));
108 memset(fRatePatch, 0, 160*sizeof(double));
109
110 fOnTime = 0;
111 return GetCurrentState();
112 }
113/*
114 if (sdata.fTriggerRate==0)
115 {
116 Message("Rate scan stopped due zero trigger rate.");
117 fThreshold = -1;
118 return;
119 }
120*/
121
122 fRate += sdata.fTriggerRate;
123 for (int i=0; i<40; i++)
124 fRateBoard[i] += sdata.fBoardRate[i];
125 for (int i=0; i<160; i++)
126 fRatePatch[i] += sdata.fPatchRate[i];
127
128 double reference = fRate;
129 if (fReference==kBoard)
130 reference = fRateBoard[fReferenceIdx];
131 if (fReference==kPatch)
132 reference = fRatePatch[fReferenceIdx];
133
134 fOnTime += sdata.fOnTime;
135
136 reference *= sdata.fElapsedTime;
137
138 if ((reference==0 || sqrt(reference)>fResolution*reference) && fCounter<fCounterMax)
139 {
140 ostringstream out;
141 out << "Triggers so far: " << reference;
142 if (reference>0)
143 out << " (" << sqrt(reference)/reference << ")";
144 Info(out);
145
146 return GetCurrentState();
147 }
148
149 const double time = sdata.fElapsedTime*fCounter;
150 const uint32_t th = fThreshold;
151
152 float data[2+3+1+40+160];
153 memcpy(data, &fStartTime, 8);
154 memcpy(data+2, &th, 4);
155 data[3] = time; // total elapsed time
156 data[4] = fOnTime/time; // relative on time
157 data[5] = fRate/fCounter;
158 for (int i=0; i<40; i++)
159 data[i+6] = fRateBoard[i]/fCounter;
160 for (int i=0; i<160; i++)
161 data[i+46] = fRatePatch[i]/fCounter;
162
163 ostringstream sout1, sout2, sout3;
164
165 sout1 << th << " " << data[5];
166 for (int i=0; i<200; i++)
167 sout2 << " " << data[i+6];
168 sout3 << " " << data[3] << " " << data[4];
169
170 Info(sout1.str());
171
172 ofstream fout("ratescan.txt", ios::app);
173 fout << sout1.str() << sout2.str() << sout3.str() << endl;
174
175 fDimData.setQuality(fCommand=="FTM_CONTROL/SET_THRESHOLD");
176 fDimData.setData(data, sizeof(data));
177 fDimData.Update();
178
179 fThreshold += fThresholdStep;
180
181 if (fCounter>=fCounterMax)
182 {
183 Message("Rate scan stopped due to timeout.");
184 //Dim::SendCommandNB("FTM_CONTROL/RESET_CONFIGURE");
185 return RateScan::State::kConnected;
186 }
187
188 if (fThreshold>fThresholdMax)
189 {
190 Message("Rate scan finished.");
191 //Dim::SendCommandNB("FTM_CONTROL/RESET_CONFIGURE");
192 return RateScan::State::kConnected;
193 }
194
195 // Does this need to be shifted upwards?
196 if (fCounter>1 && fThresholdStepDyn>0)
197 {
198 //const double scale = fCounter/reference/fResolution/fResolution;
199 //const double step = floor(scale*fThresholdStepDyn);
200
201 fThresholdStep = fCounter*fThresholdStepDyn;
202 }
203
204 //fCounter = -2; // FIXME: In principle one missed report is enough
205 fCounter = -1;
206
207 const int32_t cmd[2] = { -1, fThreshold };
208 Dim::SendCommandNB(fCommand.c_str(), cmd);
209
210 return GetCurrentState();
211 }
212
213 int Print() const
214 {
215 Out() << fDim << endl;
216 Out() << fDimFTM << endl;
217
218 return GetCurrentState();
219 }
220
221 int StartRateScan(const EventImp &evt, const string &command)
222 {
223 if (!CheckEventSize(evt, 12))
224 return kSM_FatalError;
225
226 fCommand = "FTM_CONTROL/"+command;
227
228 const int32_t step = evt.Get<int32_t>(8);
229
230 fThresholdMin = evt.Get<uint32_t>();
231 fThresholdMax = evt.Get<uint32_t>(4);
232 fThresholdStep = abs(step);
233
234 fThresholdStepDyn = step<0 ? -step : 0;
235
236 UpdateProc();
237
238 //Dim::SendCommand("FAD_CONTROL/SET_FILE_FORMAT", uint16_t(0));
239 Dim::SendCommandNB("FTM_CONTROL/CONFIGURE", string("ratescan"));
240
241 Message("Configuration for ratescan started.");
242
243 return RateScan::State::kConfiguring;
244 }
245
246 int HandleFtmStateChange(/*const EventImp &evt*/)
247 {
248 // ftmctrl connected to FTM
249 if (GetCurrentState()!=RateScan::State::kConfiguring)
250 return GetCurrentState();
251
252 if (fDimFTM.state()!=FTM::State::kConfigured1)
253 return GetCurrentState();
254
255 const int32_t data[2] = { -1, fThresholdMin };
256
257 Dim::SendCommandNB("FTM_CONTROL/RESET_CONFIGURE");
258 Dim::SendCommandNB(fCommand, data);
259
260 fThreshold = fThresholdMin;
261 fCounter = -2;
262
263 const Time now;
264 fStartTime = trunc(now.UnixTime());
265
266 ofstream fout("ratescan.txt", ios::app);
267 fout << "# ----- " << now << " (" << fStartTime << ") -----\n";
268 fout << "# Command: " << fCommand << '\n';
269 fout << "# Reference: ";
270 switch (fReference)
271 {
272 case kCamera: fout << "Camera"; break;
273 case kBoard: fout << "Board #" << fReferenceIdx; break;
274 case kPatch: fout << "Patch #" << fReferenceIdx; break;
275 }
276 fout << '\n';
277 fout << "# -----" << endl;
278
279 ostringstream msg;
280 msg << "Rate scan " << now << "(" << fStartTime << ") from " << fThresholdMin << " to ";
281 msg << fThresholdMax << " in steps of " << fThresholdStep;
282 msg << " started.";
283 Message(msg);
284
285 return RateScan::State::kInProgress;
286 }
287
288 int StopRateScan()
289 {
290 if (GetCurrentState()!=RateScan::State::kConfiguring && GetCurrentState()!=RateScan::State::kInProgress)
291 return GetCurrentState();
292
293 Dim::SendCommandNB("FTM_CONTROL/RESET_CONFIGURE");
294 Message("Rate scan manually stopped.");
295
296 return RateScan::State::kConnected;
297 }
298
299 int SetReferenceCamera()
300 {
301 fReference = kCamera;
302
303 return GetCurrentState();
304 }
305
306 int SetReferenceBoard(const EventImp &evt)
307 {
308 if (!CheckEventSize(evt, 4))
309 return kSM_FatalError;
310
311 if (evt.GetUInt()>39)
312 {
313 Error("SetReferenceBoard - Board index out of range [0;39]");
314 return GetCurrentState();
315 }
316
317 fReference = kBoard;
318 fReferenceIdx = evt.GetUInt();
319
320 return GetCurrentState();
321 }
322
323 int SetReferencePatch(const EventImp &evt)
324 {
325 if (!CheckEventSize(evt, 4))
326 return kSM_FatalError;
327
328 if (evt.GetUInt()>159)
329 {
330 Error("SetReferencePatch - Patch index out of range [0;159]");
331 return GetCurrentState();
332 }
333
334 fReference = kPatch;
335 fReferenceIdx = evt.GetUInt();
336
337 return GetCurrentState();
338 }
339
340 int ChangeStepSize(const EventImp &evt)
341 {
342 if (!CheckEventSize(evt, 4))
343 return kSM_FatalError;
344
345 fThresholdStep = evt.Get<uint32_t>();
346
347 ostringstream msg;
348 msg << "New step size " << fThresholdStep;
349 Info(msg);
350
351 UpdateProc();
352
353 return GetCurrentState();
354 }
355
356 int ChangeMaximum(const EventImp &evt)
357 {
358 if (!CheckEventSize(evt, 4))
359 return kSM_FatalError;
360
361 fThresholdMax = evt.Get<uint32_t>();
362
363 return GetCurrentState();
364 }
365
366 int Execute()
367 {
368 if (!fDim.online())
369 return RateScan::State::kDimNetworkNA;
370
371 // All subsystems are not connected
372 if (fDimFTM.state()<FTM::State::kConnected)
373 return RateScan::State::kDisconnected;
374
375 // ftmctrl connected to FTM
376 if (GetCurrentState()<=RateScan::State::kDisconnected)
377 return RateScan::State::kConnected;
378
379 return GetCurrentState();
380 }
381
382public:
383 StateMachineRateScan(ostream &out=cout) : StateMachineDim(out, "RATE_SCAN"),
384 fDimFTM("FTM_CONTROL"),
385 fDimData("RATE_SCAN/DATA", "X:1;I:1;F:1;F:1;F:1;F:40;F:160",
386 "|Id[s]:Start time used to identify measurement (UnixTime)"
387 "|Threshold[dac]:Threshold in DAC counts"
388 "|ElapsedTime[s]:Real elapsed time"
389 "|RelOnTime[ratio]:Relative on time"
390 "|TriggerRate[Hz]:Camera trigger rate"
391 "|BoardRate[Hz]:Board trigger rates"
392 "|PatchRate[Hz]:Patch trigger rates"),
393 fDimProc("RATE_SCAN/PROCESS_DATA", "I:1;I:1;I:1",
394 "Rate scan process data"
395 "|min[DAC]:Value at which scan was started"
396 "|max[DAC]:Value at which scan will end"
397 "|step[DAC]:Step size for scan"),
398 fThreshold(-1), fReference(kCamera), fReferenceIdx(0)
399 {
400 // ba::io_service::work is a kind of keep_alive for the loop.
401 // It prevents the io_service to go to stopped state, which
402 // would prevent any consecutive calls to run()
403 // or poll() to do nothing. reset() could also revoke to the
404 // previous state but this might introduce some overhead of
405 // deletion and creation of threads and more.
406
407 fDim.Subscribe(*this);
408 fDimFTM.Subscribe(*this);
409 fDimFTM.SetCallback(bind(&StateMachineRateScan::HandleFtmStateChange, this));
410
411 Subscribe("FTM_CONTROL/TRIGGER_RATES")
412 (bind(&StateMachineRateScan::HandleTriggerRates, this, placeholders::_1));
413
414 // State names
415 AddStateName(RateScan::State::kDimNetworkNA, "DimNetworkNotAvailable",
416 "The Dim DNS is not reachable.");
417
418 AddStateName(RateScan::State::kDisconnected, "Disconnected",
419 "The Dim DNS is reachable, but the required subsystems are not available.");
420
421 AddStateName(RateScan::State::kConnected, "Connected",
422 "All needed subsystems are connected to their hardware, no action is performed.");
423
424 AddStateName(RateScan::State::kConfiguring, "Configuring",
425 "Waiting for FTM to get 'Configured'.");
426
427 AddStateName(RateScan::State::kInProgress, "InProgress",
428 "Rate scan in progress.");
429
430 AddEvent("START_THRESHOLD_SCAN", "I:3", RateScan::State::kConnected)
431 (bind(&StateMachineRateScan::StartRateScan, this, placeholders::_1, "SET_THRESHOLD"))
432 ("Start rate scan for the threshold in the defined range"
433 "|min[int]:Start value in DAC counts"
434 "|max[int]:Limiting value in DAC counts"
435 "|step[int]:Single step in DAC counts");
436
437 AddEvent("START_N_OUT_OF_4_SCAN", "I:3", RateScan::State::kConnected)
438 (bind(&StateMachineRateScan::StartRateScan, this, placeholders::_1, "SET_N_OUT_OF_4"))
439 ("Start rate scan for N-out-of-4 in the defined range"
440 "|min[int]:Start value in DAC counts"
441 "|max[int]:Limiting value in DAC counts"
442 "|step[int]:Single step in DAC counts");
443
444 AddEvent("CHANGE_STEP_SIZE", "I:1", RateScan::State::kInProgress)
445 (bind(&StateMachineRateScan::ChangeStepSize, this, placeholders::_1))
446 ("Change the step size during a ratescan in progress"
447 "|step[int]:Single step in DAC counts");
448
449 AddEvent("CHANGE_MAXIMUM", "I:1", RateScan::State::kInProgress)
450 (bind(&StateMachineRateScan::ChangeMaximum, this, placeholders::_1))
451 ("Change the maximum limit during a ratescan in progress"
452 "|max[int]:Limiting value in DAC counts");
453
454 AddEvent("STOP", RateScan::State::kConfiguring, RateScan::State::kInProgress)
455 (bind(&StateMachineRateScan::StopRateScan, this))
456 ("Stop a ratescan in progress");
457
458 AddEvent("SET_REFERENCE_CAMERA", RateScan::State::kDimNetworkNA, RateScan::State::kDisconnected, RateScan::State::kConnected)
459 (bind(&StateMachineRateScan::SetReferenceCamera, this))
460 ("Use the camera trigger rate as reference for the reolution");
461 AddEvent("SET_REFERENCE_BOARD", "I:1", RateScan::State::kDimNetworkNA, RateScan::State::kDisconnected, RateScan::State::kConnected)
462 (bind(&StateMachineRateScan::SetReferenceBoard, this, placeholders::_1))
463 ("Use the given board trigger-rate as reference for the reolution"
464 "|board[idx]:Index of the board (4*crate+board)");
465 AddEvent("SET_REFERENCE_PATCH", "I:1", RateScan::State::kDimNetworkNA, RateScan::State::kDisconnected, RateScan::State::kConnected)
466 (bind(&StateMachineRateScan::SetReferenceBoard, this, placeholders::_1))
467 ("Use the given patch trigger-rate as reference for the reolution"
468 "|patch[idx]:Index of the patch (360*crate+36*board+patch)");
469
470 AddEvent("PRINT")
471 (bind(&StateMachineRateScan::Print, this))
472 ("");
473 }
474
475 int EvalOptions(Configuration &conf)
476 {
477 fCounterMax = conf.Get<uint16_t>("max-wait");
478 fResolution = conf.Get<double>("resolution");
479
480 return -1;
481 }
482};
483
484// ------------------------------------------------------------------------
485
486#include "Main.h"
487
488template<class T>
489int RunShell(Configuration &conf)
490{
491 return Main::execute<T, StateMachineRateScan>(conf);
492}
493
494void SetupConfiguration(Configuration &conf)
495{
496 po::options_description control("Rate scan options");
497 control.add_options()
498 ("max-wait", var<uint16_t>(150), "The maximum number of seconds to wait to get the anticipated resolution for a point.")
499 ("resolution", var<double>(0.05) , "The minimum resolution required for a single data point.")
500 ;
501
502 conf.AddOptions(control);
503}
504
505/*
506 Extract usage clause(s) [if any] for SYNOPSIS.
507 Translators: "Usage" and "or" here are patterns (regular expressions) which
508 are used to match the usage synopsis in program output. An example from cp
509 (GNU coreutils) which contains both strings:
510 Usage: cp [OPTION]... [-T] SOURCE DEST
511 or: cp [OPTION]... SOURCE... DIRECTORY
512 or: cp [OPTION]... -t DIRECTORY SOURCE...
513 */
514void PrintUsage()
515{
516 cout <<
517 "The ratescan program is a tool for automation of rate scans.\n"
518 "\n"
519 "Usage: ratescan [-c type] [OPTIONS]\n"
520 " or: ratescan [OPTIONS]\n";
521 cout << endl;
522}
523
524void PrintHelp()
525{
526 Main::PrintHelp<StateMachineRateScan>();
527
528 /* Additional help text which is printed after the configuration
529 options goes here */
530
531 /*
532 cout << "bla bla bla" << endl << endl;
533 cout << endl;
534 cout << "Environment:" << endl;
535 cout << "environment" << endl;
536 cout << endl;
537 cout << "Examples:" << endl;
538 cout << "test exam" << endl;
539 cout << endl;
540 cout << "Files:" << endl;
541 cout << "files" << endl;
542 cout << endl;
543 */
544}
545
546int main(int argc, const char* argv[])
547{
548 Configuration conf(argv[0]);
549 conf.SetPrintUsage(PrintUsage);
550 Main::SetupConfiguration(conf);
551 SetupConfiguration(conf);
552
553 if (!conf.DoParse(argc, argv, PrintHelp))
554 return 127;
555
556 //try
557 {
558 // No console access at all
559 if (!conf.Has("console"))
560 {
561// if (conf.Get<bool>("no-dim"))
562// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
563// else
564 return RunShell<LocalStream>(conf);
565 }
566 // Cosole access w/ and w/o Dim
567/* if (conf.Get<bool>("no-dim"))
568 {
569 if (conf.Get<int>("console")==0)
570 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
571 else
572 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
573 }
574 else
575*/ {
576 if (conf.Get<int>("console")==0)
577 return RunShell<LocalShell>(conf);
578 else
579 return RunShell<LocalConsole>(conf);
580 }
581 }
582 /*catch (std::exception& e)
583 {
584 cerr << "Exception: " << e.what() << endl;
585 return -1;
586 }*/
587
588 return 0;
589}
Note: See TracBrowser for help on using the repository browser.