| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "na64calib/config-yaml.hh" | ||
| 2 | |||
| 3 | #include "na64detID/TBName.hh" | ||
| 4 | #include "na64calib/evType.hh" | ||
| 5 | #include "na64util/str-fmt.hh" | ||
| 6 | |||
| 7 | #include "na64detID/cellID.hh" | ||
| 8 | #include "na64detID/wireID.hh" | ||
| 9 | |||
| 10 | #include "na64calib/master-time.hh" | ||
| 11 | |||
| 12 | #include <fstream> | ||
| 13 | #include <cmath> | ||
| 14 | #include <stdexcept> | ||
| 15 | #include <yaml-cpp/node/node.h> | ||
| 16 | |||
| 17 | namespace na64dp { | ||
| 18 | namespace calib { | ||
| 19 | |||
| 20 | #if 0 | ||
| 21 | /**\brief Appends run index / data index configuration wrt YAML document | ||
| 22 | * | ||
| 23 | * This utility function fills run index and data loader indexes according | ||
| 24 | * to information provided in YAML node at the runtime. The given node has to | ||
| 25 | * be a list of entries each of that contains the validity period | ||
| 26 | * (`validFromRun`) and type string key referencing particular data loader | ||
| 27 | * instance. | ||
| 28 | * */ | ||
| 29 | void | ||
| 30 | configure_from_YAML( YAML::Node & rootNode | ||
| 31 | , RangeOverrideRunIndex * runIndex | ||
| 32 | , GenericLoader * loader | ||
| 33 | , const std::string & loaderName | ||
| 34 | , std::unordered_map<std::string, YAMLCalibInfoCtr> & ciCtrs | ||
| 35 | ) { | ||
| 36 | auto & L = log4cpp::Category::getInstance( "calibrations.yaml" ); | ||
| 37 | // Iterate over the node | ||
| 38 | for( YAML::const_iterator nodeIt = rootNode.begin() | ||
| 39 | ; rootNode.end() != nodeIt | ||
| 40 | ; ++nodeIt ) { | ||
| 41 | const std::string calibTypeName = nodeIt->first.as<std::string>(); | ||
| 42 | // Get the calibration index constructor by type | ||
| 43 | auto ctrIt = ciCtrs.find( calibTypeName ); | ||
| 44 | if( ciCtrs.end() == ctrIt ) { | ||
| 45 | if( "APIVersion" != calibTypeName ) { | ||
| 46 | L.warn( "Unable to get the calibration index constructor" | ||
| 47 | " \"%s\" (calibration data type is unknown, omitted)." | ||
| 48 | , calibTypeName.c_str() ); | ||
| 49 | } | ||
| 50 | continue; | ||
| 51 | } | ||
| 52 | const YAML::Node & node = nodeIt->second; | ||
| 53 | YAMLCalibInfoCtr & ctr = ctrIt->second; | ||
| 54 | // Construct the data index if it is not yet constructed (e.g. by | ||
| 55 | // previous calls) | ||
| 56 | if( ! ctr.dataIndexPtr ) { | ||
| 57 | assert( ctr.ctr ); | ||
| 58 | // Construct new data index | ||
| 59 | ctr.dataIndexPtr = ctr.ctr(); | ||
| 60 | L.info( "New calibration data index constructed %s: %p" | ||
| 61 | , util::calib_id_to_str(ctr.ciDataID).c_str() | ||
| 62 | , ctr.dataIndexPtr ); | ||
| 63 | // Add index to loader | ||
| 64 | loader->add_data_index( ctr.ciDataID, ctr.dataIndexPtr ); | ||
| 65 | } | ||
| 66 | // Add into both indexes | ||
| 67 | for( const auto & cdNode : node ) { | ||
| 68 | EventID validFromEvent( cdNode["validFromRun"].as<na64sw_runNo_t>() | ||
| 69 | , 0, 0 ); | ||
| 70 | // It is important to keep this two calls covariant: | ||
| 71 | // - add run index entry | ||
| 72 | runIndex->add_entry( validFromEvent | ||
| 73 | , ctr.ciDataID | ||
| 74 | , loaderName ); | ||
| 75 | // - add data entry | ||
| 76 | try { | ||
| 77 | ctr.dataIndexPtr->append( validFromEvent, cdNode ); | ||
| 78 | } catch( std::exception & e ) { | ||
| 79 | L.error( "While appending entry for %s event of \"%s\" data" | ||
| 80 | " an error occured." | ||
| 81 | , validFromEvent.to_str().c_str(), calibTypeName.c_str() ); | ||
| 82 | } | ||
| 83 | L.info( "Run (%p) and data (%p) indexes %s added from YAML on event %s." | ||
| 84 | , runIndex | ||
| 85 | , ctr.dataIndexPtr | ||
| 86 | , util::calib_id_to_str(ctr.ciDataID).c_str() | ||
| 87 | , validFromEvent.to_str().c_str() ); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | #endif | ||
| 92 | |||
| 93 | /// Internal function reading the YAML node with detector naming description | ||
| 94 | /// into `DetectorNaming` object. | ||
| 95 | /// | ||
| 96 | /// \todo Document the naming config API of v.0.2 | ||
| 97 | static nameutils::DetectorNaming | ||
| 98 | ✗ | mappings_from_yaml_API02( const YAML::Node & root ) { | |
| 99 | ✗ | auto & L = log4cpp::Category::getInstance( "calib" ); | |
| 100 | ✗ | nameutils::DetectorNaming r; | |
| 101 | ✗ | for( auto kv : root["chips"] ) { | |
| 102 | ✗ | const YAML::Node & pl = kv.second; | |
| 103 | ✗ | const std::string chipName = kv.first.as<std::string>(); | |
| 104 | // add chip with name and id | ||
| 105 | nameutils::DetectorNaming::ChipFeatures & ct | ||
| 106 | ✗ | = r.chip_add( chipName, pl["id"].as<int>()); | |
| 107 | // get basic fields from the YAML chip description | ||
| 108 | // - description string is rarely used, human-readable description of | ||
| 109 | // the chip | ||
| 110 | ✗ | ct.description = pl["desc"].as<std::string>(); | |
| 111 | |||
| 112 | ✗ | const YAML::Node & pats = pl["patterns"]; | |
| 113 | // - pathFormat is slash-separated path of objects, used to organaize | ||
| 114 | // various artifacts related to the detector entity: files, | ||
| 115 | // histograms, etc. | ||
| 116 | ✗ | ct.pathFormat = pats["path"].as<std::string>(); | |
| 117 | ✗ | ct.nameFormat = pats["name"].as<std::string>(); | |
| 118 | ✗ | ct.dddNameFormat = pats["tbname"].as<std::string>(); | |
| 119 | // TODO: think on better separation of the per-chip from-/to-string | ||
| 120 | // conversion routines as it is generally not a good idea to provide | ||
| 121 | // APV's conversion function to other chips (Straws TDC and F1) | ||
| 122 | ✗ | if( "SADC" == chipName ) { | |
| 123 | ✗ | ct.append_completion_context = CellID::append_completion_context; | |
| 124 | ✗ | ct.to_string = CellID::to_string; | |
| 125 | ✗ | ct.from_string = CellID::from_string; | |
| 126 | ✗ | } else if( "NA64WB" == chipName ) { | |
| 127 | ✗ | ct.append_completion_context = CellID::append_completion_context; | |
| 128 | ✗ | ct.to_string = CellID::to_string; | |
| 129 | ✗ | ct.from_string = CellID::from_string; | |
| 130 | ✗ | } else if( "APV" == chipName ) { | |
| 131 | ✗ | ct.append_completion_context = WireID::append_completion_context; | |
| 132 | ✗ | ct.to_string = WireID::to_string; | |
| 133 | ✗ | ct.from_string = WireID::from_string; | |
| 134 | ✗ | } else if( "NA64TDC" == chipName ) { | |
| 135 | ✗ | ct.append_completion_context = WireID::append_completion_context; | |
| 136 | ✗ | ct.to_string = WireID::to_string; | |
| 137 | ✗ | ct.from_string = WireID::from_string; | |
| 138 | ✗ | } else if( "F1" == chipName ) { | |
| 139 | ✗ | ct.append_completion_context = WireID::append_completion_context; | |
| 140 | ✗ | ct.to_string = WireID::to_string; | |
| 141 | ✗ | ct.from_string = WireID::from_string; | |
| 142 | /* ... add other chips here ... */ | ||
| 143 | } else { | ||
| 144 | ✗ | L.warn( "No to-/from-string conversion and text context appender" | |
| 145 | " functions will be defined for chip \"%s\"." | ||
| 146 | , chipName.c_str() ); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | ✗ | for( auto kv : root["kins"] ) { | |
| 150 | ✗ | const YAML::Node & pl = kv.second; | |
| 151 | try { | ||
| 152 | ✗ | if( pl["patterns"] ) { | |
| 153 | ✗ | const YAML::Node & pats = pl["patterns"]; | |
| 154 | ✗ | auto & kinFts = r.define_kin( kv.first.as<std::string>() | |
| 155 | ✗ | , pl["id"].as<int>() | |
| 156 | ✗ | , pl["chip"].as<std::string>() | |
| 157 | ✗ | , pats["name"].as<std::string>() | |
| 158 | ✗ | , pl["desc"].as<std::string>() | |
| 159 | ✗ | , pats["path"].as<std::string>() | |
| 160 | ); | ||
| 161 | ✗ | kinFts.dddNameFormat = pats["tbname"].as<std::string>(); | |
| 162 | ✗ | } else { | |
| 163 | ✗ | r.define_kin( kv.first.as<std::string>() | |
| 164 | ✗ | , pl["id"].as<int>() | |
| 165 | ✗ | , pl["chip"].as<std::string>() | |
| 166 | , "" | ||
| 167 | ✗ | , pl["desc"].as<std::string>() | |
| 168 | , "" | ||
| 169 | ); | ||
| 170 | } | ||
| 171 | ✗ | } catch(std::exception & e) { | |
| 172 | ✗ | L.error( "Exception occured on kin description \"%s\"." | |
| 173 | ✗ | , kv.first.as<std::string>().c_str() ); | |
| 174 | ✗ | throw; | |
| 175 | } | ||
| 176 | } | ||
| 177 | ✗ | return r; | |
| 178 | } | ||
| 179 | |||
| 180 | void | ||
| 181 | ✗ | YAML2Naming( const YAML::Node & node | |
| 182 | , Dispatcher & d) { | ||
| 183 | //if( node["version"] ?? ) ... | ||
| 184 | ✗ | d.set<nameutils::DetectorNaming>( "default" | |
| 185 | ✗ | , mappings_from_yaml_API02( node ) ); | |
| 186 | } | ||
| 187 | |||
| 188 | void | ||
| 189 | ✗ | YAML2EventTags( const YAML::Node & node | |
| 190 | , Dispatcher & d ) { | ||
| 191 | ✗ | EventBitTags bitTags(node); | |
| 192 | ✗ | d.set<EventBitTags>( "default" | |
| 193 | , bitTags ); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void | ||
| 197 | ✗ | _dispatch_master_time_setting( const YAML::Node & node | |
| 198 | , Dispatcher & d ) { | ||
| 199 | ✗ | std::string detName; | |
| 200 | float offset; | ||
| 201 | ✗ | std::vector<std::string> triggerTypes; | |
| 202 | ✗ | if( node.IsScalar() ) { | |
| 203 | // If scalar is provided we assume it to be just a detector name, | ||
| 204 | // referring to the instance where master time must be taken from | ||
| 205 | ✗ | detName = node.as<std::string>(); | |
| 206 | ✗ | offset = std::nanf("0"); | |
| 207 | ✗ | triggerTypes.push_back("phys"); | |
| 208 | ✗ | } else if( node.IsMap() ) { | |
| 209 | // If it is a map we expect it to have "detector" and "offset" fields | ||
| 210 | // denoting detector name and offset to use | ||
| 211 | ✗ | detName = node["detector"].as<std::string>(); | |
| 212 | ✗ | offset = node["offset"] ? node["offset"].as<float>() : std::nanf("0"); | |
| 213 | ✗ | if(node["triggerTypes"]) { | |
| 214 | ✗ | triggerTypes = node["triggerTypes"].as<std::vector<std::string>>(); | |
| 215 | } else { | ||
| 216 | ✗ | triggerTypes.push_back("masterTimeSource"); | |
| 217 | } | ||
| 218 | ✗ | } else if( node.IsSequence() ) { | |
| 219 | // A sequence must be interpreted as list of items for various item | ||
| 220 | // types | ||
| 221 | throw std::runtime_error("TODO: master time for multiple triggers is" | ||
| 222 | ✗ | " not yet supported"); // TODO | |
| 223 | } else { | ||
| 224 | ✗ | NA64DP_RUNTIME_ERROR("Bad YAML node type for master time setting."); | |
| 225 | } | ||
| 226 | ✗ | for(const auto & mtsType : triggerTypes) { | |
| 227 | ✗ | if(!d.has_subscribers<MasterTimeSource>(mtsType)) { | |
| 228 | ✗ | log4cpp::Category::getInstance("calib").debug("No subscribers for" | |
| 229 | " master time source info of type \"%s\";" | ||
| 230 | " (\"%s\" with offset is %f ns is not handled)" | ||
| 231 | , mtsType.c_str() | ||
| 232 | , detName.c_str(), offset ); | ||
| 233 | ✗ | continue; | |
| 234 | } | ||
| 235 | ✗ | log4cpp::Category::getInstance("calib").debug("Notifying that time from" | |
| 236 | " \"%s\" shall be considered as" | ||
| 237 | " master time for \"%s\" event type, offset is %f ns." | ||
| 238 | , detName.c_str() | ||
| 239 | , mtsType.c_str() | ||
| 240 | , offset ); | ||
| 241 | ✗ | d.set< MasterTimeSource >( mtsType, {detName, offset} ); | |
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | void | ||
| 246 | ✗ | dispatch_master_time_setting( const YAML::Node & node | |
| 247 | , Dispatcher & d ) { | ||
| 248 | ✗ | if( node.IsSequence() ) { | |
| 249 | ✗ | for(size_t nItem = 0; nItem < node.size(); ++nItem ) { | |
| 250 | ✗ | _dispatch_master_time_setting(node[nItem], d); | |
| 251 | } | ||
| 252 | } else { | ||
| 253 | ✗ | _dispatch_master_time_setting(node, d); | |
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | } // namespace na64dp::calib | ||
| 258 | } // namespace na64dp | ||
| 259 | |||
| 260 |