1
0
Fork 0
mirror of https://github.com/gwm17/Specter.git synced 2024-11-22 10:18:50 -05:00

Overhaul data id system. Now use a pairing function to map board-channel info to a unique id.

This commit is contained in:
Gordon McCann 2022-10-01 15:13:36 -04:00
parent a26ac08f34
commit c0b51c5ba9
11 changed files with 93 additions and 25 deletions

View File

@ -15,10 +15,12 @@ namespace Specter {
beamIntegrator("beamIntegrator")
{
SPEC_PROFILE_FUNCTION();
//Bind some parameters
manager->BindParameter(delayFLTime);
manager->BindParameter(delayFRTime);
manager->BindParameter(delayBLTime);
manager->BindParameter(delayBRTime);
//Bind parameters with some default histograms. Saves us the effort of making them in the UI.
manager->BindParameter(x1, 600, -300.0, 300.0);
manager->BindParameter(x2, 600, -300.0, 300.0);
@ -29,12 +31,24 @@ namespace Specter {
manager->BindParameter(cathode, 4096, 0.0, 4096);
manager->BindParameter(xavg_sabreCoinc, 600, -300.0, 300.0);
std::vector<std::string> sabre_list;
for (int i = 0; i < 127; i++)
//Example of injecting experiment specific info. I know that SABRE is only used in 16 channel digitizers,
//so I can make a simple incremental id for use with the UI so that the parameter names are human readable. We map this "simple" id
//to the more robust and universal Specter board/channel UUID using a std::unordered_map
//This is kind of a really simple example of injecting a channel map; more complicated and advanced versions could involve reading
//a text file to get detector ID information, detector channel number, etc.
std::vector<std::string> sabre_list; //list of names will allow us to create a summary histogram.
uint32_t uuid;
for (uint32_t board = 0; board < 7; board++)
{
sabre_list.push_back("sabre_" + std::to_string(i));
sabre.emplace_back(sabre_list[i]);
manager->BindParameter(sabre[i]);
for (uint32_t channel = 0; channel < 16; channel++)
{
//ImGui & spdlog come prepackaged with the fmt library, so make good use of it!
sabre_list.push_back(fmt::format("sabre_%d", board*16 + channel));
uuid = Utilities::GetBoardChannelUUID(board, channel);
sabre[uuid] = Parameter(sabre_list.back());
manager->BindParameter(sabre[uuid]);
}
}
//If you want to make a histogram default available, you can add one like this.
@ -52,70 +66,78 @@ namespace Specter {
//Do some physics!
void SPSAnalysisStage::AnalyzePhysicsEvent(const SpecEvent& event)
{
SPEC_PROFILE_FUNCTION();
//You might want some flags for coincidence cases
//Use statics to avoid allocating extra memory each call (these pipeline functions are called a lot!)
static bool sabreFlag;
//Most analysis stages will start kinda like this. Take the raw event data and
//put it into NavParameters using the hit id. Switches are perfect for this. Can also
//put it into Specter::Parameters using the hit id. Switches are perfect for this. Can also
//create mapping classes to use text-file-based id association (commonly called channel maps).
bool sabreFlag = false;
sabreFlag = false;
for(auto& hit : event)
{
if (hit.id < 127)
//Check the SABRE map first; use iterators from std::unordered_map.
//See std::unordered_map docs for more info if this sort of idiom is unfamiliar
auto iter = sabre.find(hit.id);
if (iter != sabre.end())
{
sabreFlag = true;
if (hit.longEnergy > sabre[hit.id].GetValue())
sabre[hit.id].SetValue(hit.longEnergy);
if (hit.longEnergy > iter->second.GetValue())
iter->second.SetValue(hit.longEnergy);
continue;
}
switch (hit.id)
{
case 129:
case s_scintLeftID:
{
if (hit.longEnergy > scintLeft.GetValue())
scintLeft.SetValue(hit.longEnergy);
break;
}
case 133:
case s_beamIntID:
{
beamIntegrator.Increment();
break;
}
case 135:
case s_cathodeID:
{
if (hit.longEnergy > cathode.GetValue())
cathode.SetValue(hit.longEnergy);
break;
}
case 136:
case s_delayFrontLeftID:
{
if (!delayFLTime.IsValid())
delayFLTime.SetValue(hit.timestamp / 1.0e3);
break;
}
case 137:
case s_delayFrontRightID:
{
if (!delayFRTime.IsValid())
delayFRTime.SetValue(hit.timestamp / 1.0e3);
break;
}
case 138:
case s_delayBackLeftID:
{
if (!delayBLTime.IsValid())
delayBLTime.SetValue(hit.timestamp / 1.0e3);
break;
}
case 139:
case s_delayBackRightID:
{
if (!delayBRTime.IsValid())
delayBRTime.SetValue(hit.timestamp / 1.0e3);
break;
}
case 141:
case s_anodeFrontID:
{
if (hit.longEnergy > anodeFront.GetValue())
anodeFront.SetValue(hit.longEnergy);
break;
}
case 143:
case s_anodeBackID:
{
if (hit.longEnergy > anodeBack.GetValue())
anodeBack.SetValue(hit.longEnergy);

View File

@ -31,7 +31,9 @@ namespace Specter {
Parameter cathode;
Parameter xavg_sabreCoinc;
std::vector<Parameter> sabre;
//For collections of parameters, prefer std::unordered_map or std::map over vector
//Better with use of UUIDs for board-channel pairs
std::unordered_map<uint32_t, Parameter> sabre;
//Create a few variables
Variable x1_weight;
@ -39,6 +41,19 @@ namespace Specter {
//Create a scaler
Scaler beamIntegrator;
//Define some board-channel ID's that we'll use. The static keyword means that we only need to calculate them once,
//constexpr allows us to use them in a switch (and makes them compile time evaluated)
//Note that to make them static constexpr we use literals (i.e. hardcoded) in the arguments
static constexpr uint32_t s_scintLeftID = Utilities::GetBoardChannelUUID(8, 0);
static constexpr uint32_t s_beamIntID = Utilities::GetBoardChannelUUID(8, 5);
static constexpr uint32_t s_cathodeID = Utilities::GetBoardChannelUUID(8, 7);
static constexpr uint32_t s_delayFrontLeftID = Utilities::GetBoardChannelUUID(8, 8);
static constexpr uint32_t s_delayFrontRightID = Utilities::GetBoardChannelUUID(8, 9);
static constexpr uint32_t s_delayBackLeftID = Utilities::GetBoardChannelUUID(8, 10);
static constexpr uint32_t s_delayBackRightID = Utilities::GetBoardChannelUUID(8, 11);
static constexpr uint32_t s_anodeFrontID = Utilities::GetBoardChannelUUID(8, 13);
static constexpr uint32_t s_anodeBackID = Utilities::GetBoardChannelUUID(8, 15);
};
}

View File

@ -103,6 +103,8 @@ target_sources(Specter PRIVATE
Specter/Physics/Daqromancy/DYFileSource.cpp
Specter/Physics/Daqromancy/DYOnlineSource.h
Specter/Physics/Daqromancy/DYOnlineSource.cpp
Specter/Utils/Functions.h
Specter/Utils/Functions.cpp
)
#ImPlot sources

View File

@ -34,5 +34,6 @@
#include "Specter/Events/Event.h"
#include "Specter/Utils/TestServerLayer.h"
#include "Specter/Utils/Instrumentor.h"
#include "Specter/Utils/Functions.h"
#endif

View File

@ -82,7 +82,7 @@ namespace Specter {
m_datum.shortEnergy = m_currentHit.energyShort;
m_datum.calEnergy = m_currentHit.energyCalibrated;
m_datum.timestamp = m_currentHit.timestamp;
m_datum.id = m_currentHit.board * m_nchannels_per_board + m_currentHit.channel;
m_datum.id = Utilities::GetBoardChannelUUID(m_currentHit.board, m_currentHit.channel);
return m_datum;
}

View File

@ -147,7 +147,7 @@ namespace Specter {
m_datum.shortEnergy = m_hit.energyShort;
m_datum.calEnergy = m_hit.energyCalibrated;
m_datum.timestamp = m_hit.timestamp;
m_datum.id = m_hit.board * m_nchannels_per_board + m_hit.channel;
m_datum.id = Utilities::GetBoardChannelUUID(m_hit.board, m_hit.channel);
}
return m_datum;

View File

@ -108,7 +108,7 @@ namespace Specter {
m_datum.longEnergy = m_dyHit.energy;
m_datum.shortEnergy = m_dyHit.energyShort;
m_datum.timestamp = m_dyHit.timestamp;
m_datum.id = m_dyHit.board * m_channelsPerBoard + m_dyHit.channel;
m_datum.id = Utilities::GetBoardChannelUUID(m_dyHit.board, m_dyHit.channel);
}
return m_datum;
}

View File

@ -27,7 +27,7 @@ namespace Specter {
m_datum.longEnergy = m_dyHit.energy;
m_datum.shortEnergy = m_dyHit.energyShort;
m_datum.timestamp = m_dyHit.timestamp;
m_datum.id = m_dyHit.board * m_channelsPerBoard + m_dyHit.channel;
m_datum.id = Utilities::GetBoardChannelUUID(m_dyHit.board, m_dyHit.channel);
}
else
{

View File

@ -0,0 +1,8 @@
#include "Functions.h"
namespace Specter {
namespace Utilities {
}
}

View File

@ -0,0 +1,19 @@
#ifndef SPEC_FUNCTIONS_H
#define SPEC_FUNCTIONS_H
namespace Specter {
namespace Utilities
{
//Use Szudzik pairing function to convert board/channel number pair to a single universal unqiue identifier (UUID)
//Allows us to unqiuely id board-channel combo even with a set of boards that don't have the same number of channels
//It's constexpr, since for each board/channel pair the value should be evaluated at compile time (and allows us to use values in a switch)
//This is mostly syntactic sugar. When board and channel are constexpr (read: literals) it gives a constexpr value, otherwise behaves same as any other function
constexpr uint32_t GetBoardChannelUUID(uint32_t board, uint32_t channel)
{
return board >= channel ? (board * board + board + channel) : (channel * channel + board);
}
}
}
#endif

View File

@ -18,5 +18,6 @@
#include "Specter/Core/Logger.h"
#include "Specter/Utils/Instrumentor.h"
#include "Specter/Utils/Functions.h"
#endif