mirror of
https://github.com/gwm17/Specter.git
synced 2024-11-26 20:28:49 -05:00
Compare commits
No commits in common. "8e9fcffa65348212015a7e19467ced87f9645d92" and "7fca02119e0771ceac684144b7dee4e70deb8ebd" have entirely different histories.
8e9fcffa65
...
7fca02119e
|
@ -75,15 +75,6 @@ target_sources(Specter PRIVATE
|
||||||
Specter/Physics/Caen/CompassOnlineSource.h
|
Specter/Physics/Caen/CompassOnlineSource.h
|
||||||
Specter/Physics/Caen/CompassRun.cpp
|
Specter/Physics/Caen/CompassRun.cpp
|
||||||
Specter/Physics/Caen/CompassRun.h
|
Specter/Physics/Caen/CompassRun.h
|
||||||
Specter/Physics/nscldaq/CharonOnlineSource.h
|
|
||||||
Specter/Physics/nscldaq/CharonOnlineSource.cpp
|
|
||||||
Specter/Physics/nscldaq/CharonClient.h
|
|
||||||
Specter/Physics/nscldaq/CharonClient.cpp
|
|
||||||
Specter/Physics/nscldaq/Unpackers/Unpacker.h
|
|
||||||
Specter/Physics/nscldaq/Unpackers/CaenUnpacker.h
|
|
||||||
Specter/Physics/nscldaq/Unpackers/CaenUnpacker.cpp
|
|
||||||
Specter/Physics/nscldaq/Unpackers/MesyTecUnpacker.h
|
|
||||||
Specter/Physics/nscldaq/Unpackers/MesyTecUnpacker.cpp
|
|
||||||
Specter/Editor/EditorLayer.cpp
|
Specter/Editor/EditorLayer.cpp
|
||||||
Specter/Editor/EditorLayer.h
|
Specter/Editor/EditorLayer.h
|
||||||
Specter/Editor/FileDialog.cpp
|
Specter/Editor/FileDialog.cpp
|
||||||
|
@ -115,7 +106,6 @@ target_sources(Specter PRIVATE
|
||||||
Specter/Utils/Functions.h
|
Specter/Utils/Functions.h
|
||||||
Specter/Utils/Functions.cpp
|
Specter/Utils/Functions.cpp
|
||||||
Specter/Utils/RandomGenerator.h
|
Specter/Utils/RandomGenerator.h
|
||||||
Specter/Utils/ThreadSafeQueue.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#ImPlot sources
|
#ImPlot sources
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Specter {
|
||||||
static bool onlineFlag = false;
|
static bool onlineFlag = false;
|
||||||
static bool offlineFlag = false;
|
static bool offlineFlag = false;
|
||||||
static std::vector<DataSource::SourceType> availTypes = { DataSource::SourceType::CompassOnline, DataSource::SourceType::CompassOffline, DataSource::SourceType::DaqromancyOnline,
|
static std::vector<DataSource::SourceType> availTypes = { DataSource::SourceType::CompassOnline, DataSource::SourceType::CompassOffline, DataSource::SourceType::DaqromancyOnline,
|
||||||
DataSource::SourceType::DaqromancyOffline, DataSource::SourceType::CharonOnline };
|
DataSource::SourceType::DaqromancyOffline };
|
||||||
|
|
||||||
if (m_openFlag)
|
if (m_openFlag)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +78,6 @@ namespace Specter {
|
||||||
{
|
{
|
||||||
m_bitflags = m_bitflags ^ CompassHeaders::EnergyCalibrated;
|
m_bitflags = m_bitflags ^ CompassHeaders::EnergyCalibrated;
|
||||||
}
|
}
|
||||||
ImGui::InputInt("Coinc. Window (ps)", &m_chosenWindow);
|
|
||||||
}
|
}
|
||||||
else if (m_chosenType == DataSource::SourceType::CompassOffline)
|
else if (m_chosenType == DataSource::SourceType::CompassOffline)
|
||||||
{
|
{
|
||||||
|
@ -91,13 +90,11 @@ namespace Specter {
|
||||||
auto temp = m_fileDialog.RenderFileDialog();
|
auto temp = m_fileDialog.RenderFileDialog();
|
||||||
if (!temp.first.empty() && temp.second == FileDialog::Type::OpenDir)
|
if (!temp.first.empty() && temp.second == FileDialog::Type::OpenDir)
|
||||||
m_chosenLocation = temp.first;
|
m_chosenLocation = temp.first;
|
||||||
ImGui::InputInt("Coinc. Window (ps)", &m_chosenWindow);
|
|
||||||
}
|
}
|
||||||
else if (m_chosenType == DataSource::SourceType::DaqromancyOnline)
|
else if (m_chosenType == DataSource::SourceType::DaqromancyOnline)
|
||||||
{
|
{
|
||||||
ImGui::InputText("Hostname", &m_chosenLocation);
|
ImGui::InputText("Hostname", &m_chosenLocation);
|
||||||
ImGui::InputText("Port", &m_chosenPort);
|
ImGui::InputText("Port", &m_chosenPort);
|
||||||
ImGui::InputInt("Coinc. Window (ps)", &m_chosenWindow);
|
|
||||||
}
|
}
|
||||||
else if (m_chosenType == DataSource::SourceType::DaqromancyOffline)
|
else if (m_chosenType == DataSource::SourceType::DaqromancyOffline)
|
||||||
{
|
{
|
||||||
|
@ -110,19 +107,22 @@ namespace Specter {
|
||||||
auto temp = m_fileDialog.RenderFileDialog();
|
auto temp = m_fileDialog.RenderFileDialog();
|
||||||
if (!temp.first.empty() && temp.second == FileDialog::Type::OpenDir)
|
if (!temp.first.empty() && temp.second == FileDialog::Type::OpenDir)
|
||||||
m_chosenLocation = temp.first;
|
m_chosenLocation = temp.first;
|
||||||
ImGui::InputInt("Coinc. Window (ps)", &m_chosenWindow);
|
|
||||||
}
|
|
||||||
else if (m_chosenType == DataSource::SourceType::CharonOnline)
|
|
||||||
{
|
|
||||||
ImGui::InputText("Hostname", &m_chosenLocation);
|
|
||||||
ImGui::InputText("Port", &m_chosenPort);
|
|
||||||
}
|
}
|
||||||
|
ImGui::InputInt("Coinc. Window (ps)", &m_chosenWindow);
|
||||||
|
|
||||||
|
|
||||||
if (ImGui::Button("Ok"))
|
if (ImGui::Button("Ok"))
|
||||||
{
|
{
|
||||||
PhysicsStartEvent event(m_chosenLocation, m_chosenType, m_chosenWindow, m_chosenPort, m_bitflags);
|
if (m_chosenType == DataSource::SourceType::CompassOffline || m_chosenType == DataSource::SourceType::DaqromancyOffline)
|
||||||
Application::Get().OnEvent(event);
|
{
|
||||||
|
PhysicsStartEvent event(m_chosenLocation, m_chosenType, m_chosenWindow, m_chosenPort, false, 0U);
|
||||||
|
Application::Get().OnEvent(event);
|
||||||
|
}
|
||||||
|
else if (m_chosenType == DataSource::SourceType::CompassOnline || m_chosenType == DataSource::SourceType::DaqromancyOnline)
|
||||||
|
{
|
||||||
|
PhysicsStartEvent event(m_chosenLocation, m_chosenType, m_chosenWindow, m_chosenPort, true, m_bitflags);
|
||||||
|
Application::Get().OnEvent(event);
|
||||||
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
|
@ -21,14 +21,15 @@ namespace Specter {
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//Bitflags is a final option for random crap needed for a source. Currently used for compass online to indicate header state.
|
//Bitflags is a final option for random crap needed for a source. Currently used for compass online to indicate header state.
|
||||||
PhysicsStartEvent(const std::string& loc, DataSource::SourceType type, uint64_t window, const std::string& port = "51489", uint16_t bitflags = 0) :
|
PhysicsStartEvent(const std::string& loc, DataSource::SourceType type, uint64_t window, const std::string& port = "51489", bool sortFlag=false, uint16_t bitflags = 0) :
|
||||||
m_sourceLocation(loc), m_port(port), m_sourceType(type), m_coincidenceWindow(window), m_bitflags(bitflags)
|
m_sourceLocation(loc), m_port(port), m_sourceType(type), m_coincidenceWindow(window), m_sortFlag(sortFlag), m_bitflags(bitflags)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline const std::string GetSourceLocation() const { return m_sourceLocation; }
|
inline const std::string GetSourceLocation() const { return m_sourceLocation; }
|
||||||
inline const std::string GetSourcePort() const { return m_port; }
|
inline const std::string GetSourcePort() const { return m_port; }
|
||||||
inline const DataSource::SourceType GetSourceType() const { return m_sourceType; }
|
inline const DataSource::SourceType GetSourceType() const { return m_sourceType; }
|
||||||
inline const uint64_t GetCoincidenceWindow() const { return m_coincidenceWindow; }
|
inline const uint64_t GetCoincidenceWindow() const { return m_coincidenceWindow; }
|
||||||
|
inline const bool GetSortFlag() const { return m_sortFlag; }
|
||||||
inline const uint16_t GetBitFlags() const { return m_bitflags; }
|
inline const uint16_t GetBitFlags() const { return m_bitflags; }
|
||||||
|
|
||||||
std::string ToString() const override
|
std::string ToString() const override
|
||||||
|
@ -44,6 +45,7 @@ namespace Specter {
|
||||||
std::string m_port;
|
std::string m_port;
|
||||||
DataSource::SourceType m_sourceType;
|
DataSource::SourceType m_sourceType;
|
||||||
uint64_t m_coincidenceWindow;
|
uint64_t m_coincidenceWindow;
|
||||||
|
bool m_sortFlag;
|
||||||
uint16_t m_bitflags;
|
uint16_t m_bitflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ namespace Specter {
|
||||||
void ImGuiLayer::OnImGuiRender()
|
void ImGuiLayer::OnImGuiRender()
|
||||||
{
|
{
|
||||||
//Demo's used to figure out how to do things.
|
//Demo's used to figure out how to do things.
|
||||||
//Should not be on for actual SpecProject for
|
//Should not be on for actual NavProject for
|
||||||
//real use
|
//real use
|
||||||
//static bool show = true;
|
//static bool show = true;
|
||||||
//ImGui::ShowDemoWindow(&show);
|
//ImGui::ShowDemoWindow(&show);
|
||||||
|
|
|
@ -22,10 +22,9 @@
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
CompassOnlineSource::CompassOnlineSource(const std::string& hostname, const std::string& port, uint16_t header, uint64_t coincidenceWindow) :
|
CompassOnlineSource::CompassOnlineSource(const std::string& hostname, const std::string& port, uint16_t header) :
|
||||||
DataSource(coincidenceWindow), m_bufferIter(nullptr), m_bufferEnd(nullptr), m_header(header)
|
DataSource(), m_bufferIter(nullptr), m_bufferEnd(nullptr), m_header(header)
|
||||||
{
|
{
|
||||||
m_eventBuilder.SetSortFlag(true);
|
|
||||||
InitConnection(hostname, port);
|
InitConnection(hostname, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,14 +52,15 @@ namespace Specter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompassOnlineSource::ProcessData()
|
const SpecData& CompassOnlineSource::GetData()
|
||||||
{
|
{
|
||||||
SPEC_PROFILE_FUNCTION();
|
SPEC_PROFILE_FUNCTION();
|
||||||
size_t range = m_bufferEnd - m_bufferIter; //how much buffer we have left
|
size_t range = m_bufferEnd - m_bufferIter; //how much buffer we have left
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
{
|
{
|
||||||
SPEC_ERROR("Attempting to access invalid source at CompassOnlineSource!");
|
SPEC_ERROR("Attempting to access invalid source at CompassOnlineSource!");
|
||||||
return;
|
m_datum = SpecData();
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
else if (m_bufferIter == nullptr || range < m_datasize || m_bufferIter == m_bufferEnd) //If no buffer/buffer completely used/buffer fragmented fill
|
else if (m_bufferIter == nullptr || range < m_datasize || m_bufferIter == m_bufferEnd) //If no buffer/buffer completely used/buffer fragmented fill
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,8 @@ namespace Specter {
|
||||||
GetHit();
|
GetHit();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return;
|
m_datum = SpecData();
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_datum.longEnergy = m_currentHit.energy;
|
m_datum.longEnergy = m_currentHit.energy;
|
||||||
|
@ -80,10 +81,7 @@ namespace Specter {
|
||||||
m_datum.timestamp = m_currentHit.timestamp;
|
m_datum.timestamp = m_currentHit.timestamp;
|
||||||
m_datum.id = Utilities::GetBoardChannelUUID(m_currentHit.board, m_currentHit.channel);
|
m_datum.id = Utilities::GetBoardChannelUUID(m_currentHit.board, m_currentHit.channel);
|
||||||
|
|
||||||
if(m_eventBuilder.AddDatum(m_datum))
|
return m_datum;
|
||||||
{
|
|
||||||
m_isEventReady = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompassOnlineSource::FillBuffer()
|
void CompassOnlineSource::FillBuffer()
|
||||||
|
|
|
@ -36,15 +36,10 @@ namespace Specter {
|
||||||
class CompassOnlineSource : public DataSource
|
class CompassOnlineSource : public DataSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompassOnlineSource(const std::string& hostname, const std::string& port, uint16_t header, uint64_t coincidenceWindow);
|
CompassOnlineSource(const std::string& hostname, const std::string& port, uint16_t header);
|
||||||
virtual ~CompassOnlineSource() override;
|
virtual ~CompassOnlineSource() override;
|
||||||
|
|
||||||
virtual void ProcessData() override;
|
virtual const SpecData& GetData() override;
|
||||||
virtual const std::vector<SpecEvent>& GetEvents() override
|
|
||||||
{
|
|
||||||
m_isEventReady = false;
|
|
||||||
return m_eventBuilder.GetReadyEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitConnection(const std::string& hostname, const std::string& port);
|
void InitConnection(const std::string& hostname, const std::string& port);
|
||||||
|
|
|
@ -26,8 +26,13 @@
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
CompassRun::CompassRun(const std::string& dir, uint64_t coincidenceWindow) :
|
CompassRun::CompassRun() :
|
||||||
DataSource(coincidenceWindow), m_directory(dir), m_startIndex(0)
|
DataSource(), m_directory(""), m_startIndex(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CompassRun::CompassRun(const std::string& dir) :
|
||||||
|
DataSource(), m_directory(dir), m_startIndex(0)
|
||||||
{
|
{
|
||||||
CollectFiles();
|
CollectFiles();
|
||||||
}
|
}
|
||||||
|
@ -124,32 +129,32 @@ namespace Specter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompassRun::ProcessData()
|
const SpecData& CompassRun::GetData()
|
||||||
{
|
{
|
||||||
SPEC_PROFILE_FUNCTION();
|
SPEC_PROFILE_FUNCTION();
|
||||||
if(!IsValid())
|
if(!IsValid())
|
||||||
{
|
{
|
||||||
SPEC_ERROR("Trying to access CompassRun data when invalid, bug detected!");
|
SPEC_ERROR("Trying to access CompassRun data when invalid, bug detected!");
|
||||||
return;
|
m_datum = SpecData();
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetHitsFromFiles())
|
if (!GetHitsFromFiles())
|
||||||
{
|
{
|
||||||
m_validFlag = false;
|
m_validFlag = false;
|
||||||
return;
|
m_datum = SpecData();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
//Convert data from CoMPASS format to universal Specter format.
|
|
||||||
m_datum.longEnergy = m_hit.energy;
|
|
||||||
m_datum.shortEnergy = m_hit.energyShort;
|
|
||||||
m_datum.calEnergy = m_hit.energyCalibrated;
|
|
||||||
m_datum.timestamp = m_hit.timestamp;
|
|
||||||
m_datum.id = Utilities::GetBoardChannelUUID(m_hit.board, m_hit.channel);
|
|
||||||
|
|
||||||
if(m_eventBuilder.AddDatum(m_datum))
|
|
||||||
{
|
{
|
||||||
m_isEventReady = true;
|
//Convert data from CoMPASS format to universal Specter format.
|
||||||
|
m_datum.longEnergy = m_hit.energy;
|
||||||
|
m_datum.shortEnergy = m_hit.energyShort;
|
||||||
|
m_datum.calEnergy = m_hit.energyCalibrated;
|
||||||
|
m_datum.timestamp = m_hit.timestamp;
|
||||||
|
m_datum.id = Utilities::GetBoardChannelUUID(m_hit.board, m_hit.channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,15 +33,12 @@ namespace Specter {
|
||||||
|
|
||||||
class CompassRun : public DataSource
|
class CompassRun : public DataSource
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CompassRun(const std::string& dir, uint64_t coincidenceWindow);
|
CompassRun();
|
||||||
|
CompassRun(const std::string& dir);
|
||||||
virtual ~CompassRun();
|
virtual ~CompassRun();
|
||||||
virtual void ProcessData() override;
|
virtual const SpecData& GetData() override;
|
||||||
virtual const std::vector<SpecEvent>& GetEvents() override
|
|
||||||
{
|
|
||||||
m_isEventReady = false;
|
|
||||||
return m_eventBuilder.GetReadyEvents();
|
|
||||||
}
|
|
||||||
inline void SetDirectory(const std::string& dir) { m_directory = dir; CollectFiles(); }
|
inline void SetDirectory(const std::string& dir) { m_directory = dir; CollectFiles(); }
|
||||||
inline void SetShiftMap(const std::string& filename) { m_smap.SetFile(filename); }
|
inline void SetShiftMap(const std::string& filename) { m_smap.SetFile(filename); }
|
||||||
|
|
||||||
|
@ -61,7 +58,6 @@ namespace Specter {
|
||||||
CompassHit m_hit;
|
CompassHit m_hit;
|
||||||
|
|
||||||
unsigned int m_totalHits;
|
unsigned int m_totalHits;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
DYFileSource::DYFileSource(const std::string& directory, uint64_t coicidenceWindow) :
|
DYFileSource::DYFileSource(const std::string& directory) :
|
||||||
DataSource(coicidenceWindow), m_directory(directory)
|
DataSource(), m_directory(directory)
|
||||||
{
|
{
|
||||||
CollectFiles();
|
CollectFiles();
|
||||||
}
|
}
|
||||||
|
@ -88,26 +88,28 @@ namespace Specter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DYFileSource::ProcessData()
|
const SpecData& DYFileSource::GetData()
|
||||||
{
|
{
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
{
|
{
|
||||||
SPEC_ERROR("Trying to access DYFileSource data when invalid, bug detected!");
|
SPEC_ERROR("Trying to access DYFileSource data when invalid, bug detected!");
|
||||||
return;
|
m_datum = SpecData();
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetNextHit())
|
if (!GetNextHit())
|
||||||
{
|
{
|
||||||
m_validFlag = false;
|
m_validFlag = false;
|
||||||
|
m_datum = SpecData();
|
||||||
}
|
}
|
||||||
//Convert data from Daqromancy format to universal Specter format.
|
else
|
||||||
m_datum.longEnergy = m_dyHit.energy;
|
|
||||||
m_datum.shortEnergy = m_dyHit.energyShort;
|
|
||||||
m_datum.timestamp = m_dyHit.timestamp;
|
|
||||||
m_datum.id = Utilities::GetBoardChannelUUID(m_dyHit.board, m_dyHit.channel);
|
|
||||||
if(m_eventBuilder.AddDatum(m_datum))
|
|
||||||
{
|
{
|
||||||
m_isEventReady = true;
|
//Convert data from Daqromancy format to universal Specter format.
|
||||||
|
m_datum.longEnergy = m_dyHit.energy;
|
||||||
|
m_datum.shortEnergy = m_dyHit.energyShort;
|
||||||
|
m_datum.timestamp = m_dyHit.timestamp;
|
||||||
|
m_datum.id = Utilities::GetBoardChannelUUID(m_dyHit.board, m_dyHit.channel);
|
||||||
}
|
}
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,15 +10,10 @@ namespace Specter {
|
||||||
class DYFileSource : public DataSource
|
class DYFileSource : public DataSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DYFileSource(const std::string& directory, uint64_t coincidenceWindow);
|
DYFileSource(const std::string& directory);
|
||||||
virtual ~DYFileSource();
|
virtual ~DYFileSource();
|
||||||
|
|
||||||
virtual void ProcessData() override;
|
virtual const SpecData& GetData() override;
|
||||||
virtual const std::vector<SpecEvent>& GetEvents() override
|
|
||||||
{
|
|
||||||
m_isEventReady = false;
|
|
||||||
return m_eventBuilder.GetReadyEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CollectFiles();
|
void CollectFiles();
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
DYOnlineSource::DYOnlineSource(const std::string& hostname, const std::string& port, uint64_t coincidenceWindow) :
|
DYOnlineSource::DYOnlineSource(const std::string& hostname, const std::string& port) :
|
||||||
DataSource(coincidenceWindow), m_clientConnection(hostname, port)
|
DataSource(), m_clientConnection(hostname, port)
|
||||||
{
|
{
|
||||||
m_eventBuilder.SetSortFlag(true);
|
|
||||||
m_validFlag = m_clientConnection.IsConnected();
|
m_validFlag = m_clientConnection.IsConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +12,13 @@ namespace Specter {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DYOnlineSource::ProcessData()
|
const SpecData& DYOnlineSource::GetData()
|
||||||
{
|
{
|
||||||
if (!m_clientConnection.IsConnected())
|
if (!m_clientConnection.IsConnected())
|
||||||
{
|
{
|
||||||
m_validFlag = false;
|
m_validFlag = false;
|
||||||
return;
|
m_datum = SpecData();
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_clientConnection.GetNextEvent(m_dyHit))
|
if (m_clientConnection.GetNextEvent(m_dyHit))
|
||||||
|
@ -28,8 +28,12 @@ namespace Specter {
|
||||||
m_datum.shortEnergy = m_dyHit.energyShort;
|
m_datum.shortEnergy = m_dyHit.energyShort;
|
||||||
m_datum.timestamp = m_dyHit.timestamp;
|
m_datum.timestamp = m_dyHit.timestamp;
|
||||||
m_datum.id = Utilities::GetBoardChannelUUID(m_dyHit.board, m_dyHit.channel);
|
m_datum.id = Utilities::GetBoardChannelUUID(m_dyHit.board, m_dyHit.channel);
|
||||||
if(m_eventBuilder.AddDatum(m_datum))
|
|
||||||
m_isEventReady = true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_datum = SpecData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_datum;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,19 +9,15 @@ namespace Specter {
|
||||||
class DYOnlineSource : public DataSource
|
class DYOnlineSource : public DataSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DYOnlineSource(const std::string& hostname, const std::string& port, uint64_t coincidenceWindow);
|
DYOnlineSource(const std::string& hostname, const std::string& port);
|
||||||
virtual ~DYOnlineSource();
|
~DYOnlineSource();
|
||||||
|
|
||||||
virtual void ProcessData() override;
|
virtual const SpecData& GetData() override;
|
||||||
virtual const std::vector<SpecEvent>& GetEvents() override
|
|
||||||
{
|
|
||||||
m_isEventReady = false;
|
|
||||||
return m_eventBuilder.GetReadyEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DaqGrimoire::DYClient m_clientConnection;
|
DaqGrimoire::DYClient m_clientConnection;
|
||||||
DaqGrimoire::DYListData m_dyHit;
|
DaqGrimoire::DYListData m_dyHit;
|
||||||
|
int m_channelsPerBoard;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,19 @@
|
||||||
#include "Caen/CompassOnlineSource.h"
|
#include "Caen/CompassOnlineSource.h"
|
||||||
#include "Daqromancy/DYFileSource.h"
|
#include "Daqromancy/DYFileSource.h"
|
||||||
#include "Daqromancy/DYOnlineSource.h"
|
#include "Daqromancy/DYOnlineSource.h"
|
||||||
#include "nscldaq/CharonOnlineSource.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
//loc=either an ip address or a file location, port=address port, or unused in case of file
|
//loc=either an ip address or a file location, port=address port, or unused in case of file
|
||||||
DataSource* CreateDataSource(const std::string& location, const std::string& port, uint16_t header, DataSource::SourceType type, uint64_t coincidenceWindow)
|
DataSource* CreateDataSource(const std::string& location, const std::string& port, uint16_t header, DataSource::SourceType type)
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DataSource::SourceType::CompassOffline: return new CompassRun(location, coincidenceWindow);
|
case DataSource::SourceType::CompassOffline : return new CompassRun(location);
|
||||||
case DataSource::SourceType::CompassOnline: return new CompassOnlineSource(location, port, header, coincidenceWindow);
|
case DataSource::SourceType::CompassOnline : return new CompassOnlineSource(location, port, header);
|
||||||
case DataSource::SourceType::DaqromancyOffline: return new DYFileSource(location, coincidenceWindow);
|
case DataSource::SourceType::DaqromancyOffline: return new DYFileSource(location);
|
||||||
case DataSource::SourceType::DaqromancyOnline: return new DYOnlineSource(location, port, coincidenceWindow);
|
case DataSource::SourceType::DaqromancyOnline: return new DYOnlineSource(location, port);
|
||||||
case DataSource::SourceType::CharonOnline: return new CharonOnlineSource(location, port);
|
case DataSource::SourceType::None : return nullptr;
|
||||||
case DataSource::SourceType::None: return nullptr;
|
|
||||||
}
|
}
|
||||||
SPEC_WARN("Invalid DataSourceType at CreateDataSource!");
|
SPEC_WARN("Invalid DataSourceType at CreateDataSource!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -36,11 +34,10 @@ namespace Specter {
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DataSource::SourceType::None: return "None";
|
case DataSource::SourceType::None: return "None";
|
||||||
case DataSource::SourceType::CompassOnline: return "CompassOnline";
|
case DataSource::SourceType::CompassOnline : return "CompassOnline";
|
||||||
case DataSource::SourceType::CompassOffline: return "CompassOffline";
|
case DataSource::SourceType::CompassOffline : return "CompassOffline";
|
||||||
case DataSource::SourceType::DaqromancyOffline: return "DaqromancyOffline";
|
case DataSource::SourceType::DaqromancyOffline: return "DaqromancyOffline";
|
||||||
case DataSource::SourceType::DaqromancyOnline: return "DaqromancyOnline";
|
case DataSource::SourceType::DaqromancyOnline: return "DaqromancyOnline";
|
||||||
case DataSource::SourceType::CharonOnline: return "CharonOnline";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "None";
|
return "None";
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#define DATA_SOURCE_H
|
#define DATA_SOURCE_H
|
||||||
|
|
||||||
#include "Specter/Core/SpecCore.h"
|
#include "Specter/Core/SpecCore.h"
|
||||||
#include "Specter/Physics/PhysicsEventBuilder.h"
|
|
||||||
#include "SpecData.h"
|
#include "SpecData.h"
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
@ -24,29 +23,24 @@ namespace Specter {
|
||||||
CompassOnline,
|
CompassOnline,
|
||||||
CompassOffline,
|
CompassOffline,
|
||||||
DaqromancyOnline,
|
DaqromancyOnline,
|
||||||
DaqromancyOffline,
|
DaqromancyOffline
|
||||||
CharonOnline
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource(uint64_t coincidenceWindow = 0) :
|
DataSource() :
|
||||||
m_validFlag(false), m_isEventReady(false), m_eventBuilder(coincidenceWindow)
|
m_validFlag(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~DataSource() {};
|
virtual ~DataSource() {};
|
||||||
virtual void ProcessData() = 0;
|
virtual const SpecData& GetData() = 0;
|
||||||
virtual const std::vector<SpecEvent>& GetEvents() = 0;
|
|
||||||
inline bool IsValid() { return m_validFlag; }
|
inline bool IsValid() { return m_validFlag; }
|
||||||
inline bool IsEventReady() { return m_isEventReady; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_validFlag;
|
bool m_validFlag;
|
||||||
bool m_isEventReady;
|
|
||||||
SpecData m_datum;
|
SpecData m_datum;
|
||||||
PhysicsEventBuilder m_eventBuilder;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource* CreateDataSource(const std::string& location, const std::string& port, uint16_t bitflags, DataSource::SourceType type, uint64_t coincidenceWindow);
|
DataSource* CreateDataSource(const std::string& location, const std::string& port, uint16_t bitflags, DataSource::SourceType type);
|
||||||
|
|
||||||
std::string ConvertDataSourceTypeToString(DataSource::SourceType type);
|
std::string ConvertDataSourceTypeToString(DataSource::SourceType type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,6 @@
|
||||||
|
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
PhysicsEventBuilder::PhysicsEventBuilder() :
|
|
||||||
m_sortFlag(false), m_coincWindow(0), m_bufferIndex(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicsEventBuilder::PhysicsEventBuilder(uint64_t windowSize) :
|
PhysicsEventBuilder::PhysicsEventBuilder(uint64_t windowSize) :
|
||||||
m_sortFlag(false), m_coincWindow(windowSize), m_bufferIndex(0)
|
m_sortFlag(false), m_coincWindow(windowSize), m_bufferIndex(0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,6 @@ namespace Specter {
|
||||||
class PhysicsEventBuilder
|
class PhysicsEventBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PhysicsEventBuilder();
|
|
||||||
PhysicsEventBuilder(uint64_t windowSize);
|
PhysicsEventBuilder(uint64_t windowSize);
|
||||||
~PhysicsEventBuilder();
|
~PhysicsEventBuilder();
|
||||||
inline void SetCoincidenceWindow(uint64_t windowSize) { m_coincWindow = windowSize; }
|
inline void SetCoincidenceWindow(uint64_t windowSize) { m_coincWindow = windowSize; }
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
namespace Specter {
|
namespace Specter {
|
||||||
|
|
||||||
PhysicsLayer::PhysicsLayer(const SpectrumManager::Ref& manager) :
|
PhysicsLayer::PhysicsLayer(const SpectrumManager::Ref& manager) :
|
||||||
m_manager(manager), m_activeFlag(false), m_source(nullptr), m_physThread(nullptr)
|
m_manager(manager), m_activeFlag(false), m_source(nullptr), m_eventBuilder(0), m_physThread(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ namespace Specter {
|
||||||
|
|
||||||
void PhysicsLayer::OnAttach()
|
void PhysicsLayer::OnAttach()
|
||||||
{
|
{
|
||||||
|
/* For debugging
|
||||||
|
NavParameter par("joseph");
|
||||||
|
par.SetValue(8);
|
||||||
|
NAV_INFO("Does the par exist? {0}", ParameterMap::GetInstance().IsParameterValid("joseph"));
|
||||||
|
NAV_INFO("What is its value? {0}", ParameterMap::GetInstance().GetParameterValue("joseph"));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsLayer::OnDetach()
|
void PhysicsLayer::OnDetach()
|
||||||
|
@ -108,7 +114,10 @@ namespace Specter {
|
||||||
{
|
{
|
||||||
SPEC_PROFILE_FUNCTION();
|
SPEC_PROFILE_FUNCTION();
|
||||||
std::scoped_lock<std::mutex> guard(m_sourceMutex); //Shouldn't matter for this, but safety first
|
std::scoped_lock<std::mutex> guard(m_sourceMutex); //Shouldn't matter for this, but safety first
|
||||||
m_source.reset(CreateDataSource(event.GetSourceLocation(), event.GetSourcePort(), event.GetBitFlags(), event.GetSourceType(), event.GetCoincidenceWindow()));
|
m_source.reset(CreateDataSource(event.GetSourceLocation(), event.GetSourcePort(), event.GetBitFlags(), event.GetSourceType()));
|
||||||
|
m_eventBuilder.SetCoincidenceWindow(event.GetCoincidenceWindow());
|
||||||
|
m_eventBuilder.SetSortFlag(event.GetSortFlag());
|
||||||
|
m_eventBuilder.ClearAll(); //Protect against stopping mid-event
|
||||||
if (m_source->IsValid())
|
if (m_source->IsValid())
|
||||||
{
|
{
|
||||||
SPEC_INFO("Attach successful. Enabling data pull...");
|
SPEC_INFO("Attach successful. Enabling data pull...");
|
||||||
|
@ -136,37 +145,43 @@ namespace Specter {
|
||||||
SPEC_PROFILE_FUNCTION();
|
SPEC_PROFILE_FUNCTION();
|
||||||
|
|
||||||
std::vector<SpecEvent> events;
|
std::vector<SpecEvent> events;
|
||||||
|
SpecData datum;
|
||||||
while(m_activeFlag)
|
while(m_activeFlag)
|
||||||
{
|
{
|
||||||
//Scope to encapsulate access to the data source
|
//Scope to encapsulate access to the data source
|
||||||
{
|
{
|
||||||
std::scoped_lock<std::mutex> guard(m_sourceMutex);
|
std::scoped_lock<std::mutex> guard(m_sourceMutex);
|
||||||
if (m_source == nullptr || !m_source->IsValid())
|
if (m_source == nullptr || !m_source->IsValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Looks funny, but two conditions lead to !IsValid(). Either source prev. shutdown,
|
||||||
|
OR we reached end of source, indicated after prev. data grab
|
||||||
|
*/
|
||||||
|
datum = m_source->GetData();
|
||||||
|
if(!m_source->IsValid())
|
||||||
{
|
{
|
||||||
SPEC_INFO("End of data source.");
|
SPEC_INFO("End of data source.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_source->ProcessData();
|
|
||||||
if(m_source->IsEventReady())
|
//Pass data from source to event builder. True from AddDatum indicates events are ready
|
||||||
|
if (m_eventBuilder.AddDatum(datum))
|
||||||
|
{
|
||||||
|
events = m_eventBuilder.GetReadyEvents();
|
||||||
|
for (auto& event : events)
|
||||||
{
|
{
|
||||||
events = m_source->GetEvents();
|
for (auto& stage : m_physStack)
|
||||||
|
stage->AnalyzePhysicsEvent(event);
|
||||||
|
|
||||||
|
//Now that the analysis stack has filled all our NavParameters with data, update the histogram counts
|
||||||
|
m_manager->UpdateHistograms();
|
||||||
|
//Invalidate all parameters to get ready for next event
|
||||||
|
m_manager->InvalidateParameters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& event : events)
|
|
||||||
{
|
|
||||||
for (auto& stage : m_physStack)
|
|
||||||
stage->AnalyzePhysicsEvent(event);
|
|
||||||
|
|
||||||
//Now that the analysis stack has filled all our NavParameters with data, update the histogram counts
|
|
||||||
m_manager->UpdateHistograms();
|
|
||||||
//Invalidate all parameters to get ready for next event
|
|
||||||
m_manager->InvalidateParameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!events.empty())
|
|
||||||
events.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "AnalysisStack.h"
|
#include "AnalysisStack.h"
|
||||||
#include "AnalysisStage.h"
|
#include "AnalysisStage.h"
|
||||||
#include "DataSource.h"
|
#include "DataSource.h"
|
||||||
|
#include "PhysicsEventBuilder.h"
|
||||||
#include "Specter/Core/SpectrumManager.h"
|
#include "Specter/Core/SpectrumManager.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -54,6 +55,8 @@ namespace Specter {
|
||||||
std::mutex m_sourceMutex;
|
std::mutex m_sourceMutex;
|
||||||
|
|
||||||
std::unique_ptr<DataSource> m_source;
|
std::unique_ptr<DataSource> m_source;
|
||||||
|
PhysicsEventBuilder m_eventBuilder;
|
||||||
|
|
||||||
std::thread* m_physThread;
|
std::thread* m_physThread;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
#include "CharonClient.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
CharonClient::CharonClient(const std::string& hostname, const std::string& port) :
|
|
||||||
m_socket(m_context)
|
|
||||||
{
|
|
||||||
Connect(hostname, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
CharonClient::~CharonClient()
|
|
||||||
{
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CharonClient::GetNextEvent(std::vector<uint8_t>& event)
|
|
||||||
{
|
|
||||||
if(m_queue.IsEmpty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
event = m_queue.Front().body;
|
|
||||||
m_queue.PopFront();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharonClient::Connect(const std::string& hostname, const std::string& port)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
asio::ip::tcp::resolver resolver(m_context);
|
|
||||||
auto end_points = resolver.resolve(hostname, port);
|
|
||||||
asio::async_connect(m_socket, end_points,
|
|
||||||
[this](std::error_code ec, asio::ip::tcp::endpoint endpoint)
|
|
||||||
{
|
|
||||||
if (!ec)
|
|
||||||
{
|
|
||||||
ReadHeader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
m_ioThread = std::thread([this]() { m_context.run(); });
|
|
||||||
SPEC_WARN("Connected CharonClient to {0}:{1}", hostname, port);
|
|
||||||
}
|
|
||||||
catch (asio::system_error& e)
|
|
||||||
{
|
|
||||||
SPEC_WARN("Unable to connect CharonClient to {0}:{1}", hostname, port);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharonClient::Disconnect()
|
|
||||||
{
|
|
||||||
if (IsConnected())
|
|
||||||
{
|
|
||||||
asio::post(m_context, [this]() { m_socket.close(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
m_context.stop();
|
|
||||||
if (m_ioThread.joinable())
|
|
||||||
m_ioThread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharonClient::ReadHeader()
|
|
||||||
{
|
|
||||||
asio::async_read(m_socket, asio::buffer(&m_tempMessage.size, sizeof(m_tempMessage.size)),
|
|
||||||
[this](std::error_code ec, std::size_t size)
|
|
||||||
{
|
|
||||||
if (!ec)
|
|
||||||
{
|
|
||||||
if (m_tempMessage.size > 0)
|
|
||||||
{
|
|
||||||
m_tempMessage.body.resize(m_tempMessage.size);
|
|
||||||
ReadBody();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ReadHeader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharonClient::ReadBody()
|
|
||||||
{
|
|
||||||
asio::async_read(m_socket, asio::buffer(m_tempMessage.body.data(), m_tempMessage.body.size()),
|
|
||||||
[this](std::error_code ec, std::size_t size)
|
|
||||||
{
|
|
||||||
if (!ec)
|
|
||||||
{
|
|
||||||
m_queue.PushBack(m_tempMessage);
|
|
||||||
}
|
|
||||||
ReadHeader();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#ifndef CHARON_CLIENT_H
|
|
||||||
#define CHARON_CLIENT_H
|
|
||||||
|
|
||||||
#include "Specter/Utils/ThreadSafeQueue.h"
|
|
||||||
#include <asio.hpp>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
struct StygianMessage
|
|
||||||
{
|
|
||||||
uint64_t size;
|
|
||||||
std::vector<uint8_t> body;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CharonClient
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CharonClient(const std::string& hostname, const std::string& port);
|
|
||||||
~CharonClient();
|
|
||||||
|
|
||||||
bool GetNextEvent(std::vector<uint8_t>& event);
|
|
||||||
|
|
||||||
void Connect(const std::string& hostname, const std::string& port);
|
|
||||||
void Disconnect();
|
|
||||||
|
|
||||||
const bool IsConnected() const { return m_socket.is_open(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ReadHeader();
|
|
||||||
void ReadBody();
|
|
||||||
|
|
||||||
asio::io_context m_context;
|
|
||||||
asio::ip::tcp::socket m_socket;
|
|
||||||
std::thread m_ioThread;
|
|
||||||
|
|
||||||
StygianMessage m_tempMessage;
|
|
||||||
ThreadSafeQueue<StygianMessage> m_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,67 +0,0 @@
|
||||||
#include "CharonOnlineSource.h"
|
|
||||||
#include "Unpackers/CaenUnpacker.h"
|
|
||||||
#include "Unpackers/MesyTecUnpacker.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
CharonOnlineSource::CharonOnlineSource(const std::string& hostname, const std::string& port) :
|
|
||||||
DataSource(0), m_client(hostname, port)
|
|
||||||
{
|
|
||||||
m_validFlag = m_client.IsConnected();
|
|
||||||
m_readyEvents.emplace_back();
|
|
||||||
|
|
||||||
m_unpackers.push_back(std::make_shared<CaenUnpacker>());
|
|
||||||
m_unpackers.push_back(std::make_shared<MesyTecUnpacker>());
|
|
||||||
}
|
|
||||||
|
|
||||||
CharonOnlineSource::~CharonOnlineSource()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharonOnlineSource::ProcessData()
|
|
||||||
{
|
|
||||||
if(!m_client.IsConnected())
|
|
||||||
{
|
|
||||||
m_validFlag = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_client.GetNextEvent(m_rawBuffer))
|
|
||||||
{
|
|
||||||
m_event.clear();
|
|
||||||
UnpackRawBuffer();
|
|
||||||
m_isEventReady = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharonOnlineSource::UnpackRawBuffer()
|
|
||||||
{
|
|
||||||
uint32_t* iter = (uint32_t*) m_rawBuffer.data();
|
|
||||||
uint32_t* end = iter + m_rawBuffer.size();
|
|
||||||
bool wasUnpacked = false;
|
|
||||||
|
|
||||||
UnpackerResult result;
|
|
||||||
while(iter < end)
|
|
||||||
{
|
|
||||||
wasUnpacked = false;
|
|
||||||
for(auto& unpacker : m_unpackers)
|
|
||||||
{
|
|
||||||
if(unpacker->IsHeader(*iter))
|
|
||||||
{
|
|
||||||
result = unpacker->Unpack(iter, end);
|
|
||||||
iter = result.finalPosition;
|
|
||||||
wasUnpacked = true;
|
|
||||||
m_event.insert(m_event.end(), result.data.begin(), result.data.end());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!wasUnpacked)
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_readyEvents[0] = m_event;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef CHARON_ONLINE_SOURCE
|
|
||||||
#define CHARON_ONLINE_SOURCE
|
|
||||||
|
|
||||||
#include "Specter/Physics/DataSource.h"
|
|
||||||
#include "CharonClient.h"
|
|
||||||
#include "Unpackers/Unpacker.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
class CharonOnlineSource : public DataSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CharonOnlineSource(const std::string& hostname, const std::string& port);
|
|
||||||
virtual ~CharonOnlineSource();
|
|
||||||
|
|
||||||
virtual void ProcessData() override;
|
|
||||||
virtual const std::vector<SpecEvent>& GetEvents() override
|
|
||||||
{
|
|
||||||
m_isEventReady = false;
|
|
||||||
return m_readyEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void UnpackRawBuffer();
|
|
||||||
|
|
||||||
CharonClient m_client;
|
|
||||||
std::vector<uint8_t> m_rawBuffer;
|
|
||||||
SpecEvent m_event;
|
|
||||||
std::vector<SpecEvent> m_readyEvents;
|
|
||||||
std::vector<Unpacker::Ref> m_unpackers;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,65 +0,0 @@
|
||||||
#include "CaenUnpacker.h"
|
|
||||||
#include "Specter/Utils/Functions.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
CaenUnpacker::CaenUnpacker() :
|
|
||||||
Unpacker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CaenUnpacker::~CaenUnpacker() {}
|
|
||||||
|
|
||||||
void CaenUnpacker::UnpackHeader(uint32_t* word)
|
|
||||||
{
|
|
||||||
if(!IsHeader(*word))
|
|
||||||
{
|
|
||||||
SPEC_WARN("In CaenADCUnpacker::UnpackHeader() found non-header word!");
|
|
||||||
m_bodyWordCount = 0;
|
|
||||||
m_moduleID = s_illegalModuleID;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bodyWordCount = (*word & s_headerCountMask) >> s_headerCountShift;
|
|
||||||
m_moduleID = (*word & s_geoAddressMask) >> s_geoAddressShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CaenUnpacker::UnpackEnd(uint32_t* word)
|
|
||||||
{
|
|
||||||
if(!IsEnd(*word))
|
|
||||||
{
|
|
||||||
SPEC_WARN("In CaenADCUnpacker::UnpackEnd() found non-end word!");
|
|
||||||
}
|
|
||||||
//CAEN doesnt really put anything useful here
|
|
||||||
}
|
|
||||||
|
|
||||||
void CaenUnpacker::UnpackDatum(uint32_t* word)
|
|
||||||
{
|
|
||||||
if(!IsBody(*word))
|
|
||||||
{
|
|
||||||
SPEC_WARN("In CaenADCUnpacker::UnpackDatum() found non-body word!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecData datum;
|
|
||||||
uint32_t channel = (*word & s_dataChannelMask) >> s_dataChannelShift;
|
|
||||||
datum.id = Utilities::GetBoardChannelUUID(m_moduleID, channel);
|
|
||||||
datum.longEnergy = (*word & s_dataMask);
|
|
||||||
m_parsedEvent.data.push_back(datum);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CaenUnpacker::IsHeader(uint32_t word) const
|
|
||||||
{
|
|
||||||
return ((word & s_typeMask) == s_typeHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CaenUnpacker::IsBody(uint32_t word) const
|
|
||||||
{
|
|
||||||
return ((word & s_typeMask) == s_typeBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CaenUnpacker::IsEnd(uint32_t word) const
|
|
||||||
{
|
|
||||||
return ((word & s_typeMask) == s_typeEnd);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
#ifndef CAEN_UNPACKER_H
|
|
||||||
#define CAEN_UNPACKER_H
|
|
||||||
|
|
||||||
#include "Unpacker.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
class CaenUnpacker : public Unpacker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CaenUnpacker();
|
|
||||||
virtual ~CaenUnpacker();
|
|
||||||
|
|
||||||
virtual bool IsHeader(uint32_t word) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual bool IsBody(uint32_t word) const override;
|
|
||||||
virtual bool IsEnd(uint32_t word) const override;
|
|
||||||
|
|
||||||
virtual void UnpackHeader(uint32_t* word) override;
|
|
||||||
virtual void UnpackEnd(uint32_t* word) override;
|
|
||||||
|
|
||||||
virtual void UnpackDatum(uint32_t* word) override;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_typeMask = 0x07000000;
|
|
||||||
static constexpr uint32_t s_typeHeader = 0x02000000;
|
|
||||||
static constexpr uint32_t s_typeBody = 0x00000000;
|
|
||||||
static constexpr uint32_t s_typeEnd = 0x04000000;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_geoAddressShift = 27;
|
|
||||||
static constexpr uint32_t s_geoAddressMask = 0xf8000000;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_headerCountShift = 8;
|
|
||||||
static constexpr uint32_t s_headerCountMask = 0x00003f00;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_dataChannelShift = 16;
|
|
||||||
static constexpr uint32_t s_dataChannelMask = 0x001f0000;
|
|
||||||
static constexpr uint32_t s_dataMask = 0x00000fff;
|
|
||||||
static constexpr uint32_t s_dataStatusMask = 0x00003000;
|
|
||||||
static constexpr uint32_t s_dataOverflow = 0x00001000;
|
|
||||||
static constexpr uint32_t s_dataUnderflow = 0x00002000;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,62 +0,0 @@
|
||||||
#include "MesyTecUnpacker.h"
|
|
||||||
#include "Specter/Utils/Functions.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
MesyTecUnpacker::MesyTecUnpacker() :
|
|
||||||
Unpacker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MesyTecUnpacker::~MesyTecUnpacker() {}
|
|
||||||
|
|
||||||
void MesyTecUnpacker::UnpackHeader(uint32_t* word)
|
|
||||||
{
|
|
||||||
if(!IsHeader(*word))
|
|
||||||
{
|
|
||||||
SPEC_WARN("In MesyQDCUnpacker::UnpackHeader() found non-header word!");
|
|
||||||
m_moduleID = s_illegalModuleID;
|
|
||||||
m_bodyWordCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_moduleID = (*word & s_idMask) >> s_idShift;
|
|
||||||
m_bodyWordCount = (*word & s_headerCountMask) - 1; //For MesyTec, count includes the end word
|
|
||||||
}
|
|
||||||
|
|
||||||
void MesyTecUnpacker::UnpackDatum(uint32_t* word)
|
|
||||||
{
|
|
||||||
if(!IsBody(*word))
|
|
||||||
{
|
|
||||||
SPEC_WARN("In MesyQDCUnpacker::UnpackDatum() found non-body word!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecData datum;
|
|
||||||
uint32_t channel = (*word & s_dataChannelMask) >> s_dataChannelShift;
|
|
||||||
datum.id = Utilities::GetBoardChannelUUID(m_moduleID, channel);
|
|
||||||
datum.longEnergy = (*word & s_dataMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MesyTecUnpacker::UnpackEnd(uint32_t* word)
|
|
||||||
{
|
|
||||||
if(!IsEnd(*word))
|
|
||||||
{
|
|
||||||
SPEC_WARN("In MesyQDCUnpacker::UnpackEnd() found non-end word!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MesyTecUnpacker::IsHeader(uint32_t word) const
|
|
||||||
{
|
|
||||||
return ((word & s_typeMask) == s_typeHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MesyTecUnpacker::IsBody(uint32_t word) const
|
|
||||||
{
|
|
||||||
return ((word & s_typeMask) == s_typeBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MesyTecUnpacker::IsEnd(uint32_t word) const
|
|
||||||
{
|
|
||||||
return ((word & s_typeMask) == s_typeEnd);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef MESY_TEC_UNPACKER_H
|
|
||||||
#define MESY_TEC_UNPACKER_H
|
|
||||||
|
|
||||||
#include "Unpacker.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
class MesyTecUnpacker : public Unpacker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MesyTecUnpacker();
|
|
||||||
virtual ~MesyTecUnpacker();
|
|
||||||
|
|
||||||
virtual bool IsHeader(uint32_t word) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual bool IsBody(uint32_t word) const override;
|
|
||||||
virtual bool IsEnd(uint32_t word) const override;
|
|
||||||
|
|
||||||
virtual void UnpackHeader(uint32_t* word) override;
|
|
||||||
virtual void UnpackEnd(uint32_t* word) override;
|
|
||||||
|
|
||||||
virtual void UnpackDatum(uint32_t* word) override;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_typeMask = 0xc000000;
|
|
||||||
static constexpr uint32_t s_typeHeader = 0x40000000;
|
|
||||||
static constexpr uint32_t s_typeBody = 0x00000000;
|
|
||||||
static constexpr uint32_t s_typeEnd = 0xc0000000;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_idShift = 16;
|
|
||||||
static constexpr uint32_t s_idMask = 0x00ff0000;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_headerCountMask = 0x00000fff;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_dataChannelShift = 16;
|
|
||||||
static constexpr uint32_t s_dataChannelMask = 0x001f0000;
|
|
||||||
static constexpr uint32_t s_dataMask = 0x0000ffff;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,82 +0,0 @@
|
||||||
#ifndef UNPACKER_H
|
|
||||||
#define UNPACKER_H
|
|
||||||
|
|
||||||
#include "Specter/Physics/SpecData.h"
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
struct UnpackerResult
|
|
||||||
{
|
|
||||||
uint32_t* finalPosition = nullptr;
|
|
||||||
std::vector<SpecData> data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Unpacker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Ref = std::shared_ptr<Unpacker>;
|
|
||||||
|
|
||||||
Unpacker() :
|
|
||||||
m_bodyWordCount(0), m_moduleID(s_illegalModuleID)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
virtual ~Unpacker() {}
|
|
||||||
|
|
||||||
const UnpackerResult& Unpack(uint32_t* begin, uint32_t* end)
|
|
||||||
{
|
|
||||||
m_parsedEvent = UnpackerResult();
|
|
||||||
|
|
||||||
uint32_t* iter = begin;
|
|
||||||
UnpackHeader(iter);
|
|
||||||
++iter;
|
|
||||||
|
|
||||||
uint32_t* bodyEnd = iter + m_bodyWordCount;
|
|
||||||
if(bodyEnd > end || m_moduleID == s_illegalModuleID)
|
|
||||||
{
|
|
||||||
SPEC_WARN("In Unpacker::Unpack() header unpack error (number of words: {0}, moduleID: {1}), data not parsed!", m_bodyWordCount, m_moduleID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter = UnpackBody(iter, bodyEnd);
|
|
||||||
UnpackEnd(iter);
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_parsedEvent.finalPosition = iter;
|
|
||||||
|
|
||||||
return m_parsedEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool IsHeader(uint32_t word) const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool IsBody(uint32_t word) const = 0;
|
|
||||||
virtual bool IsEnd(uint32_t word) const = 0;
|
|
||||||
|
|
||||||
virtual void UnpackHeader(uint32_t* word) = 0;
|
|
||||||
virtual void UnpackEnd(uint32_t* word) = 0;
|
|
||||||
|
|
||||||
uint32_t* UnpackBody(uint32_t* bodyBegin, uint32_t* bodyEnd)
|
|
||||||
{
|
|
||||||
uint32_t* iter = bodyBegin;
|
|
||||||
while(iter != bodyEnd)
|
|
||||||
{
|
|
||||||
UnpackDatum(iter);
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void UnpackDatum(uint32_t* word) = 0;
|
|
||||||
|
|
||||||
UnpackerResult m_parsedEvent;
|
|
||||||
uint64_t m_bodyWordCount;
|
|
||||||
uint32_t m_moduleID;
|
|
||||||
|
|
||||||
static constexpr uint32_t s_illegalModuleID = 999;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,128 +0,0 @@
|
||||||
#ifndef SPECTER_THREAD_SAFE_QUEUE_H
|
|
||||||
#define SPECTER_THREAD_SAFE_QUEUE_H
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <atomic>
|
|
||||||
#include <queue>
|
|
||||||
#include <condition_variable>
|
|
||||||
|
|
||||||
namespace Specter {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class ThreadSafeQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ThreadSafeQueue() = default;
|
|
||||||
ThreadSafeQueue(const ThreadSafeQueue&) = delete; //no copy
|
|
||||||
~ThreadSafeQueue() { Clear(); }
|
|
||||||
|
|
||||||
void PushBack(const T& data)
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
m_queue.push_back(data);
|
|
||||||
|
|
||||||
std::scoped_lock<std::mutex> condGuard(m_conditionMutex);
|
|
||||||
m_conditional.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushFront(const T& data)
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
m_queue.push_front(data);
|
|
||||||
|
|
||||||
std::scoped_lock<std::mutex> conditionGuard(m_conditionMutex);
|
|
||||||
m_conditional.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopBack()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
m_queue.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopFront()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
m_queue.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& Front()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
return m_queue.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& Back()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
return m_queue.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t Size()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
return m_queue.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsEmpty()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
return m_queue.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
m_queue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//For iterator loops, need begin()/end() idiom
|
|
||||||
|
|
||||||
typename std::deque<T>::iterator begin()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
return m_queue.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
typename std::deque<T>::iterator end()
|
|
||||||
{
|
|
||||||
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
|
||||||
return m_queue.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wait()
|
|
||||||
{
|
|
||||||
while (IsEmpty() && !m_isForceWakeup)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> guard(m_conditionMutex);
|
|
||||||
m_conditional.wait(guard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForceWakeup()
|
|
||||||
{
|
|
||||||
m_isForceWakeup = true;
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> guard(m_conditionMutex);
|
|
||||||
m_conditional.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetWakeup()
|
|
||||||
{
|
|
||||||
m_isForceWakeup = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::mutex m_queueMutex;
|
|
||||||
std::deque<T> m_queue;
|
|
||||||
|
|
||||||
std::mutex m_conditionMutex;
|
|
||||||
std::condition_variable m_conditional;
|
|
||||||
|
|
||||||
std::atomic<bool> m_isForceWakeup = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user