#include "ProjectSerializer.h" #include #include "yaml-cpp/yaml.h" namespace YAML { template<> struct convert { static Node encode(const Daqromancy::DigitizerArgs& args) { Node node(NodeType::Map); node.force_insert("ConnectionType", args.type); node.force_insert("LinkNumber", args.linkNumber); node.force_insert("CONETNode", args.conetNode); node.force_insert("VMEAddress", args.vmeAddress); node.force_insert("Handle", args.handle); node.force_insert("Model", args.model); node.force_insert("Firmware", args.firmware); node.force_insert("Channels", args.channels); return node; } static bool decode(const Node& node, Daqromancy::DigitizerArgs& args) { if (!node.IsMap()) return false; args.type = (CAEN_DGTZ_ConnectionType) node["ConnectionType"].as(); args.linkNumber = node["LinkNumber"].as(); args.conetNode = node["ConetNode"].as(); args.vmeAddress = node["VMEAddress"].as(); args.handle = node["Handle"].as(); args.model = (CAEN_DGTZ_BoardModel_t) node["Model"].as(); args.firmware = (CAEN_DGTZ_DPPFirmware_t) node["Firmware"].as(); args.channels = node["Channels"].as(); return true; } }; template<> struct convert { static Node encode(const Daqromancy::DigitizerParameters& params) { Node node(NodeType::Map); node.force_insert("RecordLength", params.recordLength); node.force_insert("ChannelMask", params.channelMask); node.force_insert("EventAggr", params.eventAggr); node.force_insert("AcqMode", params.acqMode); node.force_insert("DPPAcqMode", params.dppAcqMode); node.force_insert("DPPSaveMode", params.dppSaveMode); node.force_insert("IOLevel", params.IOlevel); node.force_insert("TriggerMode", params.triggerMode); node.force_insert("SyncMode", params.syncMode); return node; } static bool decode(const Node& node, Daqromancy::DigitizerParameters& params) { if (!node.IsMap()) return false; params.recordLength = node["RecordLength"].as(); params.channelMask = node["ChannelMask"].as(); params.eventAggr = node["EventAggr"].as(); params.acqMode = (CAEN_DGTZ_AcqMode_t)node["AcqMode"].as(); params.dppAcqMode = (CAEN_DGTZ_DPP_AcqMode_t)node["DPPAcqMode"].as(); params.dppSaveMode = (CAEN_DGTZ_DPP_SaveParam_t)node["DPPSaveMode"].as(); params.IOlevel = (CAEN_DGTZ_IOLevel_t)node["IOLevel"].as(); params.triggerMode = (CAEN_DGTZ_TriggerMode_t)node["TriggerMode"].as(); params.syncMode = (CAEN_DGTZ_RunSyncMode_t)node["SyncMode"].as(); return true; } }; template<> struct convert { static Node encode(const Daqromancy::PHAParameters& params) { Node node(NodeType::Map); node.force_insert("IsEnabled", params.isEnabled); node.force_insert("PreTrigger", params.preTriggerTime); node.force_insert("DCOffset", params.dcOffset); node.force_insert("PulsePolarity", params.pulsePolarity); node.force_insert("DynamicRange", params.dynamicRange); node.force_insert("DecayTimeConst", params.decayTimeConst); node.force_insert("TrapFlatTop", params.trapFlatTop); node.force_insert("TrapRiseTime", params.trapRiseTime); node.force_insert("FlatTopDelay", params.flatTopDelay); node.force_insert("TriggerSmoothing", params.triggerFilterSmoothing); node.force_insert("InputRiseTime", params.inputRiseTime); node.force_insert("TriggerThreshold", params.triggerThreshold); node.force_insert("SamplesBaseline", params.samplesBaseLineMean); node.force_insert("SamplesPeak", params.samplesPeakMean); node.force_insert("PeakHoldoff", params.peakHoldOff); node.force_insert("BaselineHoldoff", params.baseLineHoldOff); node.force_insert("TriggerHoldoff", params.triggerHoldOff); node.force_insert("RiseTimeWindow", params.riseTimeValidationWindow); node.force_insert("RiseTimeDiscrimination", params.riseTimeDiscrimination); node.force_insert("DigitalProbeGain", params.digitalProbeGain); node.force_insert("EnergyNormFactor", params.energyNormalizationFactor); node.force_insert("InputDecimation", params.inputDecimation); return node; } static bool decode(const Node& node, Daqromancy::PHAParameters& params) { if (!node.IsMap()) return false; params.isEnabled = node["IsEnabled"].as(); params.preTriggerTime = node["PreTrigger"].as(); params.dcOffset = node["DCOffset"].as(); params.pulsePolarity = (CAEN_DGTZ_PulsePolarity_t)node["PulsePolarity"].as(); params.dynamicRange = (Daqromancy::DynamicRange)node["DynamicRange"].as(); params.decayTimeConst = node["DecayTimeConst"].as(); params.trapFlatTop = node["TrapFlatTop"].as(); params.trapRiseTime = node["TrapRiseTime"].as(); params.flatTopDelay = node["FlatTopDelay"].as(); params.triggerFilterSmoothing = node["TriggerSmoothing"].as(); params.inputRiseTime = node["InputRiseTime"].as(); params.triggerThreshold = node["TriggerThreshold"].as(); params.samplesBaseLineMean = node["SamplesBaseline"].as(); params.samplesPeakMean = node["SamplesPeak"].as(); params.peakHoldOff = node["PeakHoldoff"].as(); params.baseLineHoldOff = node["BaselineHoldoff"].as(); params.triggerHoldOff = node["TriggerHoldoff"].as(); params.riseTimeValidationWindow = node["RiseTimeWindow"].as(); params.riseTimeDiscrimination = node["RiseTimeDiscrimination"].as(); params.digitalProbeGain = node["DigitalProbeGain"].as(); params.energyNormalizationFactor = node["EnergyNormFactor"].as(); params.inputDecimation = node["InputDecimation"].as(); return true; } }; template<> struct convert { static Node encode(const Daqromancy::PSDParameters& params) { Node node(NodeType::Map); node.force_insert("IsEnabled", params.isEnabled); node.force_insert("PreTrigger", params.preTriggerTime); node.force_insert("DCOffset", params.dcOffset); node.force_insert("PulsePolarity", params.pulsePolarity); node.force_insert("DynamicRange", params.dynamicRange); node.force_insert("BaselineThreshold", params.baselineThreshold); node.force_insert("TriggerHoldoff", params.triggerHoldOff); node.force_insert("TriggerThreshold", params.triggerThreshold); node.force_insert("SelfTrigger", params.selfTrigger); node.force_insert("ChargeSensitivity", params.chargeSensitivity); node.force_insert("ShortGate", params.shortGate); node.force_insert("LongGate", params.longGate); node.force_insert("PreGate", params.preGate); node.force_insert("TriggerWindow", params.triggerValidationWindow); node.force_insert("BaselineSamples", params.samplesBasline); node.force_insert("DiscriminatorType", params.discrminatorType); node.force_insert("CFDFraction", params.cfdFraction); node.force_insert("CFDDelay", params.cfdDelay); node.force_insert("TriggerConfig", params.triggerConfig); node.force_insert("PileUpRejection", params.pileUpRejection); node.force_insert("PURGap", params.purgap); return node; } static bool decode(const Node& node, Daqromancy::PSDParameters& params) { if (!node.IsMap()) return false; params.isEnabled = node["IsEnabled"].as(); params.preTriggerTime = node["PreTrigger"].as(); params.dcOffset = node["DCOffset"].as(); params.pulsePolarity = (CAEN_DGTZ_PulsePolarity_t)node["PulsePolarity"].as(); params.dynamicRange = (Daqromancy::DynamicRange)node["DynamicRange"].as(); params.baselineThreshold = node["BaselineThreshold"].as(); params.triggerHoldOff = node["TriggerHoldoff"].as(); params.triggerThreshold = node["TriggerThreshold"].as(); params.selfTrigger = node["SelfTrigger"].as(); params.chargeSensitivity = node["ChargeSensitivity"].as(); params.shortGate = node["ShortGate"].as(); params.longGate = node["LongGate"].as(); params.preGate = node["PreGate"].as(); params.triggerValidationWindow = node["TriggerWindow"].as(); params.samplesBasline = node["BaselineSamples"].as(); params.discrminatorType = node["DiscriminatorType"].as(); params.cfdFraction = node["CFDFraction"].as(); params.cfdDelay = node["CFDDelay"].as(); params.triggerConfig = (CAEN_DGTZ_DPP_TriggerConfig_t)node["TriggerConfig"].as(); params.pileUpRejection = (CAEN_DGTZ_DPP_PUR_t)node["PileUpRejection"].as(); params.purgap = node["PURGap"].as(); return true; } }; template<> struct convert { static Node encode(const Daqromancy::PHAWaveParameters& waves) { Node node(NodeType::Map); node.force_insert("IsDual", waves.isDual); node.force_insert("AnalogProbe1", waves.analogProbe1); node.force_insert("AnalogProbe2", waves.analogProbe2); node.force_insert("DigitalProbe1", waves.digitalProbe1); return node; } static bool decode(const Node& node, Daqromancy::PHAWaveParameters& waves) { if (!node.IsMap()) return false; waves.isDual = (CAEN_DGTZ_DPP_VirtualProbe_t)node["IsDual"].as(); waves.analogProbe1 = (Daqromancy::PHAVirtualProbe1Options)node["AnalogProbe1"].as(); waves.analogProbe2 = (Daqromancy::PHAVirtualProbe2Options)node["AnalogProbe2"].as(); waves.digitalProbe1 = (Daqromancy::PHADigitalProbe1Options)node["DigitalProbe1"].as(); return true; } }; template<> struct convert { static Node encode(const Daqromancy::PSDWaveParameters& waves) { Node node(NodeType::Map); node.force_insert("IsDual", waves.isDual); node.force_insert("AnalogProbe1", waves.analogProbe1); node.force_insert("AnalogProbe2", waves.analogProbe2); node.force_insert("DigitalProbe1", waves.digitalProbe1); node.force_insert("DigitalProbe2", waves.digitalProbe2); return node; } static bool decode(const Node& node, Daqromancy::PSDWaveParameters& waves) { if (!node.IsMap()) return false; waves.isDual = (CAEN_DGTZ_DPP_VirtualProbe_t)node["IsDual"].as(); waves.analogProbe1 = (Daqromancy::PSDVirtualProbe1Options)node["AnalogProbe1"].as(); waves.analogProbe2 = (Daqromancy::PSDVirtualProbe2Options)node["AnalogProbe2"].as(); waves.digitalProbe1 = (Daqromancy::PSDDigitalProbe1Options)node["DigitalProbe1"].as(); waves.digitalProbe2 = (Daqromancy::PSDDigitalProbe2Options)node["DigitalProbe2"].as(); return true; } }; Emitter& operator<<(Emitter& stream, const Daqromancy::DigitizerArgs& args) { stream << YAML::BeginMap; stream << YAML::Key << "ConnectionType" << YAML::Value << args.type; stream << YAML::Key << "LinkNumber" << YAML::Value << args.linkNumber; stream << YAML::Key << "CONETNode" << YAML::Value << args.conetNode; stream << YAML::Key << "VMEAddress" << YAML::Value << args.vmeAddress; stream << YAML::Key << "Handle" << YAML::Value << args.handle; stream << YAML::Key << "Model" << YAML::Value << args.model; stream << YAML::Key << "Firmware" << YAML::Value << args.firmware; stream << YAML::Key << "Channels" << YAML::Value << args.channels; stream << YAML::EndMap; return stream; } Emitter& operator<<(Emitter& stream, const Daqromancy::DigitizerParameters& params) { stream << YAML::BeginMap; stream << YAML::Key << "RecordLength" << YAML::Value << params.recordLength; stream << YAML::Key << "ChannelMask" << YAML::Value << params.channelMask; stream << YAML::Key << "EventAggr" << YAML::Value << params.eventAggr; stream << YAML::Key << "AcqMode" << YAML::Value << params.acqMode; stream << YAML::Key << "DPPAcqMode" << YAML::Value << params.dppAcqMode; stream << YAML::Key << "DPPSaveMode" << YAML::Value << params.dppSaveMode; stream << YAML::Key << "IOLevel" << YAML::Value << params.IOlevel; stream << YAML::Key << "TriggerMode" << YAML::Value << params.triggerMode; stream << YAML::Key << "SyncMode" << YAML::Value << params.syncMode; stream << YAML::EndMap; return stream; } Emitter& operator<<(Emitter& stream, const Daqromancy::PHAParameters& params) { stream << YAML::BeginMap; stream << YAML::Key << "IsEnabled" << YAML::Value << params.isEnabled; stream << YAML::Key << "PreTrigger" << YAML::Value << params.preTriggerTime; stream << YAML::Key << "DCOffset" << YAML::Value << params.dcOffset; stream << YAML::Key << "PulsePolarity" << YAML::Value << params.pulsePolarity; stream << YAML::Key << "DynamicRange" << YAML::Value << params.dynamicRange; stream << YAML::Key << "DecayTimeConst" << YAML::Value << params.decayTimeConst; stream << YAML::Key << "TrapFlatTop" << YAML::Value << params.trapFlatTop; stream << YAML::Key << "TrapRiseTime" << YAML::Value << params.trapRiseTime; stream << YAML::Key << "FlatTopDelay" << YAML::Value << params.flatTopDelay; stream << YAML::Key << "TriggerSmoothing" << YAML::Value << params.triggerFilterSmoothing; stream << YAML::Key << "InputRiseTime" << YAML::Value << params.inputRiseTime; stream << YAML::Key << "TriggerThreshold" << YAML::Value << params.triggerThreshold; stream << YAML::Key << "SamplesBaseline" << YAML::Value << params.samplesBaseLineMean; stream << YAML::Key << "SamplesPeak" << YAML::Value << params.samplesPeakMean; stream << YAML::Key << "PeakHoldoff" << YAML::Value << params.peakHoldOff; stream << YAML::Key << "BaselineHoldoff" << YAML::Value << params.baseLineHoldOff; stream << YAML::Key << "TriggerHoldoff" << YAML::Value << params.triggerHoldOff; stream << YAML::Key << "RiseTimeWindow" << YAML::Value << params.riseTimeValidationWindow; stream << YAML::Key << "RiseTimeDiscrimination" << YAML::Value << params.riseTimeDiscrimination; stream << YAML::Key << "DigitalProbeGain" << YAML::Value << params.digitalProbeGain; stream << YAML::Key << "EnergyNormFactor" << YAML::Value << params.energyNormalizationFactor; stream << YAML::Key << "InputDecimation" << YAML::Value << params.inputDecimation; stream << YAML::EndMap; return stream; } Emitter& operator<<(Emitter& stream, const Daqromancy::PSDParameters& params) { stream << YAML::BeginMap; stream << YAML::Key << "IsEnabled" << YAML::Value << params.isEnabled; stream << YAML::Key << "PreTrigger" << YAML::Value << params.preTriggerTime; stream << YAML::Key << "DCOffset" << YAML::Value << params.dcOffset; stream << YAML::Key << "PulsePolarity" << YAML::Value << params.pulsePolarity; stream << YAML::Key << "DynamicRange" << YAML::Value << params.dynamicRange; stream << YAML::Key << "BaselineThreshold" << YAML::Value << params.baselineThreshold; stream << YAML::Key << "TriggerHoldoff" << YAML::Value << params.triggerHoldOff; stream << YAML::Key << "TriggerThreshold" << YAML::Value << params.triggerThreshold; stream << YAML::Key << "SelfTrigger" << YAML::Value << params.selfTrigger; stream << YAML::Key << "ChargeSensitivity" << YAML::Value << params.chargeSensitivity; stream << YAML::Key << "ShortGate" << YAML::Value << params.shortGate; stream << YAML::Key << "LongGate" << YAML::Value << params.longGate; stream << YAML::Key << "PreGate" << YAML::Value << params.preGate; stream << YAML::Key << "TriggerWindow" << YAML::Value << params.triggerValidationWindow; stream << YAML::Key << "BaselineSamples" << YAML::Value << params.samplesBasline; stream << YAML::Key << "DiscriminatorType" << YAML::Value << params.discrminatorType; stream << YAML::Key << "CFDFraction" << YAML::Value << params.cfdFraction; stream << YAML::Key << "CFDDelay" << YAML::Value << params.cfdDelay; stream << YAML::Key << "TriggerConfig" << YAML::Value << params.triggerConfig; stream << YAML::Key << "PileUpRejection" << YAML::Value << params.pileUpRejection; stream << YAML::Key << "PURGap" << YAML::Value << params.purgap; stream << YAML::EndMap; return stream; } Emitter& operator<<(Emitter& stream, const std::vector& channels) { stream << YAML::BeginSeq; for (const auto& params : channels) stream << params; stream << YAML::EndSeq; return stream; } Emitter& operator<<(Emitter& stream, const std::vector& channels) { stream << YAML::BeginSeq; for (const auto& params : channels) stream << params; stream << YAML::EndSeq; return stream; } Emitter& operator<<(Emitter& stream, const Daqromancy::PHAWaveParameters& waves) { stream << YAML::BeginMap; stream << YAML::Key << "IsDual" << YAML::Value << waves.isDual; stream << YAML::Key << "AnalogProbe1" << YAML::Value << waves.analogProbe1; stream << YAML::Key << "AnalogProbe2" << YAML::Value << waves.analogProbe1; stream << YAML::Key << "DigitalProbe1" << YAML::Value << waves.digitalProbe1; stream << YAML::EndMap; return stream; } Emitter& operator<<(Emitter& stream, const Daqromancy::PSDWaveParameters& waves) { stream << YAML::BeginMap; stream << YAML::Key << "IsDual" << YAML::Value << waves.isDual; stream << YAML::Key << "AnalogProbe1" << YAML::Value << waves.analogProbe1; stream << YAML::Key << "AnalogProbe2" << YAML::Value << waves.analogProbe1; stream << YAML::Key << "DigitalProbe1" << YAML::Value << waves.digitalProbe1; stream << YAML::Key << "DigitalProbe2" << YAML::Value << waves.digitalProbe2; stream << YAML::EndMap; return stream; } } namespace Daqromancy { ProjectSerializer::ProjectSerializer(const std::filesystem::path& filepath) : m_filepath(filepath) { } ProjectSerializer::~ProjectSerializer() {} void ProjectSerializer::SerializeData(const DYProject::Ref& project) { std::ofstream output(m_filepath); if (!output.is_open()) { DY_ERROR("Unable to open {0} to seralize project data!", m_filepath); return; } YAML::Emitter yamlStream; yamlStream << YAML::BeginMap; yamlStream << YAML::Key << "ProjectPath" << YAML::Value << project->GetProjectPath().string(); yamlStream << YAML::Key << "RunNumber" << YAML::Value << project->GetRunNumber(); yamlStream << YAML::Key << "DPPAcqMode" << YAML::Value << project->GetDPPAcqMode(); std::vector argList = project->GetDigitizerArgsList(); yamlStream << YAML::Key << "Digitizers" << YAML::Value << YAML::BeginSeq; for (auto& args : argList) { yamlStream << YAML::BeginMap; yamlStream << YAML::Key << "Digitizer" << YAML::Value << args.name; yamlStream << YAML::Key << "DigitizerArgs" << YAML::Value << args; yamlStream << YAML::Key << "DigitizerParameters" << YAML::Value << project->GetDigitizerParameters(args.handle); switch (args.firmware) { case CAEN_DGTZ_DPPFirmware_PHA: { yamlStream << YAML::Key << "PHAChannels" << YAML::Value << project->GetPHAParameters(args.handle); yamlStream << YAML::Key << "PHAWaves" << YAML::Value << project->GetPHAWaveParameters(args.handle); break; } case CAEN_DGTZ_DPPFirmware_PSD: { yamlStream << YAML::Key << "PSDChannels" << YAML::Value << project->GetPSDParameters(args.handle); yamlStream << YAML::Key << "PSDWaves" << YAML::Value << project->GetPSDWaveParameters(args.handle); break; } case CAEN_DGTZ_DPPFirmwareNotSupported: { break; } } yamlStream << YAML::EndMap; } yamlStream << YAML::EndSeq << YAML::EndMap; output << yamlStream.c_str(); output.close(); } void ProjectSerializer::DeserializeData(const DYProject::Ref& project) { YAML::Node data; try { data = YAML::LoadFile(m_filepath.string()); } catch (YAML::ParserException& e) { DY_ERROR("Unable to load in project settings from file {0}", m_filepath); return; } project->SetProjectPath(data["ProjectPath"].as()); project->SetRunNumber(data["RunNumber"].as()); project->SetDPPAcqMode((DPPAcqMode)data["DPPAcqMode"].as()); YAML::Node digitizers = data["Digitizers"]; //Init some memory for digitizer data DigitizerArgs args; DigitizerParameters params; std::vector phaChannels; std::vector psdChannels; PHAWaveParameters phaWaves; PSDWaveParameters psdWaves; if (digitizers) { for (auto dgtz : digitizers) { args = dgtz["DigitizerArgs"].as(); args.name = dgtz["Digitizer"].as(); params = dgtz["DigitizerParameters"].as(); switch (args.firmware) { case CAEN_DGTZ_DPPFirmware_PHA: { phaChannels = dgtz["PHAChannels"].as>(); phaWaves = dgtz["PHAWaves"].as(); if (args != project->GetDigitizerArgs(args.handle)) { DY_ERROR("When attempting to deserialize project settings, board mismatch detected at handle {0}! Stopping load, Daqromancy should be restarted.", args.handle); return; } project->SetDigitizerParameters(args.handle, params); project->SetPHAParameters(args.handle, phaChannels); project->SetPHAWaveParameters(args.handle, phaWaves); break; } case CAEN_DGTZ_DPPFirmware_PSD: { psdChannels = dgtz["PSDChannels"].as>(); psdWaves = dgtz["PSDWaves"].as(); if (args != project->GetDigitizerArgs(args.handle)) { DY_ERROR("When attempting to deserialize project settings, board mismatch detected at handle {0}! Stopping load, Daqromancy should be restarted.", args.handle); return; } project->SetDigitizerParameters(args.handle, params); project->SetPSDParameters(args.handle, psdChannels); project->SetPSDWaveParameters(args.handle, psdWaves); break; } case CAEN_DGTZ_DPPFirmwareNotSupported: { DY_WARN("Invalid firmware detected, this better just be a debug test"); if (args != project->GetDigitizerArgs(args.handle)) { DY_ERROR("When attempting to deserialize project settings, board mismatch detected at handle {0}! Stopping load, Daqromancy should be restarted.", args.handle); return; } project->SetDigitizerParameters(args.handle, params); } } } } } }