17#include "TObjString.h"
21#ifdef HAS_RNTUPLE_SUPPORT
22#include "ROOT/RNTupleModel.hxx"
23#include "ROOT/RField.hxx"
32#ifdef __USE_DATABASE__
33#include "QwParitySchema.h"
83#ifdef __USE_DATABASE__
87 po::value<bool>()->default_bool_value(
false),
88 "disable EPICS database access");
99#ifdef __USE_DATABASE__
119 std::string varname, varvalue;
128 QwDebug <<
"QwEPICSEvent::LoadChannelMap: keyword,value pair:"
130 if (varname ==
"NominalWienAngle"){
132 }
else if (varname ==
"BlinderReversalForRunTwo"){
137 }
else if (varname ==
"PrecessionReversal"){
143 QwError <<
"QwEPICSEvent::LoadChannelMap: "
144 <<
"Unknown keyword,variable pair: "
156 if (datatype ==
"") {
162 if (datatype ==
"int") datatypeid =
kEPICSInt;
167 if (
kDebug == 1) std::cout <<
"line read in the parameter file =" << lineread << std::endl;
187 name.ReplaceAll(
':',
'_');
193 tree->Branch(name, &(values[treeindex]), values.
LeafList(treeindex).c_str());
234#ifdef HAS_RNTUPLE_SUPPORT
235void QwEPICSEvent::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString& prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
244 values.push_back(0.0);
248 name.ReplaceAll(
':',
'_');
249 name.ReplaceAll(
'.',
'_');
254 auto field = model->MakeField<Double_t>(name.Data());
255 fieldPtrs.push_back(field);
256 }
catch (
const std::exception& e) {
259 fieldPtrs.push_back(
nullptr);
260 QwWarning <<
"EPICS field '" << name <<
"' already exists in RNTuple model, skipping duplicate creation" <<
QwLog::endl;
267void QwEPICSEvent::FillNTupleVector(std::vector<Double_t>& values)
const
281 values[treeindex] =
static_cast<Double_t
>(
fEPICSDataEvent[tagindex].StringValue.Hash());
312 if (
kDebug == 1) std::cout <<
"Here we are in 'CalculateRunningValues'!!"<<std::endl;
315 Bool_t anyFilled = kFALSE;
316 for (
size_t tagindex = 0; tagindex <
fEPICSDataEvent.size(); tagindex++) {
319 if (! anyFilled)
return;
354 <<
" giving a running average of "
360 <<
" seems to be not filled."<<std::endl;
394 if (
kDebug == 1) std::cout <<
"Here we are, entering 'ExtractEPICSValues'!!"<<std::endl;
402 std::stringstream ss(data, std::stringstream::in | std::stringstream::out);
406 string varname, varvalue;
429 return match->second;
555 tmpvalue = Double_t(atof(value.c_str()));
562 tmpvalue = Double_t(atol(value.c_str()));
574 Double_t average_of_squares = 0.0;
575 Double_t variance = 0.0;
576 Double_t sigma = 0.0;
578 std::cout <<
"##### EPICS Event Summary from PrintAverages() #####\n"
579 <<
"Total number of EPICS events in this run == "
581 << std::setw(20) << std::setiosflags(std::ios::left) <<
"Name"
583 <<
"Minimum Maximum"<<std::endl;
584 std::cout <<
"*****Non-string EPICS Variables*****" << std::endl;
597 variance = average_of_squares - (mean * mean);
599 sigma = sqrt(-1.0 * variance);
601 sigma = sqrt(variance);
604 std::cout << std::setw(20) << std::setiosflags(std::ios::left)
606 << std::setprecision(5) << std::setw(10)
607 <<mean<<
" " << std::setw(10)<<sigma<<
" " << std::setw(10)
611 std::cout << std::setw(20) << std::setiosflags(std::ios::left)
613 << std::setprecision(5) << std::setw(10)
620 std::cout <<
"*****String EPICS Variables are below, if any*****" << std::endl;
624 std::cout << std::setw(20) << std::setiosflags(std::ios::left)
626 <<tagindex<<
"\tand status is\t\t"
630 std::cout <<
"\t*****\tThis variable changed during the run. Only "
633 <<
"% of the events has this value.";
635 std::cout <<std::endl;
637 std::cout << std::setw(20) << std::setiosflags(std::ios::left)
639 <<
"No data..."<<std::endl;
650 QwMessage <<
"fEPICSVariableList[" << tagindex <<
"] == "
658 std::vector<Double_t> autogain_values;
659 std::vector<std::string>::iterator ptr_tag;
661 autogain_values.clear();
665 ptr_tag = tag_list.begin();
666 while (ptr_tag < tag_list.end()) {
671 return autogain_values;
679 Double_t average_of_squares = 0.0;
680 Double_t variance = 0.0;
681 Double_t sigma = 0.0;
684 std::ofstream output;
685 TString theEPICSDataFile;
686 theEPICSDataFile = getenv(
"QW_TMP");
687 theEPICSDataFile +=
"/QwEPICSData.txt";
688 output.open(theEPICSDataFile,std::ofstream::out);
690 if (output.is_open()) {
693 output <<
"##### EPICS Event Summary #####\n"
694 <<
"Total number of EPICS events in this run == "
696 << std::setw(20) << std::setiosflags(std::ios::left) <<
"Name"
698 <<
"Minimum Maximum"<<std::endl;
710 variance = average_of_squares - (mean * mean);
712 sigma = sqrt(-1.0 * variance);
714 sigma = sqrt(variance);
717 output << std::setw(20) << std::setiosflags(std::ios::left)
719 << std::setprecision(5) << std::setw(10)
720 <<mean<<
" " << std::setw(10)<<sigma<<
" " << std::setw(10)
724 output << std::setw(20) << std::setiosflags(std::ios::left)
726 << std::setprecision(5) << std::setw(10)
736 output << std::setw(20) << std::setiosflags(std::ios::left)
740 output << std::setw(20) << std::setiosflags(std::ios::left)
742 <<
"No data..."<<std::endl;
759 std::cerr <<
"The EPICS variable label and type arrays are not the same size!\n"
760 <<
"EPICS readback may be corrupted!"<<std::endl;
781#ifdef __USE_DATABASE__
791 auto c = db->GetScopedConnection();
792 QwParitySchema::slow_controls_settings slow_controls_settings;
793 bool recordsExist = c->QueryExists(
794 sqlpp::select(slow_controls_settings.slow_controls_settings_id)
795 .from(slow_controls_settings)
796 .where(slow_controls_settings.runlet_id == db->GetRunletID())
800 QwError <<
"This runlet already has slow controls entries in the database!" <<
QwLog::endl;
801 QwError <<
"Slow controls values from this replay will NOT be stored in the database." <<
QwLog::endl;
806 catch (
const std::exception& er) {
808 QwError <<
"Unable to determine if there are other slow controls entries in the database for this run. THERE MAY BE DUPLICATES." <<
QwLog::endl;
824 QwDebug <<
" -------------------------------------------------------------------------- " <<
QwLog::endl;
826 QwDebug <<
" -------------------------------------------------------------------------- " <<
QwLog::endl;
828 Double_t mean, average_of_squares, variance, sigma;
832 average_of_squares = 0.0;
839 UInt_t runlet_id = db->GetRunletID();
841 QwParitySchema::slow_controls_data slow_controls_data;
842 std::vector<QwParitySchema::row<QwParitySchema::slow_controls_data>> entrylist;
844 UInt_t sc_detector_id;
846 string table =
"slow_controls_data";
854 QwParitySchema::row<QwParitySchema::slow_controls_data> tmp_row;
859 tmp_row[slow_controls_data.runlet_id] = runlet_id;
860 tmp_row[slow_controls_data.sc_detector_id] = sc_detector_id;
862 if (!sc_detector_id)
continue;
874 variance = average_of_squares - (mean * mean);
876 sigma = sqrt(-1.0 * variance);
878 sigma = sqrt(variance);
883 tmp_row[slow_controls_data.n] =
static_cast<UInt_t
>(n_records);
884 tmp_row[slow_controls_data.value] = mean;
885 tmp_row[slow_controls_data.error] = sigma;
889 entrylist.push_back(tmp_row);
896 if( entrylist.size() ) {
897 auto c = db->GetScopedConnection();
898 QwDebug <<
"QwEPICSEvent::FillSlowControlsData::Writing to database now" <<
QwLog::endl;
902 for (
const auto& entry : entrylist) {
903 c->QueryExecute(entry.insert_into());
906 }
catch (
const std::exception &er) {
910 QwDebug <<
"QwEPICSEvent::FillSlowControlsData :: This is the case when the entrylist contains nothing " <<
QwLog::endl;
917 QwParitySchema::slow_controls_strings slow_controls_strings{};
918 std::vector<QwParitySchema::row<QwParitySchema::slow_controls_strings>> entrylist;
919 UInt_t sc_detector_id;
920 UInt_t runlet_id = db->GetRunletID();
921 string table =
"polarized_source";
929 QwParitySchema::row<QwParitySchema::slow_controls_strings> tmp_row;
934 tmp_row[slow_controls_strings.runlet_id] = runlet_id;
935 tmp_row[slow_controls_strings.sc_detector_id] = sc_detector_id;
937 if (!sc_detector_id)
continue;
943 QwWarning<<
"fEPICSDataEvent[tagindex].StringValue.Data() is not defined, tmp_row.value is set to an empty string."<<
QwLog::endl;
944 tmp_row[slow_controls_strings.value] = std::string(
"");
948 tmp_row[slow_controls_strings.value] = std::string(
fEPICSDataEvent[tagindex].StringValue.Data());
951 entrylist.push_back(tmp_row);
958 if( entrylist.size() ) {
959 auto c = db->GetScopedConnection();
960 QwDebug <<
"QwEPICSEvent::FillSlowControlsStrigs Writing to database now" <<
QwLog::endl;
964 for (
const auto& entry : entrylist) {
965 c->QueryExecute(entry.insert_into());
967 QwDebug <<
"Done executing sqlpp11 bulk insert for FillSlowControlsStrings"
969 }
catch (
const std::exception &er) {
973 QwDebug <<
"QwEPICSEvent::FillSlowControlsData :: This is the case when the entrylist contains nothing " <<
QwLog::endl;
981 QwParitySchema::slow_controls_settings slow_controls_settings{};
982 QwParitySchema::row<QwParitySchema::slow_controls_settings> tmp_row;
985 UInt_t runlet_id = db->GetRunletID();
986 tmp_row[slow_controls_settings.runlet_id] = runlet_id;
988 std::string precession_reversal;
992 precession_reversal =
"CCW";
994 precession_reversal =
"CW";
1004 tagindex =
FindIndex(
"qw:qt_mps_i_dcct");
1009 tmp_row[slow_controls_settings.qtor_current] = sqlpp::null;
1014 <<
" had no events during this run. "
1015 <<
"Send NULL word to the database."
1017 tmp_row[slow_controls_settings.qtor_current] = sqlpp::null;
1021 QwDebug <<
"Send the value of "
1025 <<
", to the database."
1027 tmp_row[slow_controls_settings.qtor_current] = qtorcurrent;
1039 tmp_row[slow_controls_settings.target_position] = sqlpp::null;
1045 <<
" changed during this run. "
1046 <<
"Send NULL word to the database."
1048 tmp_row[slow_controls_settings.target_position] = sqlpp::null;
1053 <<
" is not defined."
1054 <<
"Send NULL word to the database."
1056 tmp_row[slow_controls_settings.target_position] = sqlpp::null;
1060 QwDebug <<
"Send the value of "
1064 <<
", to the database."
1066 tmp_row[slow_controls_settings.target_position] =
1074 tagindex =
FindIndex(
"IGL1I00DI24_24M");
1080 tmp_row[slow_controls_settings.slow_helicity_plate] = sqlpp::null;
1086 <<
" changed during the run."
1087 <<
"Send NULL word to the database."
1089 tmp_row[slow_controls_settings.slow_helicity_plate] = sqlpp::null;
1094 <<
" is not defined."
1095 <<
"Send NULL word to the database."
1097 tmp_row[slow_controls_settings.slow_helicity_plate] = sqlpp::null;
1102 QwDebug <<
"Send the value of "
1106 <<
", to the database."
1108 tmp_row[slow_controls_settings.slow_helicity_plate] = std::string(
fEPICSDataEvent[tagindex].StringValue.Data());
1120 tmp_row[slow_controls_settings.passive_helicity_plate] = sqlpp::null;
1126 <<
" changed during the run."
1127 <<
"Send NULL word to the database."
1129 tmp_row[slow_controls_settings.passive_helicity_plate] = sqlpp::null;
1133 if (fabs(ihwp2_readback-13056)<1){
1135 QwDebug <<
"Send the value of "
1139 <<
", to the database."
1141 tmp_row[slow_controls_settings.passive_helicity_plate] = std::string(
"in");
1142 }
else if (fabs(ihwp2_readback-8960)<1){
1144 QwDebug <<
"Send the value of "
1148 <<
", to the database."
1150 tmp_row[slow_controls_settings.passive_helicity_plate] = std::string(
"out");
1154 <<
" is not defined."
1155 <<
"Send NULL word to the database."
1157 tmp_row[slow_controls_settings.passive_helicity_plate] = sqlpp::null;
1169 tmp_row[slow_controls_settings.wien_reversal] = sqlpp::null;
1175 <<
" changed during the run."
1176 <<
"Send NULL word to the database."
1178 tmp_row[slow_controls_settings.wien_reversal] = sqlpp::null;
1183 <<
" is not defined."
1184 <<
"Send NULL word to the database."
1186 tmp_row[slow_controls_settings.wien_reversal] = sqlpp::null;
1189 TString wien_enum[5] = {
"indeterminate",
1191 "transverse_vertical",
1192 "transverse_horizontal"};
1193 QwDebug <<
"Send the value of "
1197 <<
", to the database."
1199 tmp_row[slow_controls_settings.wien_reversal] =
1208 tmp_row[slow_controls_settings.precession_reversal] = std::string(
"reverse");
1210 tmp_row[slow_controls_settings.precession_reversal] = std::string(
"normal");
1215 tagindex =
FindIndex(
"qw:ChargeFeedback");
1221 tmp_row[slow_controls_settings.charge_feedback] = sqlpp::null;
1228 <<
" changed during the run."
1229 <<
"Send NULL word to the database."
1231 tmp_row[slow_controls_settings.charge_feedback] = sqlpp::null;
1237 <<
" is not defined."
1238 <<
"Send NULL word to the database."
1240 tmp_row[slow_controls_settings.charge_feedback] = sqlpp::null;
1247 QwDebug <<
"Send the value of "
1251 <<
", to the database."
1255 tmp_row[slow_controls_settings.charge_feedback] = std::string(tmpval.Data());
1262 auto c = db->GetScopedConnection();
1263 QwDebug <<
"QwEPICSEvent::FillSlowControlsSettings Writing to database now" <<
QwLog::endl;
1264 c->QueryExecute(tmp_row.insert_into());
1267 auto insert_stmt = sqlpp::insert_into(slow_controls_settings).set(
1268 slow_controls_settings.runlet_id = runlet_id,
1269 slow_controls_settings.precession_reversal = precession_reversal
1271 c->QueryExecute(insert_stmt);
1272 QwDebug <<
"QwEPICSEvent::FillSlowControlsSettings Successfully wrote to database" <<
QwLog::endl;
1273 }
catch (
const std::exception& er) {
1282 Bool_t local_debug =
false;
1284 TList *string_list =
new TList;
1285 string_list->SetOwner(
true);
1287 std::size_t tagindex = 0;
1294 epics_string +=
"---";
1300 epics_string +=
"empty";
1303 std::cout <<
"QwEPICSEvent::GetEPICSStringValues() "
1307 string_list -> Add(
new TObjString(epics_string));
1318 Bool_t local_debug =
false;
1320 TSeqCollection *file_list = gROOT->GetListOfFiles();
1324 Int_t size = file_list->GetSize();
1325 for (Int_t i=0; i<size; i++)
1327 TFile *file = (TFile*) file_list->At(i);
1330 std::cout <<
"QwEPICSEvent::WriteEPICSStringValue()"
1335 TTree *slow_tree = (TTree*) file->Get(
"slow");
1343 name.ReplaceAll(
':',
'_');
1344 TString name_type = name +
"/C";\
1346 Char_t epics_char[128];
1347 TString epics_string;
1349 TBranch *new_branch = slow_tree->Branch(name, epics_char, name_type);
1355 epics_string =
"empty";
1359 std::cout <<
"QwEPICSEvent::WriteEPICSStringValue()\n";
1360 std::cout << name <<
" " << epics_string << std::endl;
1364 sprintf(epics_char,
"%s", epics_string.Data());
1370 file -> Write(
"", TObject::kOverwrite);
1382 Int_t ihwppolarity = 0;
1390 QwWarning <<
"IHWP state is not well defined: '"
1400 QwWarning <<
"IHWP state is not well defined: '"
1405 QwDebug <<
"QwEPICSEvent::DetermineIHWPPolarity: "
1406 <<
"raw IHWP polarity is: "
1409 QwDebug <<
"QwEPICSEvent::DetermineIHWPPolarity: "
1410 <<
"IHWP polarity after extra reversal is: "
1412 return ihwppolarity;
1418 Double_t launchangle = 0.0;
1423 Double_t hoffset = 0.0;
1424 if (fabs(vwienangle)<10.0 && fabs(phiangle)<10.0){
1426 }
else if (fabs(vwienangle)>80.0 && fabs(phiangle)>80.0
1427 && fabs(vwienangle+phiangle)<10. ){
1429 }
else if (fabs(vwienangle)>80.0 && fabs(phiangle)>80.0
1430 && fabs(vwienangle+phiangle)>170. ){
1432 }
else if (fabs(vwienangle)>80.0 && fabs(phiangle)<10.0) {
1436 launchangle = hoffset+hwienangle;
1437 Double_t long_proj =
1439 if (long_proj > 0.5){
1441 }
else if (long_proj < -0.5){
1443 }
else if (fabs(long_proj)<0.25){
A logfile class, based on an identical class in the Hermes analyzer.
#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.
ROOT file and tree management wrapper classes.
Parameter file parsing and management.
EPICS data event handling and storage.
Basic data types and constants used throughout the Qweak analysis framework.
EQwWienMode WienModeIndex(TString name)
std::string WienModeName(EQwWienMode type)
EQwWienMode
Double Wien configuration.
Int_t AddEPICSTag(const string &tag, const string &table="", EQwEPICSDataType datatype=kEPICSFloat)
static void DefineOptions(QwOptions &options)
Define the configuration options.
Int_t DetermineIHWPPolarity() const
void ProcessOptions(QwOptions &options)
Process the configuration options.
std::vector< std::string > fEPICSVariableList
void WriteEPICSStringValues()
std::vector< EPICSVariableRecord > fEPICSDataEvent
void ExtractEPICSValues(const string &data, int event)
void FillSlowControlsSettings(QwParityDB *db)
Int_t LoadChannelMap(TString mapfile)
virtual ~QwEPICSEvent()
Virtual destructor.
Double_t fNominalWienAngle
Bool_t IsNumber(const string &word)
void FillSlowControlsStrings(QwParityDB *db)
int SetDataValue(const string &tag, const double value, const int event)
void PrintAverages() const
void CalculateRunningValues()
void ReportEPICSData() const
Int_t fExtraHelicityReversal
static void SetDefaultAutogainList(std::vector< std::string > &input_list)
static std::vector< std::string > fDefaultAutogainList
Default autogain list.
void FillDB(QwParityDB *db)
std::vector< EQwEPICSDataType > fEPICSVariableType
void SetDataLoaded(Bool_t flag)
EQwWienMode DetermineWienMode() const
void FillSlowControlsData(QwParityDB *db)
std::map< std::string, Int_t > fEPICSVariableMap
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
Construct the branch and tree vector.
std::vector< EPICSCumulativeRecord > fEPICSCumulativeData
static void InitDefaultAutogainList()
Initialize the default autogain list.
Int_t FindIndex(const string &tag) const
Find the index of an EPICS variable, or return error.
void FillTreeVector(QwRootTreeBranchVector &values) const
Fill the tree vector.
std::vector< Double_t > ReportAutogains(std::vector< std::string > tag_list=fDefaultAutogainList)
static const int kEPICS_OK
Double_t GetDataValue(const string &tag) const
static const Double_t kInvalidEPICSData
Int_t fNumberEPICSVariables
TString GetDataString(const string &tag) const
Bool_t fPrecessionReversal
std::vector< std::string > fEPICSTableList
EQwEPICSDataType
EPICS data types.
size_t fTreeArrayNumEntries
TList * GetEPICSStringValues()
void PrintVariableList() const
QwEPICSEvent()
Default constructor.
Bool_t fBlinderReversalForRunTwo
static const int kEPICS_Error
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.
T GetTypedNextToken()
Get next token into specific type.
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
Bool_t HasVariablePair(const std::string &separatorchars, std::string &varname, std::string &varvalue)
void TrimComment(const char commentchar)
A helper class to manage a vector of branch entries for ROOT trees.
size_type size() const noexcept
std::string LeafList(size_type start_index=0) const
void push_back(const std::string &name, const char type='D')
void SetValue(size_type index, Double_t val)