19#ifdef __USE_DATABASE__
20#include "QwParitySchema.h"
28#ifdef __USE_DATABASE__
30SQLPP_ALIAS_PROVIDER(run_first);
31SQLPP_ALIAS_PROVIDER(run_last);
34SQLPP_CREATE_NAME_TAG(run_first);
35SQLPP_CREATE_NAME_TAG(run_last);
59 "Blindable",
"BlindableFail"};
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");
124 QwError <<
"Invalid CREX target index for blindable events! Exiting!"
131 fSeed.Prepend(TString(
"[Using CREX positions!] "));
134 std::string strategy;
136 std::transform(strategy.begin(), strategy.end(), strategy.begin(), ::tolower);
145 std::string 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;
153 }
else if (spin_direction ==
"spin-backward"){
154 QwWarning <<
"QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-backward" <<
QwLog::endl;
158 }
else if (spin_direction ==
"spin-vertical"){
159 QwWarning <<
"QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-vertical" <<
QwLog::endl;
163 }
else if (spin_direction ==
"spin-horizontal"){
164 QwWarning <<
"QwBlinder::QwBlinder: Spin direction forced with force-spin-direction==spin-horizontal" <<
QwLog::endl;
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."
176 std::string 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;
183 }
else if (target_type ==
"target-out"){
184 QwWarning <<
"QwBlinder::QwBlinder: Target position forced with force-target-type==target-out" <<
QwLog::endl;
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."
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."
238 }
else if (options.
GetValue<
bool>(
"blinder.force-target-blindable")){
239 QwWarning <<
"QwBlinder::ProcessOptions: Target position forced with blinder.force-target-blindable." <<
QwLog::endl;
242 }
else if (options.
GetValue<
bool>(
"blinder.force-target-out")){
243 QwWarning <<
"QwBlinder::ProcessOptions: Target position forced with blinder.force-target-out." <<
QwLog::endl;
251#ifdef __USE_DATABASE__
309 Bool_t tmp_beam = kFALSE;
338 Double_t tgt_pos = epics.
GetDataValue(
"pcrex90BDSPOS.VAL");
339 QwDebug <<
"Target parameters used by the blinder: "
341 <<
"QWTGTPOS=" << tgt_pos <<
" "
347 (tgt_pos>14.5e6 && tgt_pos<18.0e6) ){
352 ( (tgt_pos>-1.0e3 && tgt_pos<14.5e6)
353 || (tgt_pos>18.0e6 && tgt_pos<61.e6) ) ){
361 (tgt_pos>11.5e6 && tgt_pos<14.5e6) ){
366 ( (tgt_pos>-1.0e3 && tgt_pos<11.5e6)
367 || (tgt_pos>14.5e6 && tgt_pos<61.e6) ) ){
375 ( (tgt_pos > 3e6 && tgt_pos < 6.9e6)
376 || (tgt_pos > 7.3e6 && tgt_pos < 7.7e6))
378 ||( (tgt_pos>30.e6 && tgt_pos<69e6)
379 || (tgt_pos>73e6 && tgt_pos<78e6)
386 ((tgt_pos > -1e3 && tgt_pos < 3e6)
387 || (tgt_pos > 6.8e6 && tgt_pos < 7.2e6)
388 || (tgt_pos > 7.7e6 && tgt_pos < 10e6))
390 || ( (tgt_pos>17e6 && tgt_pos<30e6)
391 || (tgt_pos>69e6 && tgt_pos<73e6)
392 || (tgt_pos>78e6 && tgt_pos<90e6)
400 QwWarning <<
"Target parameters used by the blinder are indeterminate: "
402 <<
"QWTGTPOS=" << tgt_pos <<
" "
436#ifdef __USE_DATABASE__
443 fSeed =
"Default seed, No database specified";
446 if (! db->AllowsReadAccess()){
447 QwDebug <<
"QwBlinder::ReadSeed(): Database access is turned off. Don't update the blinder." <<
QwLog::endl;
453 auto c = db->GetScopedConnection();
455 QwError <<
"QwBlinder::ReadSeed db->GetRunNumber() returns "
459 QwParitySchema::seeds seeds{};
460 QwParitySchema::run first_run{};
461 QwParitySchema::run last_run{};
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)
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);
474 QwError <<
"QwBlinder::ReadSeed executing sqlpp11 query for run number "
477 auto results = c->QuerySelect(query);
478 size_t result_count = c->CountResults(results);
479 if (result_count == 1) {
481 c->ForFirstResult(results, [
this](
const auto& row) {
484 if (!is_null(row.seed)) {
485 fSeed = row.seed.value();
487 QwError <<
"QwBlinder::ReadSeed(): Seed value came back NULL from the database." <<
QwLog::endl;
493 std::cout <<
"QwBlinder::ReadSeed(): Successfully read "
494 << Form(
"the fSeed with ID %d from the database.",
fSeedID)
501 fSeed = Form(
"ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
503 std::cerr <<
"QwBlinder::ReadSeed(): "<<
fSeed<<std::endl;
505 }
catch (
const std::exception& er) {
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;
528 static const Char_t alphanum[] =
531 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
532 "abcdefghijklmnopqrstuvwxyz";
534 Int_t strLen =
sizeof(alphanum) - 1;
535 const size_t length = 20;
536 Char_t randomchar[length];
541 for (
int i = 0; i < length; ++i) {
542 randomchar[i] = alphanum[rand() % strLen];
545 TString frandomSeed(randomchar, length);
561#ifdef __USE_DATABASE__
568 fSeed =
"Default seed, No database specified";
574 auto c = db->GetScopedConnection();
577 QwParitySchema::seeds seeds{};
580 auto query = sqlpp::select(sqlpp::all_of(seeds))
582 .where(seeds.seed_id == seed_id);
583 auto results = db->QuerySelect(query);
586 UInt_t found_seed_id = 0;
587 TString found_seed =
"";
588 size_t result_count = db->CountResults(results);
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();
595 QwError <<
"QwBlinder::ReadSeed(): Seed value came back NULL from the database." <<
QwLog::endl;
602 if (result_count == 1) {
605 std::cout <<
"QwBlinder::ReadSeed(): Successfully read "
606 << Form(
"the fSeed with ID %d from the database.",
fSeedID)
610 fSeed = Form(
"ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
612 std::cerr <<
"QwBlinder::ReadSeed(): " <<
fSeed << std::endl;
616 auto query = sqlpp::select(sqlpp::all_of(seeds))
618 .order_by(seeds.seed_id.desc())
620 .where(sqlpp::value(
true));
621 auto results = db->QuerySelect(query);
624 UInt_t found_seed_id2 = 0;
625 TString found_seed2 =
"";
627 size_t result_count2 = db->CountResults(results);
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();
634 QwError <<
"QwBlinder::ReadSeed(): Seed value came back NULL from the database." <<
QwLog::endl;
641 if (result_count2 == 1) {
644 std::cout <<
"QwBlinder::ReadSeed(): Successfully read "
645 << Form(
"the fSeed with ID %d from the database.",
fSeedID)
649 fSeed = Form(
"ERROR: There should be one and only one seed_id for each seed, but this had %zu.",
651 std::cerr <<
"QwBlinder::ReadSeed(): " <<
fSeed << std::endl;
654 }
catch (
const std::exception& er) {
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;
688 if ((finalseed & 0x80000000) == 0x80000000) {
689 newtempout = -1.0 * (finalseed & 0x7FFFFFFF);
691 newtempout = 1.0 * (finalseed & 0x7FFFFFFF);
701 Double_t tmp1 = maximum_asymmetry_sqrt * (newtempout / Int_t(0x7FFFFFFF));
732 for (
size_t i = 0; i <
fDigest.size(); i++)
736#ifdef __USE_DATABASE__
741 QwError <<
"QwBlinder::WriteFinalValuesToDB(): "
742 <<
"Blinded test values have changed; may be a problem in the analysis!!!"
766 for (
int i = 0; i < n; i++) {
769 for (Int_t j = 0; j < 16; j++) {
770 finalseed &= 0x7FFFFFFF;
771 if ((finalseed & 0x800000) == 0x800000) {
772 finalseed = ((finalseed ^ 0x00000d) << 1) | 0x1;
781 Int_t mask = 0xFFFFFF;
782 Double_t tempval = (1.0 - 2.0*(finalseed&mask)/mask) / (1.0e6);
793 <<
" test values have been calculated successfully." <<
QwLog::endl;
803 std::vector<UInt_t> choppedwords;
807 for (Int_t i = 0; i < barestring.Length(); i++)
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)
813 choppedwords.push_back(tmpword);
814 finalseed ^= (tmpword);
817 for (Int_t i=0; i<64; i++)
819 finalseed &= 0x7FFFFFFF;
820 if ((finalseed & 0x800000) == 0x800000)
822 finalseed = ((finalseed^0x00000d)<<1) | 0x1;
829 if ((finalseed&0x80000000) == 0x80000000)
831 finalseed = -1 * (finalseed&0x7FFFFFFF);
835 finalseed = (finalseed&0x7FFFFFFF);
855 longmask|=0xFFFFFFFF;
859 for (Int_t i=0; i<barestring.Length(); i++)
861 if ( ((barestring[i])&0xC0)!=0 && ((barestring[i])&0xC0)!=0xC0)
863 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x40)>>6);
866 if ( ((barestring[i])&0x30)!=0 && ((barestring[i])&0x30)!=0x30)
868 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x10)>>4);
871 if ( ((barestring[i])&0xC)!=0 && ((barestring[i])&0xC)!=0xC)
873 finalseed = ((finalseed&longmask)<<1) | (((barestring[i])&0x4)>>2);
876 if ( ((barestring[i])&0x3)!=0 && ((barestring[i])&0x3)!=0x3)
878 finalseed = ((finalseed&longmask)<<1) | ((barestring[i])&0x1);
882 for (Int_t i=0; i<(192-bitcount); i++)
884 if ((finalseed & 0x800000) == 0x800000)
886 finalseed = ((finalseed^0x00000d)<<1) | 0x1;
893 tempout = (finalseed&0xFFFFFFFF) ^ ((finalseed>>32)&0xFFFFFFFF);
894 if ((tempout&0x80000000) == 0x80000000)
896 tempout = -1 * (tempout&0x7FFFFFFF);
900 tempout = 1 * (tempout&0x7FFFFFFF);
917 for (
size_t i = 0; i < digest.size(); i++)
924 temp |= (digest[i])<<(24-(j*8));
925 if ( (j==3) || (i==(digest.size()-1)))
931 if ((tempout & 0x80000000) == 0x80000000) {
932 tempout = -1 * (tempout & 0x7FFFFFFF);
934 tempout = (tempout & 0x7FFFFFFF);
953#ifdef __USE_DATABASE__
959 QwParitySchema::analysis analysis{};
960 auto update_query = sqlpp::update(analysis)
961 .set(analysis.seed_id =
fSeedID,
963 .where(analysis.analysis_id == db->GetAnalysisID());
967 auto c = db->GetScopedConnection();
968 db->QueryExecute(update_query);
985 QwParitySchema::bf_test bf_test{};
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),
999 auto c = db->GetScopedConnection();
1000 db->QueryExecute(insert_query);
1014 Bool_t status = kTRUE;
1018 double epsilon = std::numeric_limits<double>::epsilon();
1026 double test2 = checkval;
1027 if ((test1 - test2) <= -epsilon || (test1 - test2) >= epsilon) {
1028 QwError <<
"QwBlinder::CheckTestValues(): Unblinded test value "
1030 <<
" does not agree with original test value, "
1031 <<
"with a difference of "
1033 <<
" (epsilon==" << epsilon <<
")"
1041 if ((test1 - test2) <= -epsilon || (test1 - test2) >= epsilon) {
1042 QwError <<
"QwBlinder::CheckTestValues(): Unblinded test value "
1044 <<
" does not agree with original test value, "
1045 <<
"with a difference of "
1063 const UInt_t length = 16;
1064 UChar_t value[length];
1065 for (UInt_t i = 0; i < length; i++)
1070 md5.Update((UChar_t*) input.Data(), input.Length());
1074 std::vector<UChar_t> output;
1075 for (UInt_t i = 0; i < length; i++)
1076 output.push_back(value[i]);
1087 Int_t total_count = 0;
1091 if (total_count<=0)
return;
1101 QwMessage <<
"The blinding parameters checksum for seed ID "
1106 double epsilon = std::numeric_limits<double>::epsilon();
1110 << std::setw(16) <<
"Original value"
1111 << std::setw(16) <<
"Blinded value"
1112 << std::setw(22) <<
"Orig.-Unblind value"
1121 << std::setw(16) << Form(
" [CENSORED]")
1123 << std::setw(22) << diff
1168#ifdef __USE_DATABASE__
1169void QwBlinder::FillDB(QwParityDB *db, TString datatype)
1171 QwDebug <<
" --------------------------------------------------------------- " <<
QwLog::endl;
1173 QwDebug <<
" --------------------------------------------------------------- " <<
QwLog::endl;
1176 UInt_t analysis_id = db->GetAnalysisID();
1180 QwError <<
"QwBlinder::FillDB(): "
1181 <<
"Blinded test values have changed; "
1182 <<
"may be a problem in the analysis!!!"
1188 auto c = db->GetScopedConnection();
1192 QwParitySchema::analysis analysis{};
1194 auto update_query = sqlpp::update(analysis)
1195 .set(analysis.seed_id =
fSeedID,
1197 .where(analysis.analysis_id == analysis_id);
1200 db->QueryExecute(update_query);
1202 }
catch (
const std::exception& err) {
1209 QwParitySchema::bf_test bf_test{};
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),
1216 db->QueryExecute(insert_query);
1220 QwMessage <<
"QwBlinder::FillDB(): No bf_test entries to write."
1223 }
catch (
const std::exception& err) {
1228void QwBlinder::FillErrDB(QwParityDB *db, TString datatype)
1230 QwDebug <<
" --------------------------------------------------------------- " <<
QwLog::endl;
1232 QwDebug <<
" --------------------------------------------------------------- " <<
QwLog::endl;
1234 UInt_t analysis_id = db->GetAnalysisID();
1235 QwParitySchema::general_errors general_errors{};
1237 auto c = db->GetScopedConnection();
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,
1248 db->QueryExecute(insert_query);
1251 QwDebug <<
"Inserted blinder error counters for analysis " << analysis_id <<
QwLog::endl;
1253 }
catch (
const std::exception& err) {
1266 QwMessage <<
"QwBlinder: First set target blindability to "
1277 QwMessage <<
"QwBlinder: First set Wien state to "
1287 QwMessage <<
"QwBlinder: First set IHWP state to "
1300 QwDebug <<
"QwBlinder::CheckBlindability: The target blindability is not determined. "
1306 QwDebug <<
"QwBlinder::CheckBlindability: The target blindability has changed. "
1350 QwError <<
"QwBlinder::CheckBlindability: The pattern blindability is unclear. "
A logfile class, based on an identical class in the Hermes analyzer.
#define QwVerbose
Predefined log drain for verbose messages.
#define QwError
Predefined log drain for errors.
#define QwWarning
Predefined log drain for warnings.
#define QwMessage
Predefined log drain for regular messages.
#define QwDebug
Predefined log drain for debugging output.
Parameter file parsing and management.
Decoding and management for VQWK ADC channels (6x32-bit datawords)
std::string WienModeName(EQwWienMode type)
EQwWienMode
Double Wien configuration.
A class for blinding data, adapted from G0 blinder class.
unsigned long long ULong64_t
EQwBlinderErrorCounterIndices
Blinder event counter indices.
@ kBlinderCount_ChangedIHWP
@ kBlinderCount_UndefinedIHWP
@ kBlinderCount_NumCounters
@ kBlinderCount_Blindable
@ kBlinderCount_UnknownTarget
@ kBlinderCount_OtherFailure
@ kBlinderCount_NonBlindable
@ kBlinderCount_ChangedWien
@ kBlinderCount_ChangedTarget
@ kBlinderCount_Transverse
@ kBlinderCount_UndefinedWien
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.
Command-line and configuration file options processor.
T GetValue(const std::string &key)
Get a templated value.
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
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
QwBlinder(const EQwBlindingStrategy blinding_strategy=kAdditive)
Default constructor with optional database.
void InitTestValues(const int n)
Initializes fBlindingFactor from fSeed.
EQwBlinderStatus
Status of the blinding process or intermediate steps of the process.
Int_t ReadRandomSeed()
Read the seed string generated utilizing a random number generator.
std::vector< UChar_t > GenerateDigest(const TString &input) const
Writes fTestNumber and fBlindTestValue to DB for this analysis ID.
static const TString fStatusName[4]
EQwBlinderStatus fTargetBlindability_firstread
Indicates the first value received of the blindability of the target.
void WriteTestValues(QwParityDB *db)
Writes fSeedID and fBFChecksum to DB for this analysis ID.
Bool_t fTargetPositionForced
std::vector< double > fBlindTestValues
Vector of test values, original.
std::vector< double > fTestValues
Checksum in ASCII hex.
void UnBlindValue(Double_t &value) const
Asymmetry unblinding.
void PrintFinalValues(Int_t kVerbosity=1)
std::vector< UChar_t > fDigest
Default seed.
Double_t fBlindingOffset_Base
The term to be added to detector asymmetries.
static const TString kDefaultSeed
Seed string (seeds.seed)
std::vector< Int_t > fPatternCounters
Counts the number of events in each failure mode.
Int_t UsePseudorandom(const TString &barestring)
Double_t fBlindingFactor
The term to be added to detector asymmetries, before polarity correction.
void Update()
Update the status using a random number.
std::string fChecksum
Checksum in raw hex.
Double_t fBlindingOffset
Blinding strategy.
Double_t fBeamCurrentThreshold
std::vector< Int_t > fPairCounters
Counts the number of helicity pairs in each failure mode.
Double_t fMaximumBlindingAsymmetry
Default maximum blinding factor (in fraction from identity)
static const Double_t kDefaultMaximumBlindingAsymmetry
The factor to be multiplied to detector asymmetries.
static void DefineOptions(QwOptions &options)
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.
TString fSeed
ID of seed used (seeds.seed_id)
EQwWienMode fWienMode_firstread
void SetIHWPPolarity(Int_t ihwppolarity)
Bool_t fSpinDirectionForced
void WriteFinalValuesToDB(QwParityDB *db)
static const Double_t kDefaultMaximumBlindingFactor
Default maximum blinding asymmetry (in ppm)
EQwBlindingStrategy
Available blinding strategies.
@ kAdditiveMultiplicative
Int_t UseStringManip(const TString &barestring)
Returns an integer from a string using MD5.
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.
Double_t fMaximumBlindingFactor
Maximum blinding asymmetry (in ppm)
EQwBlinderStatus CheckBlindability(std::vector< Int_t > &fCounters)
std::vector< double > fUnBlindTestValues
Vector of test values, after blinding.
void InitBlinders(const UInt_t seed_id)
Vector of test values, after unblinding.
EQwBlindingStrategy fBlindingStrategy
UInt_t fSeedID
Maximum blinding factor (in fraction from identity)
Int_t fIHWPPolarity_firstread
virtual ~QwBlinder()
Default destructor.
EQwBlinderStatus fTargetBlindability
void ProcessOptions(QwOptions &options)
Update the status with new external information.
Subsystem array container specialized for parity analysis with asymmetry calculations.