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 // Check for the target blindability flag
305
306 // Check that the current on target is above acceptable limit
307 Bool_t tmp_beam = kFALSE;
308 const VQwHardwareChannel* q_targ = detectors.RequestExternalPointer("q_targ");
309 if (q_targ != nullptr) {
310 if (q_targ->GetValue() > fBeamCurrentThreshold) {
311 tmp_beam = kTRUE;
312 }
313 }
314
315 fBeamIsPresent &= tmp_beam;
316 }
317}
318
319/**
320 * Update the blinder status with new external information
321 *
322 * @param epics Current EPICS event
323 */
325{
326 // Check for the target information
327 // Position:
328 // QWtgt_name == "HYDROGEN-CELL" || QWTGTPOS > 350
329 // Temperature:
330 // QWT_miA < 22.0 && QWT_moA < 22.0
331 // Pressure:
332 // QW_PT3 in [20,35] && QW_PT4 in [20,35]
334 //TString position = epics.GetDataString("QWtgt_name");
335 Double_t tgt_pos = epics.GetDataValue("pcrex90BDSPOS.VAL");
336 QwDebug << "Target parameters used by the blinder: "
337 // << "QWtgt_name=" << position << " "
338 << "QWTGTPOS=" << tgt_pos << " "
339 << QwLog::endl;
340
341 //
342 // **** Target index 1: Beginning of CREX
343 if (fCREXTargetIndex==1 &&
344 (tgt_pos>14.5e6 && tgt_pos<18.0e6) ){
345 // Calcium-48 target position
347
348 } else if (fCREXTargetIndex==1 &&
349 ( (tgt_pos>-1.0e3 && tgt_pos<14.5e6)
350 || (tgt_pos>18.0e6 && tgt_pos<61.e6) ) ){
351 // Reasonable non-calcium-48 target positions
353
354
355 //
356 // **** Target index 2: After 20January change in target location
357 } else if (fCREXTargetIndex==2 &&
358 (tgt_pos>11.5e6 && tgt_pos<14.5e6) ){
359 // Calcium-48 target position (old Ca-40 position)
361
362 } else if (fCREXTargetIndex==2 &&
363 ( (tgt_pos>-1.0e3 && tgt_pos<11.5e6)
364 || (tgt_pos>14.5e6 && tgt_pos<61.e6) ) ){
365 // Reasonable non-calcium-48 target positions
367
368 //
369 // **** Target index -1: These are the PREX positions
370 } else if ( fCREXTargetIndex==-1 &&
371 (/* Target positions before 1 August 2019.*/
372 ( (tgt_pos > 3e6 && tgt_pos < 6.9e6)
373 || (tgt_pos > 7.3e6 && tgt_pos < 7.7e6))
374 /* Target positions after 1 August 2019.*/
375 ||( (tgt_pos>30.e6 && tgt_pos<69e6)
376 || (tgt_pos>73e6 && tgt_pos<78e6)
377 ) ) ){
378 // Lead-208 target positions
380
381 } else if ( fCREXTargetIndex==-1 &&
382 (/* Target positions before 1 August 2019.*/
383 ((tgt_pos > -1e3 && tgt_pos < 3e6)
384 || (tgt_pos > 6.8e6 && tgt_pos < 7.2e6)
385 || (tgt_pos > 7.7e6 && tgt_pos < 10e6))
386 /* Target positions after 1 August 2019.*/
387 || ( (tgt_pos>17e6 && tgt_pos<30e6)
388 || (tgt_pos>69e6 && tgt_pos<73e6)
389 || (tgt_pos>78e6 && tgt_pos<90e6)
390 )
391 ) ){
392 // Positions are not lead-208 targets.
394
395 } else {
397 QwWarning << "Target parameters used by the blinder are indeterminate: "
398 // << "QWtgt_name=" << position << " "
399 << "QWTGTPOS=" << tgt_pos << " "
400 << QwLog::endl;
401 } // End of tests on target positions
402 }
403 // Check for the beam polarity information
404 // IGL1I00DI24_24M Beam Half-wave plate Read(off=out)
405 //
408 // Use the EPICS class functions to determine the
409 // Wien mode and IHWP polarity.
412
413 if (fWienMode == kWienForward){
415 } else if (fWienMode == kWienBackward){
417 } else {
418 fBlindingOffset = 0.0;
419 }
420 }
421}
422
423/*!-----------------------------------------------------------
424 *------------------------------------------------------------
425 * Function to read the seed in from the database.
426 *
427 * Parameters:
428 *
429 * Return: Int_t
430 *
431 *------------------------------------------------------------
432 *------------------------------------------------------------*/
433#ifdef __USE_DATABASE__
434Int_t QwBlinder::ReadSeed(QwParityDB* db)
435{
436 // Return unchanged if no database specified
437 if (! db) {
438 QwWarning << "QwBlinder::ReadSeed(): No database specified" << QwLog::endl;
439 fSeedID = 0;
440 fSeed = "Default seed, No database specified";
441 return 0;
442 }
443 if (! db->AllowsReadAccess()){
444 QwDebug << "QwBlinder::ReadSeed(): Database access is turned off. Don't update the blinder." << QwLog::endl;
445 return 0;
446 }
447
448 // Try to connect to the database
449 try {
450 auto c = db->GetScopedConnection();
451
452 QwError << "QwBlinder::ReadSeed db->GetRunNumber() returns "
453 << db->GetRunNumber() << QwLog::endl;
454
455 // Convert to sqlpp11 query with JOINs
456 QwParitySchema::seeds seeds{};
457 QwParitySchema::run first_run{};
458 QwParitySchema::run last_run{};
459
460 // Create aliases for the run table
461 auto rf_alias = first_run.as(run_first);
462 auto rl_alias = last_run.as(run_last);
463 auto query = sqlpp::select(seeds.seed_id, seeds.seed)
464 .from(seeds
465 .join(rf_alias).on(seeds.first_run_id == rf_alias.run_id)
466 .join(rl_alias).on(seeds.last_run_id == rl_alias.run_id))
467 .where(rf_alias.run_number <= db->GetRunNumber()
468 and rl_alias.run_number >= db->GetRunNumber()
469 and seeds.seed_id > 2);
470
471 QwError << "QwBlinder::ReadSeed executing sqlpp11 query for run number "
472 << db->GetRunNumber() << QwLog::endl;
473
474 auto results = c->QuerySelect(query);
475 size_t result_count = c->CountResults(results);
476 if (result_count == 1) {
477 // Analyze the single result using database-agnostic interface
478 c->ForFirstResult(results, [this](const auto& row) {
479 // Process first (and only) row
480 fSeedID = row.seed_id;
481 if (!is_null(row.seed)) {
482 fSeed = row.seed.value();
483 } else {
484 QwError << "QwBlinder::ReadSeed(): Seed value came back NULL from the database." << QwLog::endl;
485 fSeedID = 0;
487 }
488 });
489
490 std::cout << "QwBlinder::ReadSeed(): Successfully read "
491 << Form("the fSeed with ID %d from the database.", fSeedID)
492 << std::endl;
493
494 } else {
495 // Error Condition.
496 // There should be one and only one seed_id for each seed.
497 fSeedID = 0;
498 fSeed = Form("ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
499 result_count);
500 std::cerr << "QwBlinder::ReadSeed(): "<<fSeed<<std::endl;
501 }
502 } catch (const std::exception& er) {
503 // We were unable to open the connection.
504 fSeedID = 0;
505 fSeed = "ERROR: Unable to open the connection to the database.";
506 QwError << "QwBlinder::ReadSeed(): Unable to open connection to database: " << er.what() << QwLog::endl;
507 }
508
509 return fSeedID;
510}
511#endif // __USE_DATABASE__
512
513/*!-----------------------------------------------------------
514 *------------------------------------------------------------
515 * Function to read the seed string generated utilizing a random number generator
516 *
517 * Parameters: none
518 *
519 * Return: Int_t
520 *
521 *------------------------------------------------------------
522 *------------------------------------------------------------*/
524{
525 static const Char_t alphanum[] =
526 "0123456789"
527 "!@#$%^&*"
528 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
529 "abcdefghijklmnopqrstuvwxyz";
530
531 Int_t strLen = sizeof(alphanum) - 1;
532 const size_t length = 20;
533 Char_t randomchar[length];
534 // Initialize random number generator.
535 srand(time(0));
536 //get a "random" positive integer
537
538 for (size_t i = 0; i < length; ++i) {
539 randomchar[i] = alphanum[rand() % strLen];
540 }
541 fSeedID=rand();
542 TString frandomSeed(randomchar, length);
543 fSeed=frandomSeed;//a random string
544 return fSeedID;
545}
546
547/*!-----------------------------------------------------------
548 *------------------------------------------------------------
549 * Function to read the seed in from the database.
550 *
551 * Parameters:
552 * seed_id = ID number of seed to use (0 = most recent seed)
553 *
554 * Return: Int_t
555 *
556 *------------------------------------------------------------
557 *------------------------------------------------------------*/
558#ifdef __USE_DATABASE__
559Int_t QwBlinder::ReadSeed(QwParityDB* db, const UInt_t seed_id)
560{
561 // Return unchanged if no database specified
562 if (! db) {
563 QwWarning << "QwBlinder::ReadSeed(): No database specified" << QwLog::endl;
564 fSeedID = 0;
565 fSeed = "Default seed, No database specified";
566 return 0;
567 }
568
569 // Try to connect to the database
570 try {
571 auto c = db->GetScopedConnection();
572
573 // Convert to sqlpp11 query
574 QwParitySchema::seeds seeds{};
575 if (fSeedID > 0) {
576 // Use specified seed
577 auto query = sqlpp::select(sqlpp::all_of(seeds))
578 .from(seeds)
579 .where(seeds.seed_id == seed_id);
580 auto results = db->QuerySelect(query);
581
582 // Process results using database-agnostic interface
583 UInt_t found_seed_id = 0;
584 TString found_seed = "";
585 size_t result_count = db->CountResults(results);
586
587 db->ForFirstResult(results, [&](const auto& row) {
588 found_seed_id = row.seed_id;
589 if (!is_null(row.seed)) {
590 found_seed = row.seed.value();
591 } else {
592 QwError << "QwBlinder::ReadSeed(): Seed value came back NULL from the database." << QwLog::endl;
593 found_seed_id = 0;
594 found_seed = kDefaultSeed;
595 }
596 });
597
598 // Process result for specified seed
599 if (result_count == 1) {
600 fSeedID = found_seed_id;
601 fSeed = found_seed;
602 std::cout << "QwBlinder::ReadSeed(): Successfully read "
603 << Form("the fSeed with ID %d from the database.", fSeedID)
604 << std::endl;
605 } else {
606 fSeedID = 0;
607 fSeed = Form("ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
608 result_count);
609 std::cerr << "QwBlinder::ReadSeed(): " << fSeed << std::endl;
610 }
611 } else {
612 // Use most recent seed
613 auto query = sqlpp::select(sqlpp::all_of(seeds))
614 .from(seeds)
615 .order_by(seeds.seed_id.desc())
616 .limit(1u)
617 .where(sqlpp::value(true));
618 auto results = db->QuerySelect(query);
619
620 // Process results using database-agnostic interface
621 UInt_t found_seed_id2 = 0;
622 TString found_seed2 = "";
623
624 size_t result_count2 = db->CountResults(results);
625
626 db->ForFirstResult(results, [&](const auto& row) {
627 found_seed_id2 = row.seed_id;
628 if (!is_null(row.seed)) {
629 found_seed2 = row.seed.value();
630 } else {
631 QwError << "QwBlinder::ReadSeed(): Seed value came back NULL from the database." << QwLog::endl;
632 found_seed_id2 = 0;
633 found_seed2 = kDefaultSeed;
634 }
635 });
636
637 // Process result for most recent seed
638 if (result_count2 == 1) {
639 fSeedID = found_seed_id2;
640 fSeed = found_seed2;
641 std::cout << "QwBlinder::ReadSeed(): Successfully read "
642 << Form("the fSeed with ID %d from the database.", fSeedID)
643 << std::endl;
644 } else {
645 fSeedID = 0;
646 fSeed = Form("ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
647 result_count2);
648 std::cerr << "QwBlinder::ReadSeed(): " << fSeed << std::endl;
649 }
650 }
651 } catch (const std::exception& er) {
652
653 // We were unable to open the connection.
654 fSeedID = 0;
655 fSeed = "ERROR: Unable to open the connection to the database.";
656 QwError << "QwBlinder::ReadSeed(): Unable to open connection to database: " << er.what() << QwLog::endl;
657 }
658
659 return fSeedID;
660}
661#endif // __USE_DATABASE__
662
663
664/**
665 * Initialize the blinder parameters
666 */
667void QwBlinder::InitBlinders(const UInt_t seed_id)
668{
669 // If the blinding strategy is disabled
671
673 fSeedID = 0;
674 fBlindingFactor = 1.0;
675 fBlindingOffset = 0.0;
677 QwWarning << "Blinding parameters have been disabled!"<< QwLog::endl;
678
679 // Else blinding is enabled
680 } else {
681
682 Int_t finalseed = UseMD5(fSeed);
683
684 Double_t newtempout;
685 if ((finalseed & 0x80000000) == 0x80000000) {
686 newtempout = -1.0 * (finalseed & 0x7FFFFFFF);
687 } else {
688 newtempout = 1.0 * (finalseed & 0x7FFFFFFF);
689 }
690
691
692 /// The blinding constants are determined in two steps.
693 ///
694 /// First, the blinding asymmetry (offset) is determined. It is
695 /// generated from a signed number between +/- 0.244948974 that
696 /// is squared to get a number between +/- 0.06 ppm.
697 static Double_t maximum_asymmetry_sqrt = sqrt(fMaximumBlindingAsymmetry);
698 Double_t tmp1 = maximum_asymmetry_sqrt * (newtempout / Int_t(0x7FFFFFFF));
699 fBlindingOffset = tmp1 * fabs(tmp1) * 0.000001;
700
701 // Do another little calculation to round off the blinding asymmetry
702 Double_t tmp2;
703 tmp1 = fBlindingOffset * 4; // Exactly shifts by two binary places
704 tmp2 = tmp1 + fBlindingOffset; // Rounds 5*fBlindingOffset
705 fBlindingOffset = tmp2 - tmp1; // fBlindingOffset has been rounded.
706
707 // Set the base blinding offset.
709
710 /// Secondly, the multiplicative blinding factor is determined. This
711 /// number is generated from the blinding asymmetry between, say, 0.9 and 1.1
712 /// by an oscillating but uniformly distributed sawtooth function.
713 fBlindingFactor = 1.0;
714 if (fMaximumBlindingAsymmetry > 0.0) {
715 /// TODO: This section of InitBlinders doesn't calculate a reasonable fBlindingFactor but we don't use it for anything.
718 }
719
720 QwMessage << "Blinding parameters have been calculated."<< QwLog::endl;
721
722 }
723
724 // Generate checksum
725#if __cplusplus < 202002L
726 ULong64_t factor_bits, offset_bits;
727 memcpy(&factor_bits, &fBlindingFactor, sizeof(ULong64_t));
728 memcpy(&offset_bits, &fBlindingOffset, sizeof(ULong64_t));
729#else
730 auto factor_bits = std::bit_cast<ULong64_t>(fBlindingFactor);
731 auto offset_bits = std::bit_cast<ULong64_t>(fBlindingOffset);
732#endif
733 TString hex_string;
734 hex_string.Form("%.16llx%.16llx", factor_bits, offset_bits);
735 fDigest = GenerateDigest(hex_string);
736 fChecksum = "";
737 for (size_t i = 0; i < fDigest.size(); i++)
738 fChecksum += string(Form("%.2x",fDigest[i]));
739}
740
741#ifdef __USE_DATABASE__
742void QwBlinder::WriteFinalValuesToDB(QwParityDB* db)
743{
744 WriteChecksum(db);
745 if (! CheckTestValues()) {
746 QwError << "QwBlinder::WriteFinalValuesToDB(): "
747 << "Blinded test values have changed; may be a problem in the analysis!!!"
748 << QwLog::endl;
749 }
750 WriteTestValues(db);
751}
752#endif // __USE_DATABASE__
753
754
755/**
756 * Generate a set of test values of similar size as measured asymmetries
757 * @param n Number of test values
758 */
760{
761 // Use the stored seed to get a pseudorandom number
762 Int_t finalseed = UsePseudorandom(fSeed);
763
764 fTestValues.clear();
765 fBlindTestValues.clear();
766 fUnBlindTestValues.clear();
767
768 Double_t tmp_offset = fBlindingOffset;
770 // For each test case
771 for (int i = 0; i < n; i++) {
772
773 // Generate a pseudorandom number
774 for (Int_t j = 0; j < 16; j++) {
775 finalseed &= 0x7FFFFFFF;
776 if ((finalseed & 0x800000) == 0x800000) {
777 finalseed = ((finalseed ^ 0x00000d) << 1) | 0x1;
778 } else {
779 finalseed <<= 1;
780 }
781 }
782
783 // Mask out the low digits of the finalseed, multiply by two,
784 // divide by the mask value, subtract from 1, and divide result by
785 // 1.0e6 to get a range of about -1000 to +1000 ppb.
786 Int_t mask = 0xFFFFFF;
787 Double_t tempval = (1.0 - 2.0*(finalseed&mask)/mask) / (1.0e6);
788
789 // Store the test values
790 fTestValues.push_back(tempval);
791 BlindValue(tempval);
792 fBlindTestValues.push_back(tempval);
793 UnBlindValue(tempval);
794 fUnBlindTestValues.push_back(tempval);
795 }
796 fBlindingOffset = tmp_offset;
797 QwMessage << "QwBlinder::InitTestValues(): A total of " << fTestValues.size()
798 << " test values have been calculated successfully." << QwLog::endl;
799}
800
801/**
802 * Use string manipulation to get a number from the seed string
803 * @param barestring Seed string
804 * @return Integer number
805 */
806Int_t QwBlinder::UseStringManip(const TString& barestring)
807{
808 std::vector<UInt_t> choppedwords;
809 UInt_t tmpword = 0;
810 Int_t finalseed = 0;
811
812 for (Int_t i = 0; i < barestring.Length(); i++)
813 {
814 if (i % 4 == 0) tmpword = 0;
815 tmpword |= (char(barestring[i]))<<(24-8*(i%4));
816 if (i%4 == 3 || i == barestring.Length()-1)
817 {
818 choppedwords.push_back(tmpword);
819 finalseed ^= (tmpword);
820 }
821 }
822 for (Int_t i=0; i<64; i++)
823 {
824 finalseed &= 0x7FFFFFFF;
825 if ((finalseed & 0x800000) == 0x800000)
826 {
827 finalseed = ((finalseed^0x00000d)<<1) | 0x1;
828 }
829 else
830 {
831 finalseed<<=1;
832 }
833 }
834 if ((finalseed&0x80000000) == 0x80000000)
835 {
836 finalseed = -1 * (finalseed&0x7FFFFFFF);
837 }
838 else
839 {
840 finalseed = (finalseed&0x7FFFFFFF);
841 }
842 return finalseed;
843}
844
845
846/**
847 * Use pseudo-random number generator to get a number from the seed string
848 * @param barestring Seed string
849 * @return Integer number
850 */
851Int_t QwBlinder::UsePseudorandom(const TString& barestring)
852{
853 ULong64_t finalseed;
854 Int_t bitcount;
855 Int_t tempout = 0;
856
857 // This is an attempt to build a portable 64-bit constant
858 ULong64_t longmask = (0x7FFFFFFF);
859 longmask<<=32;
860 longmask|=0xFFFFFFFF;
861
862 finalseed = 0;
863 bitcount = 0;
864 for (Int_t i=0; i<barestring.Length(); i++)
865 {
866 if ( ((barestring[i])&0xC0)!=0 && ((barestring[i])&0xC0)!=0xC0)
867 {
868 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x40)>>6);
869 bitcount++;
870 }
871 if ( ((barestring[i])&0x30)!=0 && ((barestring[i])&0x30)!=0x30)
872 {
873 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x10)>>4);
874 bitcount++;
875 }
876 if ( ((barestring[i])&0xC)!=0 && ((barestring[i])&0xC)!=0xC)
877 {
878 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x4)>>2);
879 bitcount++;
880 }
881 if ( ((barestring[i])&0x3)!=0 && ((barestring[i])&0x3)!=0x3)
882 {
883 finalseed = ((finalseed&longmask)<<1) | ((barestring[i])&0x1);
884 bitcount++;
885 }
886 }
887 for (Int_t i=0; i<(192-bitcount); i++)
888 {
889 if ((finalseed & 0x800000) == 0x800000)
890 {
891 finalseed = ((finalseed^0x00000d)<<1) | 0x1;
892 }
893 else
894 {
895 finalseed<<=1;
896 }
897 }
898 tempout = (finalseed&0xFFFFFFFF) ^ ((finalseed>>32)&0xFFFFFFFF);
899 if ((tempout&0x80000000) == 0x80000000)
900 {
901 tempout = -1 * (tempout&0x7FFFFFFF);
902 }
903 else
904 {
905 tempout = 1 * (tempout&0x7FFFFFFF);
906 }
907 return tempout;
908}
909
910
911/**
912 * Use an MD5 checksum to get a number from the seed string
913 * @param barestring Seed string
914 * @return Integer number
915 */
916Int_t QwBlinder::UseMD5(const TString& barestring)
917{
918 Int_t temp = 0;
919 Int_t tempout = 0;
920
921 std::vector<UChar_t> digest = GenerateDigest(barestring);
922 for (size_t i = 0; i < digest.size(); i++)
923 {
924 Int_t j = i%4;
925 if (j == 0)
926 {
927 temp = 0;
928 }
929 temp |= (digest[i])<<(24-(j*8));
930 if ( (j==3) || (i==(digest.size()-1)))
931 {
932 tempout ^= temp;
933 }
934 }
935
936 if ((tempout & 0x80000000) == 0x80000000) {
937 tempout = -1 * (tempout & 0x7FFFFFFF);
938 } else {
939 tempout = (tempout & 0x7FFFFFFF);
940 }
941
942 return tempout;
943}
944
945
946/*!-----------------------------------------------------------
947 *------------------------------------------------------------
948 * Function to write the checksum into the analysis table
949 *
950 * Parameters: void
951 *
952 * Return: void
953 *
954 * Note: This function assumes that the analysis table has already
955 * been filled for the run.
956 *------------------------------------------------------------
957 *------------------------------------------------------------*/
958#ifdef __USE_DATABASE__
959void QwBlinder::WriteChecksum(QwParityDB* db)
960{
961 //----------------------------------------------------------
962 // Construct and execute sqlpp11 UPDATE query
963 //----------------------------------------------------------
964 QwParitySchema::analysis analysis{};
965 auto update_query = sqlpp::update(analysis)
966 .set(analysis.seed_id = fSeedID,
967 analysis.bf_checksum = fChecksum)
968 .where(analysis.analysis_id == db->GetAnalysisID());
969 //----------------------------------------------------------
970 // Execute SQL
971 //----------------------------------------------------------
972 auto c = db->GetScopedConnection();
973 db->QueryExecute(update_query);
974} //End QwBlinder::WriteChecksum
975
976/*!------------------------------------------------------------
977 *------------------------------------------------------------
978 * Function to write the test values into the database
979 *
980 * Parameters: void
981 *
982 * Return: void
983 *------------------------------------------------------------
984 *------------------------------------------------------------*/
985void QwBlinder::WriteTestValues(QwParityDB* db)
986{
987 //----------------------------------------------------------
988 // Use sqlpp11 INSERT for bf_test table
989 //----------------------------------------------------------
990 QwParitySchema::bf_test bf_test{};
991
992 //----------------------------------------------------------
993 // Insert test values using sqlpp11
994 //----------------------------------------------------------
995 // Loop over all test values
996 for (size_t i = 0; i < fTestValues.size(); i++)
997 {
998 auto insert_query = sqlpp::insert_into(bf_test)
999 .set(bf_test.analysis_id = db->GetAnalysisID(),
1000 bf_test.test_number = static_cast<int>(i),
1001 bf_test.test_value = fBlindTestValues[i]);
1002
1003 // Execute SQL
1004 auto c = db->GetScopedConnection();
1005 db->QueryExecute(insert_query);
1006 }
1007}
1008#endif // __USE_DATABASE__
1009
1010/*!--------------------------------------------------------------
1011 * This routines checks to see if the stored fBlindTestValues[i]
1012 * match a recomputed blinded test value. The values are cast
1013 * into floats, and their difference must be less than a change
1014 * of the least-significant-bit of fBlindTestValues[i].
1015 *--------------------------------------------------------------*/
1016
1018{
1019 Bool_t status = kTRUE;
1020
1021 Double_t tmp_offset = fBlindingOffset;
1023 double epsilon = std::numeric_limits<double>::epsilon();
1024 for (size_t i = 0; i < fTestValues.size(); i++) {
1025
1026 /// First test: compare a blinded value with a second computation
1027 double checkval = fBlindTestValues[i];
1028 UnBlindValue(checkval);
1029
1030 double test1 = fTestValues[i];
1031 double test2 = checkval;
1032 if ((test1 - test2) <= -epsilon || (test1 - test2) >= epsilon) {
1033 QwError << "QwBlinder::CheckTestValues(): Unblinded test value "
1034 << i
1035 << " does not agree with original test value, "
1036 << "with a difference of "
1037 << (test1 - test2)
1038 << " (epsilon==" << epsilon << ")"
1039 << "." << QwLog::endl;
1040 status = kFALSE;
1041 }
1042
1043 /// Second test: compare the unblinded value with the original value
1044 test1 = fUnBlindTestValues[i];
1045 test2 = fTestValues[i];
1046 if ((test1 - test2) <= -epsilon || (test1 - test2) >= epsilon) {
1047 QwError << "QwBlinder::CheckTestValues(): Unblinded test value "
1048 << i
1049 << " does not agree with original test value, "
1050 << "with a difference of "
1051 << (test1 - test2) << "." << QwLog::endl;
1052 status = kFALSE;
1053 }
1054 }
1055 fBlindingOffset = tmp_offset;
1056 return status;
1057}
1058
1059
1060/**
1061 * Generate an MD5 digest of the blinding parameters
1062 * @param input Input string
1063 * @return MD5 digest of the input string
1064 */
1065std::vector<UChar_t> QwBlinder::GenerateDigest(const TString& input) const
1066{
1067 // Initialize MD5 checksum array
1068 const UInt_t length = 16;
1069 UChar_t value[length];
1070 for (UInt_t i = 0; i < length; i++)
1071 value[i] = 0;
1072
1073 // Calculate MD5 checksum from input and store in md5_value
1074 TMD5 md5;
1075 md5.Update((UChar_t*) input.Data(), input.Length());
1076 md5.Final(value);
1077
1078 // Copy the MD5 checksum in an STL vector
1079 std::vector<UChar_t> output;
1080 for (UInt_t i = 0; i < length; i++)
1081 output.push_back(value[i]);
1082
1083 return output;
1084}
1085
1086
1087/**
1088 * Print a summary of the blinding/unblinding test
1089 */
1090void QwBlinder::PrintFinalValues(Int_t kVerbosity)
1091{
1092 Int_t total_count = 0;
1093 for (size_t i=0; i<kBlinderCount_NumCounters; i++){
1094 total_count += fPatternCounters.at(i);
1095 }
1096 if (total_count<=0) return;
1097
1098 QwMessage << "QwBlinder::PrintFinalValues(): Begin summary" << QwLog::endl;
1099 QwMessage << "================================================" << QwLog::endl;
1101 if(kVerbosity==1){
1102 QwMessage << "================================================" << QwLog::endl;
1104 }
1105 QwMessage << "================================================" << QwLog::endl;
1106 QwMessage << "The blinding parameters checksum for seed ID "
1107 << fSeedID << " is:" << QwLog::endl;
1109 QwMessage << "================================================" << QwLog::endl;
1111 double epsilon = std::numeric_limits<double>::epsilon();
1112 TString diff;
1113 QwMessage << "The test results are:" << QwLog::endl;
1114 QwMessage << std::setw(8) << "Index"
1115 << std::setw(16) << "Original value"
1116 << std::setw(16) << "Blinded value"
1117 << std::setw(22) << "Orig.-Unblind value"
1118 << QwLog::endl;
1119 for (size_t i = 0; i < fTestValues.size(); i++) {
1120 if ((fTestValues[i]-fUnBlindTestValues[i]) < -epsilon
1121 || (fTestValues[i]-fUnBlindTestValues[i]) > epsilon )
1122 diff = Form("% 9g ppb", fTestValues[i]-fUnBlindTestValues[i]*1e9);
1123 else
1124 diff = "epsilon";
1125 QwMessage << std::setw(8) << i
1126 << std::setw(16) << Form(" [CENSORED]")
1127 << std::setw(16) << Form("% 9.3f ppb",fBlindTestValues[i]*1e9)
1128 << std::setw(22) << diff
1129 << QwLog::endl;
1130 }
1131 QwMessage << "================================================" << QwLog::endl;
1132 QwMessage << "QwBlinder::PrintFinalValues(): End of summary" << QwLog::endl;
1133}
1134
1135void QwBlinder::PrintCountersValues(std::vector<Int_t> fCounters, TString counter_type)
1136{
1137 QwMessage << "Blinder Passed " << counter_type << QwLog::endl;
1138 QwMessage << "\t" << counter_type
1139 << " with blinding disabled: " << fCounters.at(kBlinderCount_Disabled) << QwLog::endl;
1140 QwMessage << "\t" << counter_type
1141 << " on a non-blindable target: " << fCounters.at(kBlinderCount_NonBlindable) << QwLog::endl;
1142 QwMessage << "\t" << counter_type
1143 << " with transverse beam: " << fCounters.at(kBlinderCount_Transverse) << QwLog::endl;
1144 QwMessage << "\t" << counter_type
1145 << " on blindable target with beam present: " << fCounters.at(kBlinderCount_Blindable) << QwLog::endl;
1146 QwMessage << "Blinder Failed " << counter_type << QwLog::endl;
1147 QwMessage << "\t" << counter_type
1148 << " with unknown target position: " << fCounters.at(kBlinderCount_UnknownTarget) << QwLog::endl;
1149 QwMessage << "\t" << counter_type
1150 << " with changed target position: " << fCounters.at(kBlinderCount_ChangedTarget) << QwLog::endl;
1151 QwMessage << "\t" << counter_type
1152 << " with an undefined Wien setting: " << fCounters.at(kBlinderCount_UndefinedWien) << QwLog::endl;
1153 QwMessage << "\t" << counter_type
1154 << " with a changed Wien setting: " << fCounters.at(kBlinderCount_ChangedWien) << QwLog::endl;
1155 QwMessage << "\t" << counter_type
1156 << " with an undefined IHWP setting: " << fCounters.at(kBlinderCount_UndefinedIHWP) << QwLog::endl;
1157 QwMessage << "\t" << counter_type
1158 << " with a changed IHWP setting: " << fCounters.at(kBlinderCount_ChangedIHWP) << QwLog::endl;
1159 QwMessage << "\t" << counter_type
1160 << " on blindable target with no beam: " << fCounters.at(kBlinderCount_NoBeam) << QwLog::endl;
1161 QwMessage << "\t" << counter_type
1162 << " with other blinding failure: " << fCounters.at(kBlinderCount_OtherFailure) << QwLog::endl;
1163
1164}
1165
1166
1167/**
1168 * Write the blinding parameters to the database
1169 *
1170 * For each analyzed run the database contains a digest of the blinding parameters
1171 * and a number of blinded test entries.
1172 */
1173#ifdef __USE_DATABASE__
1174void QwBlinder::FillDB(QwParityDB *db, TString datatype)
1175{
1176 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1177 QwDebug << " QwBlinder::FillDB " << QwLog::endl;
1178 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1179
1180 // Get the analysis ID
1181 UInt_t analysis_id = db->GetAnalysisID();
1182
1183 // Fill the test values for database insertion
1184 if (! CheckTestValues()) {
1185 QwError << "QwBlinder::FillDB(): "
1186 << "Blinded test values have changed; "
1187 << "may be a problem in the analysis!!!"
1188 << QwLog::endl;
1189 }
1190
1191
1192 // Connect to the database
1193 auto c = db->GetScopedConnection();
1194
1195 // Modify the seed_id and bf_checksum in the analysis table
1196 try {
1197 QwParitySchema::analysis analysis{};
1198
1199 auto update_query = sqlpp::update(analysis)
1200 .set(analysis.seed_id = fSeedID,
1201 analysis.bf_checksum = fChecksum)
1202 .where(analysis.analysis_id == analysis_id);
1203
1204 QwDebug << "Updating analysis table with blinder information" << QwLog::endl;
1205 db->QueryExecute(update_query);
1206
1207 } catch (const std::exception& err) {
1208 QwError << "Failed to update analysis table: " << err.what() << QwLog::endl;
1209 }
1210
1211 // Add the bf_test rows
1212 try {
1213 if (fTestValues.size() > 0) {
1214 QwParitySchema::bf_test bf_test{};
1215 for (size_t i = 0; i < fTestValues.size(); i++) {
1216 auto insert_query = sqlpp::insert_into(bf_test)
1217 .set(bf_test.analysis_id = analysis_id,
1218 bf_test.test_number = static_cast<int>(i),
1219 bf_test.test_value = fBlindTestValues[i]);
1220
1221 db->QueryExecute(insert_query);
1222 }
1223 QwDebug << "Inserted " << fTestValues.size() << " bf_test entries" << QwLog::endl;
1224 } else {
1225 QwMessage << "QwBlinder::FillDB(): No bf_test entries to write."
1226 << QwLog::endl;
1227 }
1228 } catch (const std::exception& err) {
1229 QwError << "Failed to insert bf_test entries: " << err.what() << QwLog::endl;
1230 }
1231}
1232
1233void QwBlinder::FillErrDB(QwParityDB *db, TString datatype)
1234{
1235 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1236 QwDebug << " QwBlinder::FillErrDB " << QwLog::endl;
1237 QwDebug << " --------------------------------------------------------------- " << QwLog::endl;
1238
1239 UInt_t analysis_id = db->GetAnalysisID();
1240 QwParitySchema::general_errors general_errors{};
1241
1242 auto c = db->GetScopedConnection();
1243
1244 try {
1245 // Insert error counter entries for each blinder counter type
1246 for (size_t index = 0; index < kBlinderCount_NumCounters; index++) {
1247 if (fPatternCounters.at(index) > 0) { // Only insert non-zero counters
1248 auto insert_query = sqlpp::insert_into(general_errors)
1249 .set(general_errors.analysis_id = analysis_id,
1250 general_errors.error_code_id = index + 20, // error codes 20+
1251 general_errors.n = fPatternCounters.at(index));
1252
1253 db->QueryExecute(insert_query);
1254 }
1255 }
1256 QwDebug << "Inserted blinder error counters for analysis " << analysis_id << QwLog::endl;
1257
1258 } catch (const std::exception& err) {
1259 QwError << "Failed to insert blinder error counters: " << err.what() << QwLog::endl;
1260 }
1261};
1262#endif // __USE_DATABASE__
1263
1264
1275
1277{
1278 fWienMode = wienmode;
1282 QwMessage << "QwBlinder: First set Wien state to "
1284 }
1285}
1286
1287void QwBlinder::SetIHWPPolarity(Int_t ihwppolarity)
1288{
1289 fIHWPPolarity = ihwppolarity;
1290 if (fIHWPPolarity_firstread == 0 && fIHWPPolarity != 0){
1292 QwMessage << "QwBlinder: First set IHWP state to "
1294 }
1295}
1296
1297
1299{
1302 status = QwBlinder::kNotBlindable;
1303 fCounters.at(kBlinderCount_Disabled)++;
1305 QwDebug << "QwBlinder::CheckBlindability: The target blindability is not determined. "
1306 << "Fail this pattern." << QwLog::endl;
1308 fCounters.at(kBlinderCount_UnknownTarget)++;
1311 QwDebug << "QwBlinder::CheckBlindability: The target blindability has changed. "
1312 << "Fail this pattern." << QwLog::endl;
1314 fCounters.at(kBlinderCount_ChangedTarget)++;
1315 } else if (fTargetBlindability==kNotBlindable) {
1316 // This isn't a blindable target, so don't do anything.
1317 status = QwBlinder::kNotBlindable;
1318 fCounters.at(kBlinderCount_NonBlindable)++;
1319 } else if (fTargetBlindability==kBlindable &&
1321 // Wien status changed. Fail
1323 fCounters.at(kBlinderCount_ChangedWien)++;
1324 } else if (fTargetBlindability==kBlindable &&
1326 // IHWP status changed. Fail
1328 fCounters.at(kBlinderCount_ChangedIHWP)++;
1329 } else if (fTargetBlindability==kBlindable &&
1331 // Wien status isn't determined. Fail.
1333 fCounters.at(kBlinderCount_UndefinedWien)++;
1334 } else if (fTargetBlindability==kBlindable &&
1335 fIHWPPolarity==0) {
1336 // IHWP status isn't determined. Fail.
1338 fCounters.at(kBlinderCount_UndefinedIHWP)++;
1339 } else if (fTargetBlindability==kBlindable &&
1341 // We don't have longitudinal beam, so don't blind.
1342 status = QwBlinder::kNotBlindable;
1343 fCounters.at(kBlinderCount_Transverse)++;
1345 && fBeamIsPresent) {
1346 // This is a blindable target and the beam is sufficient.
1347 status = QwBlinder::kBlindable;
1348 fCounters.at(kBlinderCount_Blindable)++;
1350 && (! fBeamIsPresent) ) {
1351 // This is a blindable target but there is insufficient beam present
1352 status = QwBlinder::kNotBlindable;
1353 fCounters.at(kBlinderCount_NoBeam)++;
1354 } else {
1355 QwError << "QwBlinder::CheckBlindability: The pattern blindability is unclear. "
1356 << "Fail this pattern." << QwLog::endl;
1358 fCounters.at(kBlinderCount_OtherFailure)++;
1359 }
1360 //
1362
1363 return status;
1364}
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
const VQwHardwareChannel * RequestExternalPointer(const TString &name) const
Retrieve a direct pointer to an external variable Searches for the named variable in external subsyst...
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)
Abstract base for concrete hardware channels implementing dual-operator pattern.
Double_t GetValue() const
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:759
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:523
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:851
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:806
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:916
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:667
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.