JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwBlinder.cc
Go to the documentation of this file.
1/*!
2 * \file QwBlinder.cc
3 * \brief A class for blinding data, adapted from G0 blinder class.
4 *
5 * \author Peiqing Wang
6 * \date 2010-04-14
7 */
8
9#include "QwBlinder.h"
10
11// System headers
12#include <string>
13#include <limits>
14
15#include "TMath.h"
16
17// Qweak headers
18#include "QwLog.h"
19#ifdef __USE_DATABASE__
20#include "QwParitySchema.h"
21#include "QwParityDB.h"
22#endif // __USE_DATABASE__
23#include "QwVQWK_Channel.h"
24#include "QwParameterFile.h"
25
26/// Run table aliases for seed query
27/// (these types must be defined outside function scope)
28#ifdef __USE_DATABASE__
29#ifdef __USE_SQLPP11__
30SQLPP_ALIAS_PROVIDER(run_first);
31SQLPP_ALIAS_PROVIDER(run_last);
32#endif // __USE_SQLPP11__
33#ifdef __USE_SQLPP23__
34SQLPP_CREATE_NAME_TAG(run_first);
35SQLPP_CREATE_NAME_TAG(run_last);
36#endif // __USE_SQLPP23__
37#endif // __USE_DATABASE__
38
39/// Blinder event counter indices
55
56
57// String names of the blinding and Wien status values
58const TString QwBlinder::fStatusName[4] = {"Indeterminate", "NotBlindable",
59 "Blindable", "BlindableFail"};
60
61// Maximum blinding asymmetry for additive blinding
62const Double_t QwBlinder::kDefaultMaximumBlindingAsymmetry = 0.150; // ppm
63const Double_t QwBlinder::kDefaultMaximumBlindingFactor = 0.0; // [fraction]
64
65// Default seed, associated with seed_id 0
66const TString QwBlinder::kDefaultSeed = "Default seed, should not be used!";
67
68//**************************************************//
70 options.AddOptions("Blinder")("blinder.force-target-blindable", po::value<bool>()->default_bool_value(false),
71 "Forces the blinder to interpret the target as being in a blindable position");
72 options.AddOptions("Blinder")("blinder.force-target-out", po::value<bool>()->default_bool_value(false),
73 "Forces the blinder to interpret the target position as target-out");
74 options.AddOptions("Blinder")("blinder.beam-current-threshold", po::value<double>()->default_value(2.5),
75 "Beam current in microamps below which data will not be blinded");
76}
77
78
79/**
80 * Default constructor using optional database connection and blinding strategy
81 * @param blinding_strategy Blinding strategy
82 */
87 //
93 //
95 fBeamIsPresent(kFALSE),
96 fBlindingStrategy(blinding_strategy),
97 fBlindingOffset(0.0),
99 fBlindingFactor(1.0),
100 //
103{
104 // Set up the blinder with seed_id 0
106 fSeedID = 0;
107
108 fCREXTargetIndex = -1;
109
110 Int_t tgt_index;
111
112 // Read parameter file
113 QwParameterFile blinder("blinder.map");
114 if (blinder.FileHasVariablePair("=", "seed", fSeed))
115 QwVerbose << "Using seed from file: " << fSeed << QwLog::endl;
116 if (blinder.FileHasVariablePair("=", "max_asymmetry", fMaximumBlindingAsymmetry))
117 QwVerbose << "Using blinding box: " << fMaximumBlindingAsymmetry << " ppm" << QwLog::endl;
118 if (blinder.FileHasVariablePair("=", "max_factor", fMaximumBlindingFactor))
119 QwVerbose << "Using blinding factor: " << fMaximumBlindingFactor << QwLog::endl;
120 if (blinder.FileHasVariablePair("=", "crex_target_index", tgt_index)){
121 if (tgt_index>=kCREXTgtIndexMin && tgt_index<=kCREXTgtIndexMax){
122 fCREXTargetIndex = tgt_index;
123 } else {
124 QwError << "Invalid CREX target index for blindable events! Exiting!"
125 << QwLog::endl;
126 exit(100);
127 }
128 }
129 QwMessage << "What is the blindable CREX target position (-1 means we're using the PREX positions)? " << fCREXTargetIndex << QwLog::endl;
131 fSeed.Prepend(TString("[Using CREX positions!] "));
132 QwMessage << "Updated the seed string: " << fSeed << QwLog::endl;
133 }
134 std::string strategy;
135 if (blinder.FileHasVariablePair("=", "strategy", strategy)) {
136 std::transform(strategy.begin(), strategy.end(), strategy.begin(), ::tolower);
137 QwVerbose << "Using blinding strategy from file: " << strategy << QwLog::endl;
138 if (strategy == "disabled") fBlindingStrategy = kDisabled;
139 else if (strategy == "additive") fBlindingStrategy = kAdditive;
140 else if (strategy == "multiplicative") fBlindingStrategy = kMultiplicative;
141 else if (strategy == "additivemultiplicative") fBlindingStrategy = kAdditiveMultiplicative;
142 else QwWarning << "Blinding strategy " << strategy << " not recognized" << QwLog::endl;
143 }
144
145 std::string spin_direction;
146 if (blinder.FileHasVariablePair("=", "force-spin-direction", spin_direction)) {
147 std::transform(spin_direction.begin(), spin_direction.end(), spin_direction.begin(), ::tolower);
148 if (spin_direction == "spin-forward"){
149 QwWarning << "QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-forward" << QwLog::endl;
151 SetIHWPPolarity(+1);
152 fSpinDirectionForced = kTRUE;
153 } else if (spin_direction == "spin-backward"){
154 QwWarning << "QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-backward" << QwLog::endl;
156 SetIHWPPolarity(+1);
157 fSpinDirectionForced = kTRUE;
158 } else if (spin_direction == "spin-vertical"){
159 QwWarning << "QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-vertical" << QwLog::endl;
161 SetIHWPPolarity(+1);
162 fSpinDirectionForced = kTRUE;
163 } else if (spin_direction == "spin-horizontal"){
164 QwWarning << "QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-horizontal" << QwLog::endl;
166 SetIHWPPolarity(+1);
167 fSpinDirectionForced = kTRUE;
168 } else {
169 QwError << "QwBlinder::QwBlinder: Unrecognized option given to force-spin-direction in blinder.map; "
170 << "force-spin-direction==" << spin_direction << ". Exit and correct the file."
171 << QwLog::endl;
172 exit(10);
173 }
174 }
175
176 std::string target_type;
177 if (blinder.FileHasVariablePair("=", "force-target-type", target_type)) {
178 std::transform(target_type.begin(), target_type.end(), target_type.begin(), ::tolower);
179 if (target_type == "target-blindable"){
180 QwWarning << "QwBlinder::QwBlinder: Target position forced with force-target-type==target-blindable" << QwLog::endl;
181 fTargetPositionForced = kTRUE;
183 } else if (target_type == "target-out"){
184 QwWarning << "QwBlinder::QwBlinder: Target position forced with force-target-type==target-out" << QwLog::endl;
185 fTargetPositionForced = kTRUE;
187 } else {
188 QwError << "QwBlinder::QwBlinder: Unrecognized option given to force-target-type in blinder.map; "
189 << "force-target-type==" << target_type << ". Exit and correct the file."
190 << QwLog::endl;
191 exit(10);
192 }
193 }
194
195 // Initialize blinder from seed
196 InitBlinders(0);
197 // Calculate set of test values
198 InitTestValues(10);
199
201 if (fWienMode == kWienForward){
203 } else if (fWienMode == kWienBackward){
205 } else {
206 fBlindingOffset = 0.0;
207 }
208 }
209
210 // Resize counters
213}
214
215
216/**
217 * Destructor checks the validity of the blinding and unblinding
218 */
220{
221 // Check the blinded values
223}
224
225
226/**
227 * Update the blinder status with new external information
228 * @param options Qweak option handler
229 */
231{
232 if (options.GetValue<bool>("blinder.force-target-out")
233 && options.GetValue<bool>("blinder.force-target-blindable")){
234 QwError << "QwBlinder::ProcessOptions: Both blinder.force-target-blindable and blinder.force-target-out are set. "
235 << "Only one can be in force at one time. Exit and choose one option."
236 << QwLog::endl;
237 exit(10);
238 } else if (options.GetValue<bool>("blinder.force-target-blindable")){
239 QwWarning << "QwBlinder::ProcessOptions: Target position forced with blinder.force-target-blindable." << QwLog::endl;
240 fTargetPositionForced = kTRUE;
242 } else if (options.GetValue<bool>("blinder.force-target-out")){
243 QwWarning << "QwBlinder::ProcessOptions: Target position forced with blinder.force-target-out." << QwLog::endl;
244 fTargetPositionForced = kTRUE;
246 }
247
248 fBeamCurrentThreshold = options.GetValue<double>("blinder.beam-current-threshold");
249}
250
251#ifdef __USE_DATABASE__
252/**
253 * Update the blinder status with new external information
254 *
255 * @param db Database connection
256 */
257void QwBlinder::Update(QwParityDB* db)
258{
259 // Update the seed ID then tell us if it has changed.
260 UInt_t old_seed_id = fSeedID;
261 ReadSeed(db);
262 // If the blinding seed has changed, re-initialize the blinder
263 if (fSeedID != old_seed_id ||
264 (fSeedID==0 && fSeed!=kDefaultSeed) ) {
265 QwWarning << "Changing blinder seed to " << fSeedID
266 << " from " << old_seed_id << "." << QwLog::endl;
268 InitTestValues(10);
269 }
270}
271#endif // __USE_DATABASE__
272
273/**
274 * Update the blinder status using a random number
275 */
277{
278 // Update the seed ID then tell us if it has changed.
279 UInt_t old_seed_id = fSeedID;
281 // Force the target to blindable, Wien to be forward,
282 // and IHWP polarity to be +1
285 SetIHWPPolarity(+1);
286 // If the blinding seed has changed, re-initialize the blinder
287 if (fSeedID != old_seed_id ||
288 (fSeedID==0 && fSeed!=kDefaultSeed) ) {
289 QwWarning << "Changing blinder seed to " << fSeedID
290 << " from " << old_seed_id << "." << QwLog::endl;
292 InitTestValues(10);
293 }
294}
295
296/**
297 * Update the blinder status with new external information
298 *
299 * @param detectors Current subsystem array
300 */
302{
303 static QwVQWK_Channel q_targ("q_targ");
305 // Check for the target blindability flag
306
307
308 // Check that the current on target is above acceptable limit
309 Bool_t tmp_beam = kFALSE;
310 // if (detectors.RequestExternalValue(q_targ.GetElementName(), &q_targ)) {
311 if (detectors.RequestExternalValue("q_targ", &q_targ)) {
312 if (q_targ.GetValue() > fBeamCurrentThreshold){
313 // std::cerr << "q_targ.GetValue()=="
314 // << q_targ.GetValue() << std::endl;
315 tmp_beam = kTRUE;
316 }
317 }
318 fBeamIsPresent &= tmp_beam;
319 }
320}
321
322/**
323 * Update the blinder status with new external information
324 *
325 * @param epics Current EPICS event
326 */
328{
329 // Check for the target information
330 // Position:
331 // QWtgt_name == "HYDROGEN-CELL" || QWTGTPOS > 350
332 // Temperature:
333 // QWT_miA < 22.0 && QWT_moA < 22.0
334 // Pressure:
335 // QW_PT3 in [20,35] && QW_PT4 in [20,35]
337 //TString position = epics.GetDataString("QWtgt_name");
338 Double_t tgt_pos = epics.GetDataValue("pcrex90BDSPOS.VAL");
339 QwDebug << "Target parameters used by the blinder: "
340 // << "QWtgt_name=" << position << " "
341 << "QWTGTPOS=" << tgt_pos << " "
342 << QwLog::endl;
343
344 //
345 // **** Target index 1: Beginning of CREX
346 if (fCREXTargetIndex==1 &&
347 (tgt_pos>14.5e6 && tgt_pos<18.0e6) ){
348 // Calcium-48 target position
350
351 } else if (fCREXTargetIndex==1 &&
352 ( (tgt_pos>-1.0e3 && tgt_pos<14.5e6)
353 || (tgt_pos>18.0e6 && tgt_pos<61.e6) ) ){
354 // Reasonable non-calcium-48 target positions
356
357
358 //
359 // **** Target index 2: After 20January change in target location
360 } else if (fCREXTargetIndex==2 &&
361 (tgt_pos>11.5e6 && tgt_pos<14.5e6) ){
362 // Calcium-48 target position (old Ca-40 position)
364
365 } else if (fCREXTargetIndex==2 &&
366 ( (tgt_pos>-1.0e3 && tgt_pos<11.5e6)
367 || (tgt_pos>14.5e6 && tgt_pos<61.e6) ) ){
368 // Reasonable non-calcium-48 target positions
370
371 //
372 // **** Target index -1: These are the PREX positions
373 } else if ( fCREXTargetIndex==-1 &&
374 (/* Target positions before 1 August 2019.*/
375 ( (tgt_pos > 3e6 && tgt_pos < 6.9e6)
376 || (tgt_pos > 7.3e6 && tgt_pos < 7.7e6))
377 /* Target positions after 1 August 2019.*/
378 ||( (tgt_pos>30.e6 && tgt_pos<69e6)
379 || (tgt_pos>73e6 && tgt_pos<78e6)
380 ) ) ){
381 // Lead-208 target positions
383
384 } else if ( fCREXTargetIndex==-1 &&
385 (/* Target positions before 1 August 2019.*/
386 ((tgt_pos > -1e3 && tgt_pos < 3e6)
387 || (tgt_pos > 6.8e6 && tgt_pos < 7.2e6)
388 || (tgt_pos > 7.7e6 && tgt_pos < 10e6))
389 /* Target positions after 1 August 2019.*/
390 || ( (tgt_pos>17e6 && tgt_pos<30e6)
391 || (tgt_pos>69e6 && tgt_pos<73e6)
392 || (tgt_pos>78e6 && tgt_pos<90e6)
393 )
394 ) ){
395 // Positions are not lead-208 targets.
397
398 } else {
400 QwWarning << "Target parameters used by the blinder are indeterminate: "
401 // << "QWtgt_name=" << position << " "
402 << "QWTGTPOS=" << tgt_pos << " "
403 << QwLog::endl;
404 } // End of tests on target positions
405 }
406 // Check for the beam polarity information
407 // IGL1I00DI24_24M Beam Half-wave plate Read(off=out)
408 //
411 // Use the EPICS class functions to determine the
412 // Wien mode and IHWP polarity.
415
416 if (fWienMode == kWienForward){
418 } else if (fWienMode == kWienBackward){
420 } else {
421 fBlindingOffset = 0.0;
422 }
423 }
424}
425
426/*!-----------------------------------------------------------
427 *------------------------------------------------------------
428 * Function to read the seed in from the database.
429 *
430 * Parameters:
431 *
432 * Return: Int_t
433 *
434 *------------------------------------------------------------
435 *------------------------------------------------------------*/
436#ifdef __USE_DATABASE__
437Int_t QwBlinder::ReadSeed(QwParityDB* db)
438{
439 // Return unchanged if no database specified
440 if (! db) {
441 QwWarning << "QwBlinder::ReadSeed(): No database specified" << QwLog::endl;
442 fSeedID = 0;
443 fSeed = "Default seed, No database specified";
444 return 0;
445 }
446 if (! db->AllowsReadAccess()){
447 QwDebug << "QwBlinder::ReadSeed(): Database access is turned off. Don't update the blinder." << QwLog::endl;
448 return 0;
449 }
450
451 // Try to connect to the database
452 try {
453 auto c = db->GetScopedConnection();
454
455 QwError << "QwBlinder::ReadSeed db->GetRunNumber() returns "
456 << db->GetRunNumber() << QwLog::endl;
457
458 // Convert to sqlpp11 query with JOINs
459 QwParitySchema::seeds seeds{};
460 QwParitySchema::run first_run{};
461 QwParitySchema::run last_run{};
462
463 // Create aliases for the run table
464 auto rf_alias = first_run.as(run_first);
465 auto rl_alias = last_run.as(run_last);
466 auto query = sqlpp::select(seeds.seed_id, seeds.seed)
467 .from(seeds
468 .join(rf_alias).on(seeds.first_run_id == rf_alias.run_id)
469 .join(rl_alias).on(seeds.last_run_id == rl_alias.run_id))
470 .where(rf_alias.run_number <= db->GetRunNumber()
471 and rl_alias.run_number >= db->GetRunNumber()
472 and seeds.seed_id > 2);
473
474 QwError << "QwBlinder::ReadSeed executing sqlpp11 query for run number "
475 << db->GetRunNumber() << QwLog::endl;
476
477 auto results = c->QuerySelect(query);
478 size_t result_count = c->CountResults(results);
479 if (result_count == 1) {
480 // Analyze the single result using database-agnostic interface
481 c->ForFirstResult(results, [this](const auto& row) {
482 // Process first (and only) row
483 fSeedID = row.seed_id;
484 if (!is_null(row.seed)) {
485 fSeed = row.seed.value();
486 } else {
487 QwError << "QwBlinder::ReadSeed(): Seed value came back NULL from the database." << QwLog::endl;
488 fSeedID = 0;
490 }
491 });
492
493 std::cout << "QwBlinder::ReadSeed(): Successfully read "
494 << Form("the fSeed with ID %d from the database.", fSeedID)
495 << std::endl;
496
497 } else {
498 // Error Condition.
499 // There should be one and only one seed_id for each seed.
500 fSeedID = 0;
501 fSeed = Form("ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
502 result_count);
503 std::cerr << "QwBlinder::ReadSeed(): "<<fSeed<<std::endl;
504 }
505 } catch (const std::exception& er) {
506 // We were unable to open the connection.
507 fSeedID = 0;
508 fSeed = "ERROR: Unable to open the connection to the database.";
509 QwError << "QwBlinder::ReadSeed(): Unable to open connection to database: " << er.what() << QwLog::endl;
510 }
511
512 return fSeedID;
513}
514#endif // __USE_DATABASE__
515
516/*!-----------------------------------------------------------
517 *------------------------------------------------------------
518 * Function to read the seed string generated utilizing a random number generator
519 *
520 * Parameters: none
521 *
522 * Return: Int_t
523 *
524 *------------------------------------------------------------
525 *------------------------------------------------------------*/
527{
528 static const Char_t alphanum[] =
529 "0123456789"
530 "!@#$%^&*"
531 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
532 "abcdefghijklmnopqrstuvwxyz";
533
534 Int_t strLen = sizeof(alphanum) - 1;
535 const size_t length = 20;
536 Char_t randomchar[length];
537 // Initialize random number generator.
538 srand(time(0));
539 //get a "random" positive integer
540
541 for (int i = 0; i < length; ++i) {
542 randomchar[i] = alphanum[rand() % strLen];
543 }
544 fSeedID=rand();
545 TString frandomSeed(randomchar, length);
546 fSeed=frandomSeed;//a random string
547 return fSeedID;
548}
549
550/*!-----------------------------------------------------------
551 *------------------------------------------------------------
552 * Function to read the seed in from the database.
553 *
554 * Parameters:
555 * seed_id = ID number of seed to use (0 = most recent seed)
556 *
557 * Return: Int_t
558 *
559 *------------------------------------------------------------
560 *------------------------------------------------------------*/
561#ifdef __USE_DATABASE__
562Int_t QwBlinder::ReadSeed(QwParityDB* db, const UInt_t seed_id)
563{
564 // Return unchanged if no database specified
565 if (! db) {
566 QwWarning << "QwBlinder::ReadSeed(): No database specified" << QwLog::endl;
567 fSeedID = 0;
568 fSeed = "Default seed, No database specified";
569 return 0;
570 }
571
572 // Try to connect to the database
573 try {
574 auto c = db->GetScopedConnection();
575
576 // Convert to sqlpp11 query
577 QwParitySchema::seeds seeds{};
578 if (fSeedID > 0) {
579 // Use specified seed
580 auto query = sqlpp::select(sqlpp::all_of(seeds))
581 .from(seeds)
582 .where(seeds.seed_id == seed_id);
583 auto results = db->QuerySelect(query);
584
585 // Process results using database-agnostic interface
586 UInt_t found_seed_id = 0;
587 TString found_seed = "";
588 size_t result_count = db->CountResults(results);
589
590 db->ForFirstResult(results, [&](const auto& row) {
591 found_seed_id = row.seed_id;
592 if (!is_null(row.seed)) {
593 found_seed = row.seed.value();
594 } else {
595 QwError << "QwBlinder::ReadSeed(): Seed value came back NULL from the database." << QwLog::endl;
596 found_seed_id = 0;
597 found_seed = kDefaultSeed;
598 }
599 });
600
601 // Process result for specified seed
602 if (result_count == 1) {
603 fSeedID = found_seed_id;
604 fSeed = found_seed;
605 std::cout << "QwBlinder::ReadSeed(): Successfully read "
606 << Form("the fSeed with ID %d from the database.", fSeedID)
607 << std::endl;
608 } else {
609 fSeedID = 0;
610 fSeed = Form("ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
611 result_count);
612 std::cerr << "QwBlinder::ReadSeed(): " << fSeed << std::endl;
613 }
614 } else {
615 // Use most recent seed
616 auto query = sqlpp::select(sqlpp::all_of(seeds))
617 .from(seeds)
618 .order_by(seeds.seed_id.desc())
619 .limit(1u)
620 .where(sqlpp::value(true));
621 auto results = db->QuerySelect(query);
622
623 // Process results using database-agnostic interface
624 UInt_t found_seed_id2 = 0;
625 TString found_seed2 = "";
626
627 size_t result_count2 = db->CountResults(results);
628
629 db->ForFirstResult(results, [&](const auto& row) {
630 found_seed_id2 = row.seed_id;
631 if (!is_null(row.seed)) {
632 found_seed2 = row.seed.value();
633 } else {
634 QwError << "QwBlinder::ReadSeed(): Seed value came back NULL from the database." << QwLog::endl;
635 found_seed_id2 = 0;
636 found_seed2 = kDefaultSeed;
637 }
638 });
639
640 // Process result for most recent seed
641 if (result_count2 == 1) {
642 fSeedID = found_seed_id2;
643 fSeed = found_seed2;
644 std::cout << "QwBlinder::ReadSeed(): Successfully read "
645 << Form("the fSeed with ID %d from the database.", fSeedID)
646 << std::endl;
647 } else {
648 fSeedID = 0;
649 fSeed = Form("ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
650 result_count2);
651 std::cerr << "QwBlinder::ReadSeed(): " << fSeed << std::endl;
652 }
653 }
654 } catch (const std::exception& er) {
655
656 // We were unable to open the connection.
657 fSeedID = 0;
658 fSeed = "ERROR: Unable to open the connection to the database.";
659 QwError << "QwBlinder::ReadSeed(): Unable to open connection to database: " << er.what() << QwLog::endl;
660 }
661
662 return fSeedID;
663}
664#endif // __USE_DATABASE__
665
666
667/**
668 * Initialize the blinder parameters
669 */
670void QwBlinder::InitBlinders(const UInt_t seed_id)
671{
672 // If the blinding strategy is disabled
674
676 fSeedID = 0;
677 fBlindingFactor = 1.0;
678 fBlindingOffset = 0.0;
680 QwWarning << "Blinding parameters have been disabled!"<< QwLog::endl;
681
682 // Else blinding is enabled
683 } else {
684
685 Int_t finalseed = UseMD5(fSeed);
686
687 Double_t newtempout;
688 if ((finalseed & 0x80000000) == 0x80000000) {
689 newtempout = -1.0 * (finalseed & 0x7FFFFFFF);
690 } else {
691 newtempout = 1.0 * (finalseed & 0x7FFFFFFF);
692 }
693
694
695 /// The blinding constants are determined in two steps.
696 ///
697 /// First, the blinding asymmetry (offset) is determined. It is
698 /// generated from a signed number between +/- 0.244948974 that
699 /// is squared to get a number between +/- 0.06 ppm.
700 static Double_t maximum_asymmetry_sqrt = sqrt(fMaximumBlindingAsymmetry);
701 Double_t tmp1 = maximum_asymmetry_sqrt * (newtempout / Int_t(0x7FFFFFFF));
702 fBlindingOffset = tmp1 * fabs(tmp1) * 0.000001;
703
704 // Do another little calculation to round off the blinding asymmetry
705 Double_t tmp2;
706 tmp1 = fBlindingOffset * 4; // Exactly shifts by two binary places
707 tmp2 = tmp1 + fBlindingOffset; // Rounds 5*fBlindingOffset
708 fBlindingOffset = tmp2 - tmp1; // fBlindingOffset has been rounded.
709
710 // Set the base blinding offset.
712
713 /// Secondly, the multiplicative blinding factor is determined. This
714 /// number is generated from the blinding asymmetry between, say, 0.9 and 1.1
715 /// by an oscillating but uniformly distributed sawtooth function.
716 fBlindingFactor = 1.0;
717 if (fMaximumBlindingAsymmetry > 0.0) {
718 /// TODO: This section of InitBlinders doesn't calculate a reasonable fBlindingFactor but we don't use it for anything.
721 }
722
723 QwMessage << "Blinding parameters have been calculated."<< QwLog::endl;
724
725 }
726
727 // Generate checksum
728 TString hex_string;
729 hex_string.Form("%.16llx%.16llx", *(ULong64_t*)(&fBlindingFactor), *(ULong64_t*)(&fBlindingOffset));
730 fDigest = GenerateDigest(hex_string);
731 fChecksum = "";
732 for (size_t i = 0; i < fDigest.size(); i++)
733 fChecksum += string(Form("%.2x",fDigest[i]));
734}
735
736#ifdef __USE_DATABASE__
737void QwBlinder::WriteFinalValuesToDB(QwParityDB* db)
738{
739 WriteChecksum(db);
740 if (! CheckTestValues()) {
741 QwError << "QwBlinder::WriteFinalValuesToDB(): "
742 << "Blinded test values have changed; may be a problem in the analysis!!!"
743 << QwLog::endl;
744 }
745 WriteTestValues(db);
746}
747#endif // __USE_DATABASE__
748
749
750/**
751 * Generate a set of test values of similar size as measured asymmetries
752 * @param n Number of test values
753 */
755{
756 // Use the stored seed to get a pseudorandom number
757 Int_t finalseed = UsePseudorandom(fSeed);
758
759 fTestValues.clear();
760 fBlindTestValues.clear();
761 fUnBlindTestValues.clear();
762
763 Double_t tmp_offset = fBlindingOffset;
765 // For each test case
766 for (int i = 0; i < n; i++) {
767
768 // Generate a pseudorandom number
769 for (Int_t j = 0; j < 16; j++) {
770 finalseed &= 0x7FFFFFFF;
771 if ((finalseed & 0x800000) == 0x800000) {
772 finalseed = ((finalseed ^ 0x00000d) << 1) | 0x1;
773 } else {
774 finalseed <<= 1;
775 }
776 }
777
778 // Mask out the low digits of the finalseed, multiply by two,
779 // divide by the mask value, subtract from 1, and divide result by
780 // 1.0e6 to get a range of about -1000 to +1000 ppb.
781 Int_t mask = 0xFFFFFF;
782 Double_t tempval = (1.0 - 2.0*(finalseed&mask)/mask) / (1.0e6);
783
784 // Store the test values
785 fTestValues.push_back(tempval);
786 BlindValue(tempval);
787 fBlindTestValues.push_back(tempval);
788 UnBlindValue(tempval);
789 fUnBlindTestValues.push_back(tempval);
790 }
791 fBlindingOffset = tmp_offset;
792 QwMessage << "QwBlinder::InitTestValues(): A total of " << fTestValues.size()
793 << " test values have been calculated successfully." << QwLog::endl;
794}
795
796/**
797 * Use string manipulation to get a number from the seed string
798 * @param barestring Seed string
799 * @return Integer number
800 */
801Int_t QwBlinder::UseStringManip(const TString& barestring)
802{
803 std::vector<UInt_t> choppedwords;
804 UInt_t tmpword = 0;
805 Int_t finalseed = 0;
806
807 for (Int_t i = 0; i < barestring.Length(); i++)
808 {
809 if (i % 4 == 0) tmpword = 0;
810 tmpword |= (char(barestring[i]))<<(24-8*(i%4));
811 if (i%4 == 3 || i == barestring.Length()-1)
812 {
813 choppedwords.push_back(tmpword);
814 finalseed ^= (tmpword);
815 }
816 }
817 for (Int_t i=0; i<64; i++)
818 {
819 finalseed &= 0x7FFFFFFF;
820 if ((finalseed & 0x800000) == 0x800000)
821 {
822 finalseed = ((finalseed^0x00000d)<<1) | 0x1;
823 }
824 else
825 {
826 finalseed<<=1;
827 }
828 }
829 if ((finalseed&0x80000000) == 0x80000000)
830 {
831 finalseed = -1 * (finalseed&0x7FFFFFFF);
832 }
833 else
834 {
835 finalseed = (finalseed&0x7FFFFFFF);
836 }
837 return finalseed;
838}
839
840
841/**
842 * Use pseudo-random number generator to get a number from the seed string
843 * @param barestring Seed string
844 * @return Integer number
845 */
846Int_t QwBlinder::UsePseudorandom(const TString& barestring)
847{
848 ULong64_t finalseed;
849 Int_t bitcount;
850 Int_t tempout = 0;
851
852 // This is an attempt to build a portable 64-bit constant
853 ULong64_t longmask = (0x7FFFFFFF);
854 longmask<<=32;
855 longmask|=0xFFFFFFFF;
856
857 finalseed = 0;
858 bitcount = 0;
859 for (Int_t i=0; i<barestring.Length(); i++)
860 {
861 if ( ((barestring[i])&0xC0)!=0 && ((barestring[i])&0xC0)!=0xC0)
862 {
863 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x40)>>6);
864 bitcount++;
865 }
866 if ( ((barestring[i])&0x30)!=0 && ((barestring[i])&0x30)!=0x30)
867 {
868 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x10)>>4);
869 bitcount++;
870 }
871 if ( ((barestring[i])&0xC)!=0 && ((barestring[i])&0xC)!=0xC)
872 {
873 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x4)>>2);
874 bitcount++;
875 }
876 if ( ((barestring[i])&0x3)!=0 && ((barestring[i])&0x3)!=0x3)
877 {
878 finalseed = ((finalseed&longmask)<<1) | ((barestring[i])&0x1);
879 bitcount++;
880 }
881 }
882 for (Int_t i=0; i<(192-bitcount); i++)
883 {
884 if ((finalseed & 0x800000) == 0x800000)
885 {
886 finalseed = ((finalseed^0x00000d)<<1) | 0x1;
887 }
888 else
889 {
890 finalseed<<=1;
891 }
892 }
893 tempout = (finalseed&0xFFFFFFFF) ^ ((finalseed>>32)&0xFFFFFFFF);
894 if ((tempout&0x80000000) == 0x80000000)
895 {
896 tempout = -1 * (tempout&0x7FFFFFFF);
897 }
898 else
899 {
900 tempout = 1 * (tempout&0x7FFFFFFF);
901 }
902 return tempout;
903}
904
905
906/**
907 * Use an MD5 checksum to get a number from the seed string
908 * @param barestring Seed string
909 * @return Integer number
910 */
911Int_t QwBlinder::UseMD5(const TString& barestring)
912{
913 Int_t temp = 0;
914 Int_t tempout = 0;
915
916 std::vector<UChar_t> digest = GenerateDigest(barestring);
917 for (size_t i = 0; i < digest.size(); i++)
918 {
919 Int_t j = i%4;
920 if (j == 0)
921 {
922 temp = 0;
923 }
924 temp |= (digest[i])<<(24-(j*8));
925 if ( (j==3) || (i==(digest.size()-1)))
926 {
927 tempout ^= temp;
928 }
929 }
930
931 if ((tempout & 0x80000000) == 0x80000000) {
932 tempout = -1 * (tempout & 0x7FFFFFFF);
933 } else {
934 tempout = (tempout & 0x7FFFFFFF);
935 }
936
937 return tempout;
938}
939
940
941/*!-----------------------------------------------------------
942 *------------------------------------------------------------
943 * Function to write the checksum into the analysis table
944 *
945 * Parameters: void
946 *
947 * Return: void
948 *
949 * Note: This function assumes that the analysis table has already
950 * been filled for the run.
951 *------------------------------------------------------------
952 *------------------------------------------------------------*/
953#ifdef __USE_DATABASE__
954void QwBlinder::WriteChecksum(QwParityDB* db)
955{
956 //----------------------------------------------------------
957 // Construct and execute sqlpp11 UPDATE query
958 //----------------------------------------------------------
959 QwParitySchema::analysis analysis{};
960 auto update_query = sqlpp::update(analysis)
961 .set(analysis.seed_id = fSeedID,
962 analysis.bf_checksum = fChecksum)
963 .where(analysis.analysis_id == db->GetAnalysisID());
964 //----------------------------------------------------------
965 // Execute SQL
966 //----------------------------------------------------------
967 auto c = db->GetScopedConnection();
968 db->QueryExecute(update_query);
969} //End QwBlinder::WriteChecksum
970
971/*!------------------------------------------------------------
972 *------------------------------------------------------------
973 * Function to write the test values into the database
974 *
975 * Parameters: void
976 *
977 * Return: void
978 *------------------------------------------------------------
979 *------------------------------------------------------------*/
980void QwBlinder::WriteTestValues(QwParityDB* db)
981{
982 //----------------------------------------------------------
983 // Use sqlpp11 INSERT for bf_test table
984 //----------------------------------------------------------
985 QwParitySchema::bf_test bf_test{};
986
987 //----------------------------------------------------------
988 // Insert test values using sqlpp11
989 //----------------------------------------------------------
990 // Loop over all test values
991 for (size_t i = 0; i < fTestValues.size(); i++)
992 {
993 auto insert_query = sqlpp::insert_into(bf_test)
994 .set(bf_test.analysis_id = db->GetAnalysisID(),
995 bf_test.test_number = static_cast<int>(i),
996 bf_test.test_value = fBlindTestValues[i]);
997
998 // Execute SQL
999 auto c = db->GetScopedConnection();
1000 db->QueryExecute(insert_query);
1001 }
1002}
1003#endif // __USE_DATABASE__
1004
1005/*!--------------------------------------------------------------
1006 * This routines checks to see if the stored fBlindTestValues[i]
1007 * match a recomputed blinded test value. The values are cast
1008 * into floats, and their difference must be less than a change
1009 * of the least-significant-bit of fBlindTestValues[i].
1010 *--------------------------------------------------------------*/
1011
1013{
1014 Bool_t status = kTRUE;
1015
1016 Double_t tmp_offset = fBlindingOffset;
1018 double epsilon = std::numeric_limits<double>::epsilon();
1019 for (size_t i = 0; i < fTestValues.size(); i++) {
1020
1021 /// First test: compare a blinded value with a second computation
1022 double checkval = fBlindTestValues[i];
1023 UnBlindValue(checkval);
1024
1025 double test1 = fTestValues[i];
1026 double test2 = checkval;
1027 if ((test1 - test2) <= -epsilon || (test1 - test2) >= epsilon) {
1028 QwError << "QwBlinder::CheckTestValues(): Unblinded test value "
1029 << i
1030 << " does not agree with original test value, "
1031 << "with a difference of "
1032 << (test1 - test2)
1033 << " (epsilon==" << epsilon << ")"
1034 << "." << QwLog::endl;
1035 status = kFALSE;
1036 }
1037
1038 /// Second test: compare the unblinded value with the original value
1039 test1 = fUnBlindTestValues[i];
1040 test2 = fTestValues[i];
1041 if ((test1 - test2) <= -epsilon || (test1 - test2) >= epsilon) {
1042 QwError << "QwBlinder::CheckTestValues(): Unblinded test value "
1043 << i
1044 << " does not agree with original test value, "
1045 << "with a difference of "
1046 << (test1 - test2) << "." << QwLog::endl;
1047 status = kFALSE;
1048 }
1049 }
1050 fBlindingOffset = tmp_offset;
1051 return status;
1052}
1053
1054
1055/**
1056 * Generate an MD5 digest of the blinding parameters
1057 * @param input Input string
1058 * @return MD5 digest of the input string
1059 */
1060std::vector<UChar_t> QwBlinder::GenerateDigest(const TString& input) const
1061{
1062 // Initialize MD5 checksum array
1063 const UInt_t length = 16;
1064 UChar_t value[length];
1065 for (UInt_t i = 0; i < length; i++)
1066 value[i] = 0;
1067
1068 // Calculate MD5 checksum from input and store in md5_value
1069 TMD5 md5;
1070 md5.Update((UChar_t*) input.Data(), input.Length());
1071 md5.Final(value);
1072
1073 // Copy the MD5 checksum in an STL vector
1074 std::vector<UChar_t> output;
1075 for (UInt_t i = 0; i < length; i++)
1076 output.push_back(value[i]);
1077
1078 return output;
1079}
1080
1081
1082/**
1083 * Print a summary of the blinding/unblinding test
1084 */
1085void QwBlinder::PrintFinalValues(Int_t kVerbosity)
1086{
1087 Int_t total_count = 0;
1088 for (size_t i=0; i<kBlinderCount_NumCounters; i++){
1089 total_count += fPatternCounters.at(i);
1090 }
1091 if (total_count<=0) return;
1092
1093 QwMessage << "QwBlinder::PrintFinalValues(): Begin summary" << QwLog::endl;
1094 QwMessage << "================================================" << QwLog::endl;
1096 if(kVerbosity==1){
1097 QwMessage << "================================================" << QwLog::endl;
1099 }
1100 QwMessage << "================================================" << QwLog::endl;
1101 QwMessage << "The blinding parameters checksum for seed ID "
1102 << fSeedID << " is:" << QwLog::endl;
1104 QwMessage << "================================================" << QwLog::endl;
1106 double epsilon = std::numeric_limits<double>::epsilon();
1107 TString diff;
1108 QwMessage << "The test results are:" << QwLog::endl;
1109 QwMessage << std::setw(8) << "Index"
1110 << std::setw(16) << "Original value"
1111 << std::setw(16) << "Blinded value"
1112 << std::setw(22) << "Orig.-Unblind value"
1113 << QwLog::endl;
1114 for (size_t i = 0; i < fTestValues.size(); i++) {
1115 if ((fTestValues[i]-fUnBlindTestValues[i]) < -epsilon
1116 || (fTestValues[i]-fUnBlindTestValues[i]) > epsilon )
1117 diff = Form("% 9g ppb", fTestValues[i]-fUnBlindTestValues[i]*1e9);
1118 else
1119 diff = "epsilon";
1120 QwMessage << std::setw(8) << i
1121 << std::setw(16) << Form(" [CENSORED]")
1122 << std::setw(16) << Form("% 9.3f ppb",fBlindTestValues[i]*1e9)
1123 << std::setw(22) << diff
1124 << QwLog::endl;
1125 }
1126 QwMessage << "================================================" << QwLog::endl;
1127 QwMessage << "QwBlinder::PrintFinalValues(): End of summary" << QwLog::endl;
1128}
1129
1130void QwBlinder::PrintCountersValues(std::vector<Int_t> fCounters, TString counter_type)
1131{
1132 QwMessage << "Blinder Passed " << counter_type << QwLog::endl;
1133 QwMessage << "\t" << counter_type
1134 << " with blinding disabled: " << fCounters.at(kBlinderCount_Disabled) << QwLog::endl;
1135 QwMessage << "\t" << counter_type
1136 << " on a non-blindable target: " << fCounters.at(kBlinderCount_NonBlindable) << QwLog::endl;
1137 QwMessage << "\t" << counter_type
1138 << " with transverse beam: " << fCounters.at(kBlinderCount_Transverse) << QwLog::endl;
1139 QwMessage << "\t" << counter_type
1140 << " on blindable target with beam present: " << fCounters.at(kBlinderCount_Blindable) << QwLog::endl;
1141 QwMessage << "Blinder Failed " << counter_type << QwLog::endl;
1142 QwMessage << "\t" << counter_type
1143 << " with unknown target position: " << fCounters.at(kBlinderCount_UnknownTarget) << QwLog::endl;
1144 QwMessage << "\t" << counter_type
1145 << " with changed target position: " << fCounters.at(kBlinderCount_ChangedTarget) << QwLog::endl;
1146 QwMessage << "\t" << counter_type
1147 << " with an undefined Wien setting: " << fCounters.at(kBlinderCount_UndefinedWien) << QwLog::endl;
1148 QwMessage << "\t" << counter_type
1149 << " with a changed Wien setting: " << fCounters.at(kBlinderCount_ChangedWien) << QwLog::endl;
1150 QwMessage << "\t" << counter_type
1151 << " with an undefined IHWP setting: " << fCounters.at(kBlinderCount_UndefinedIHWP) << QwLog::endl;
1152 QwMessage << "\t" << counter_type
1153 << " with a changed IHWP setting: " << fCounters.at(kBlinderCount_ChangedIHWP) << QwLog::endl;
1154 QwMessage << "\t" << counter_type
1155 << " on blindable target with no beam: " << fCounters.at(kBlinderCount_NoBeam) << QwLog::endl;
1156 QwMessage << "\t" << counter_type
1157 << " with other blinding failure: " << fCounters.at(kBlinderCount_OtherFailure) << QwLog::endl;
1158
1159}
1160
1161
1162/**
1163 * Write the blinding parameters to the database
1164 *
1165 * For each analyzed run the database contains a digest of the blinding parameters
1166 * and a number of blinded test entries.
1167 */
1168#ifdef __USE_DATABASE__
1169void QwBlinder::FillDB(QwParityDB *db, TString datatype)
1170{
1171 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1172 QwDebug << " QwBlinder::FillDB " << QwLog::endl;
1173 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1174
1175 // Get the analysis ID
1176 UInt_t analysis_id = db->GetAnalysisID();
1177
1178 // Fill the test values for database insertion
1179 if (! CheckTestValues()) {
1180 QwError << "QwBlinder::FillDB(): "
1181 << "Blinded test values have changed; "
1182 << "may be a problem in the analysis!!!"
1183 << QwLog::endl;
1184 }
1185
1186
1187 // Connect to the database
1188 auto c = db->GetScopedConnection();
1189
1190 // Modify the seed_id and bf_checksum in the analysis table
1191 try {
1192 QwParitySchema::analysis analysis{};
1193
1194 auto update_query = sqlpp::update(analysis)
1195 .set(analysis.seed_id = fSeedID,
1196 analysis.bf_checksum = fChecksum)
1197 .where(analysis.analysis_id == analysis_id);
1198
1199 QwDebug << "Updating analysis table with blinder information" << QwLog::endl;
1200 db->QueryExecute(update_query);
1201
1202 } catch (const std::exception& err) {
1203 QwError << "Failed to update analysis table: " << err.what() << QwLog::endl;
1204 }
1205
1206 // Add the bf_test rows
1207 try {
1208 if (fTestValues.size() > 0) {
1209 QwParitySchema::bf_test bf_test{};
1210 for (size_t i = 0; i < fTestValues.size(); i++) {
1211 auto insert_query = sqlpp::insert_into(bf_test)
1212 .set(bf_test.analysis_id = analysis_id,
1213 bf_test.test_number = static_cast<int>(i),
1214 bf_test.test_value = fBlindTestValues[i]);
1215
1216 db->QueryExecute(insert_query);
1217 }
1218 QwDebug << "Inserted " << fTestValues.size() << " bf_test entries" << QwLog::endl;
1219 } else {
1220 QwMessage << "QwBlinder::FillDB(): No bf_test entries to write."
1221 << QwLog::endl;
1222 }
1223 } catch (const std::exception& err) {
1224 QwError << "Failed to insert bf_test entries: " << err.what() << QwLog::endl;
1225 }
1226}
1227
1228void QwBlinder::FillErrDB(QwParityDB *db, TString datatype)
1229{
1230 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1231 QwDebug << " QwBlinder::FillErrDB " << QwLog::endl;
1232 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1233
1234 UInt_t analysis_id = db->GetAnalysisID();
1235 QwParitySchema::general_errors general_errors{};
1236
1237 auto c = db->GetScopedConnection();
1238
1239 try {
1240 // Insert error counter entries for each blinder counter type
1241 for (size_t index = 0; index < kBlinderCount_NumCounters; index++) {
1242 if (fPatternCounters.at(index) > 0) { // Only insert non-zero counters
1243 auto insert_query = sqlpp::insert_into(general_errors)
1244 .set(general_errors.analysis_id = analysis_id,
1245 general_errors.error_code_id = index + 20, // error codes 20+
1246 general_errors.n = fPatternCounters.at(index));
1247
1248 db->QueryExecute(insert_query);
1249 }
1250 }
1251 QwDebug << "Inserted blinder error counters for analysis " << analysis_id << QwLog::endl;
1252
1253 } catch (const std::exception& err) {
1254 QwError << "Failed to insert blinder error counters: " << err.what() << QwLog::endl;
1255 }
1256};
1257#endif // __USE_DATABASE__
1258
1259
1270
1272{
1273 fWienMode = wienmode;
1277 QwMessage << "QwBlinder: First set Wien state to "
1279 }
1280}
1281
1282void QwBlinder::SetIHWPPolarity(Int_t ihwppolarity)
1283{
1284 fIHWPPolarity = ihwppolarity;
1285 if (fIHWPPolarity_firstread == 0 && fIHWPPolarity != 0){
1287 QwMessage << "QwBlinder: First set IHWP state to "
1289 }
1290}
1291
1292
1294{
1297 status = QwBlinder::kNotBlindable;
1298 fCounters.at(kBlinderCount_Disabled)++;
1300 QwDebug << "QwBlinder::CheckBlindability: The target blindability is not determined. "
1301 << "Fail this pattern." << QwLog::endl;
1303 fCounters.at(kBlinderCount_UnknownTarget)++;
1306 QwDebug << "QwBlinder::CheckBlindability: The target blindability has changed. "
1307 << "Fail this pattern." << QwLog::endl;
1309 fCounters.at(kBlinderCount_ChangedTarget)++;
1310 } else if (fTargetBlindability==kNotBlindable) {
1311 // This isn't a blindable target, so don't do anything.
1312 status = QwBlinder::kNotBlindable;
1313 fCounters.at(kBlinderCount_NonBlindable)++;
1314 } else if (fTargetBlindability==kBlindable &&
1316 // Wien status changed. Fail
1318 fCounters.at(kBlinderCount_ChangedWien)++;
1319 } else if (fTargetBlindability==kBlindable &&
1321 // IHWP status changed. Fail
1323 fCounters.at(kBlinderCount_ChangedIHWP)++;
1324 } else if (fTargetBlindability==kBlindable &&
1326 // Wien status isn't determined. Fail.
1328 fCounters.at(kBlinderCount_UndefinedWien)++;
1329 } else if (fTargetBlindability==kBlindable &&
1330 fIHWPPolarity==0) {
1331 // IHWP status isn't determined. Fail.
1333 fCounters.at(kBlinderCount_UndefinedIHWP)++;
1334 } else if (fTargetBlindability==kBlindable &&
1336 // We don't have longitudinal beam, so don't blind.
1337 status = QwBlinder::kNotBlindable;
1338 fCounters.at(kBlinderCount_Transverse)++;
1339 } else if (fTargetBlindability==kBlindable
1340 && fBeamIsPresent) {
1341 // This is a blindable target and the beam is sufficient.
1342 status = QwBlinder::kBlindable;
1343 fCounters.at(kBlinderCount_Blindable)++;
1344 } else if (fTargetBlindability==kBlindable
1345 && (! fBeamIsPresent) ) {
1346 // This is a blindable target but there is insufficient beam present
1347 status = QwBlinder::kNotBlindable;
1348 fCounters.at(kBlinderCount_NoBeam)++;
1349 } else {
1350 QwError << "QwBlinder::CheckBlindability: The pattern blindability is unclear. "
1351 << "Fail this pattern." << QwLog::endl;
1353 fCounters.at(kBlinderCount_OtherFailure)++;
1354 }
1355 //
1357
1358 return status;
1359}
A logfile class, based on an identical class in the Hermes analyzer.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
Parameter file parsing and management.
Decoding and management for VQWK ADC channels (6x32-bit datawords)
std::string WienModeName(EQwWienMode type)
Definition QwTypes.cc:150
EQwWienMode
Double Wien configuration.
Definition QwTypes.h:308
@ kWienIndeterminate
Definition QwTypes.h:309
@ kWienBackward
Definition QwTypes.h:311
@ kWienVertTrans
Definition QwTypes.h:312
@ kWienForward
Definition QwTypes.h:310
@ kWienHorizTrans
Definition QwTypes.h:313
A class for blinding data, adapted from G0 blinder class.
unsigned long long ULong64_t
Definition QwBlinder.h:41
EQwBlinderErrorCounterIndices
Blinder event counter indices.
Definition QwBlinder.cc:40
@ kBlinderCount_ChangedIHWP
Definition QwBlinder.cc:51
@ kBlinderCount_NoBeam
Definition QwBlinder.cc:45
@ kBlinderCount_UndefinedIHWP
Definition QwBlinder.cc:50
@ kBlinderCount_NumCounters
Definition QwBlinder.cc:53
@ kBlinderCount_Blindable
Definition QwBlinder.cc:41
@ kBlinderCount_UnknownTarget
Definition QwBlinder.cc:46
@ kBlinderCount_OtherFailure
Definition QwBlinder.cc:52
@ kBlinderCount_NonBlindable
Definition QwBlinder.cc:42
@ kBlinderCount_ChangedWien
Definition QwBlinder.cc:49
@ kBlinderCount_ChangedTarget
Definition QwBlinder.cc:47
@ kBlinderCount_Transverse
Definition QwBlinder.cc:43
@ kBlinderCount_UndefinedWien
Definition QwBlinder.cc:48
@ kBlinderCount_Disabled
Definition QwBlinder.cc:44
Bool_t RequestExternalValue(const TString &name, VQwHardwareChannel *value) const
Retrieve a variable value from external sources by copying Searches for the named variable in externa...
EPICS slow controls data management.
Int_t DetermineIHWPPolarity() const
EQwWienMode DetermineWienMode() const
Double_t GetDataValue(const string &tag) const
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Command-line and configuration file options processor.
Definition QwOptions.h:141
T GetValue(const std::string &key)
Get a templated value.
Definition QwOptions.h:236
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition QwOptions.h:170
Configuration file parser with flexible tokenization and search capabilities.
Bool_t FileHasVariablePair(const std::string &separatorchars, const std::string &varname, std::string &varvalue)
Concrete hardware channel for VQWK ADC modules (6x32-bit words)
Double_t GetValue(size_t element) const override
Int_t kCREXTgtIndexMax
Definition QwBlinder.h:244
QwBlinder(const EQwBlindingStrategy blinding_strategy=kAdditive)
Default constructor with optional database.
Definition QwBlinder.cc:83
void InitTestValues(const int n)
Initializes fBlindingFactor from fSeed.
Definition QwBlinder.cc:754
EQwBlinderStatus
Status of the blinding process or intermediate steps of the process.
Definition QwBlinder.h:69
@ kBlindableFail
Definition QwBlinder.h:73
@ kIndeterminate
Definition QwBlinder.h:70
@ kNotBlindable
Definition QwBlinder.h:71
Int_t fIHWPPolarity
Definition QwBlinder.h:232
Int_t ReadRandomSeed()
Read the seed string generated utilizing a random number generator.
Definition QwBlinder.cc:526
std::vector< UChar_t > GenerateDigest(const TString &input) const
Writes fTestNumber and fBlindTestValue to DB for this analysis ID.
Int_t fCREXTargetIndex
Definition QwBlinder.h:242
static const TString fStatusName[4]
Definition QwBlinder.h:58
EQwBlinderStatus fTargetBlindability_firstread
Indicates the first value received of the blindability of the target.
Definition QwBlinder.h:226
void WriteTestValues(QwParityDB *db)
Writes fSeedID and fBFChecksum to DB for this analysis ID.
Bool_t fTargetPositionForced
Definition QwBlinder.h:228
std::vector< double > fBlindTestValues
Vector of test values, original.
Definition QwBlinder.h:283
std::vector< double > fTestValues
Checksum in ASCII hex.
Definition QwBlinder.h:282
void UnBlindValue(Double_t &value) const
Asymmetry unblinding.
Definition QwBlinder.h:136
void PrintFinalValues(Int_t kVerbosity=1)
Bool_t fBeamIsPresent
Definition QwBlinder.h:247
std::vector< UChar_t > fDigest
Default seed.
Definition QwBlinder.h:279
Bool_t CheckTestValues()
EQwWienMode fWienMode
Definition QwBlinder.h:230
Double_t fBlindingOffset_Base
The term to be added to detector asymmetries.
Definition QwBlinder.h:265
static const TString kDefaultSeed
Seed string (seeds.seed)
Definition QwBlinder.h:277
std::vector< Int_t > fPatternCounters
Counts the number of events in each failure mode.
Definition QwBlinder.h:316
Int_t UsePseudorandom(const TString &barestring)
Definition QwBlinder.cc:846
Double_t fBlindingFactor
The term to be added to detector asymmetries, before polarity correction.
Definition QwBlinder.h:266
void Update()
Update the status using a random number.
Definition QwBlinder.cc:276
std::string fChecksum
Checksum in raw hex.
Definition QwBlinder.h:280
Double_t fBlindingOffset
Blinding strategy.
Definition QwBlinder.h:264
Double_t fBeamCurrentThreshold
Definition QwBlinder.h:246
std::vector< Int_t > fPairCounters
Counts the number of helicity pairs in each failure mode.
Definition QwBlinder.h:317
Double_t fMaximumBlindingAsymmetry
Default maximum blinding factor (in fraction from identity)
Definition QwBlinder.h:272
static const Double_t kDefaultMaximumBlindingAsymmetry
The factor to be multiplied to detector asymmetries.
Definition QwBlinder.h:269
static void DefineOptions(QwOptions &options)
Definition QwBlinder.cc:69
void WriteChecksum(QwParityDB *db)
void SetTargetBlindability(EQwBlinderStatus status)
Set the current target blindability status.
void SetWienState(EQwWienMode wienmode)
void BlindValue(Double_t &value) const
Asymmetry blinding.
Definition QwBlinder.h:124
Int_t kCREXTgtIndexMin
Definition QwBlinder.h:243
TString fSeed
ID of seed used (seeds.seed_id)
Definition QwBlinder.h:276
EQwWienMode fWienMode_firstread
Definition QwBlinder.h:229
void SetIHWPPolarity(Int_t ihwppolarity)
Bool_t fSpinDirectionForced
Definition QwBlinder.h:233
void WriteFinalValuesToDB(QwParityDB *db)
static const Double_t kDefaultMaximumBlindingFactor
Default maximum blinding asymmetry (in ppm)
Definition QwBlinder.h:270
EQwBlindingStrategy
Available blinding strategies.
Definition QwBlinder.h:62
@ kMultiplicative
Definition QwBlinder.h:65
@ kAdditiveMultiplicative
Definition QwBlinder.h:66
Int_t UseStringManip(const TString &barestring)
Returns an integer from a string using MD5.
Definition QwBlinder.cc:801
void PrintCountersValues(std::vector< Int_t > fCounters, TString counter_type)
Int_t ReadSeed(QwParityDB *db, const UInt_t seed_id)
Reads the seed with specified id from the database object.
Int_t UseMD5(const TString &barestring)
Recomputes fBlindTestValue to check for memory errors.
Definition QwBlinder.cc:911
Double_t fMaximumBlindingFactor
Maximum blinding asymmetry (in ppm)
Definition QwBlinder.h:273
EQwBlinderStatus CheckBlindability(std::vector< Int_t > &fCounters)
std::vector< double > fUnBlindTestValues
Vector of test values, after blinding.
Definition QwBlinder.h:284
void InitBlinders(const UInt_t seed_id)
Vector of test values, after unblinding.
Definition QwBlinder.cc:670
EQwBlindingStrategy fBlindingStrategy
Definition QwBlinder.h:263
UInt_t fSeedID
Maximum blinding factor (in fraction from identity)
Definition QwBlinder.h:275
Int_t fIHWPPolarity_firstread
Definition QwBlinder.h:231
virtual ~QwBlinder()
Default destructor.
Definition QwBlinder.cc:219
EQwBlinderStatus fTargetBlindability
Definition QwBlinder.h:227
Bool_t fBlinderIsOkay
Definition QwBlinder.h:250
void ProcessOptions(QwOptions &options)
Update the status with new external information.
Definition QwBlinder.cc:230
Subsystem array container specialized for parity analysis with asymmetry calculations.