Commit caf429f2 authored by Jérémie Dudouet's avatar Jérémie Dudouet
Browse files

add PSAHist files

parent b1f8ba6f
/***************************************************************************
* Copyright (C) 2018 by Jeremie Dudouet *
* jeremie.dudouet(AT)csnsm.in2p3.fr *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef AGAPRO_PSAHist
#include "AGAPRO_PSAHist.h"
#endif
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "PSAFilter.h"
#include "AgataKeyFactory.h"
#include "AgataFrameFactory.h"
#include "adetParams.h"
#include "commonDefs.h"
using namespace ADF;
using namespace AGAPRO;
PSAHist::PSAHist() :
Histogramer("data:psa")
{
gActualClass = "PSAHist";
fBasePortNumber = 12;
vector<void* > AmpliList;
fListOfHists.push_back(AmpliList);
vector<void* > HitPaternsList;
fListOfHists.push_back(HitPaternsList);
vector<void* > T0List;
fListOfHists.push_back(T0List);
vector<void* > TimeStampList;
fListOfHists.push_back(TimeStampList);
fNextCycleSec = 3600.;
fNextCycleMin = 720.;
fNextCycleH = 48.;
}
PSAHist::~PSAHist()
{
cServer.Finish();
// in principle not needed ... just in case reset it has not been called by narval
UInt_t error = 0u; process_reset(&error) ;
}
UInt_t PSAHist::Process()
{
Log.ClearMessage();
Log.GetProcessName() = "PSAHist";
Log.SetProcessMethod("Process()");
Log.SetPID(GetPID());
vector< void* > Amplilist = fListOfHists[(Int_t)HistLib::Ampli];
if(fPlotAmpli && Amplilist.size() == (kNSG+kNCC))
{
for(int nn = 0; nn < number_of_hits; nn++)
{
auto hist = (Hist1F*)Amplilist[SegId[nn]];
FillHist1F(hist,SegE[nn]);
}
for(int nn = 0; nn < kNCC; nn++)
{
auto hist = (Hist1F*)Amplilist[kNSG+nn];
FillHist1F(hist,CoreE[nn]);
}
}
vector< void* > HitPaternslist = fListOfHists[(Int_t)HistLib::HitPaterns];
if(fPlotHitPaterns && HitPaternslist.size() == 9)
{
for(int nn = 0; nn < number_of_hits; nn++)
{
int slice = SegId[nn]%6;
auto hist2d = (Hist2F_PSA*)HitPaternslist[slice];
FillHist2F(hist2d,SegX[nn],SegY[nn]);
hist2d = (Hist2F_PSA*)HitPaternslist[6];
FillHist2F(hist2d,SegX[nn],SegZ[nn]);
hist2d = (Hist2F_PSA*)HitPaternslist[7];
FillHist2F(hist2d,SegR[nn],SegZ[nn]);
}
auto hist = (Hist1F*)HitPaternslist[8];
FillHist1F(hist,number_of_hits);
}
vector< void* > CoreTlist = fListOfHists[(Int_t)HistLib::CoreT];
if(fPlotCoreT && CoreTlist.size() == 2)
{
for(int nn = 0; nn < kNCC; nn++)
{
auto hist = (Hist1F*)CoreTlist[nn];
FillHist1F(hist,CoreT[nn]);
}
}
vector< void* > TSlist = fListOfHists[(Int_t)HistLib::TimeStamps];
if(fPlotTimeStamps && TSlist.size() == 2)
{
if(fFirstTS == 0)
{
fFirstTS = timestamp;
}
if(timestamp != 0 && timestamp>fLastTS)
{
auto hists = (Hist1F*)TSlist[0];
auto histm = (Hist1F*)TSlist[1];
double TSinSec = fmod((timestamp-fFirstTS)*10*1e-9,3600);
double TSinMin = fmod((timestamp-fFirstTS)*10*1e-9/60.,720);
if((timestamp-fFirstTS)*10*1e-9 > fNextCycleSec)
{
ResetHist1F(hists);
fNextCycleSec += 3600.;
}
if((timestamp-fFirstTS)*10*1e-9/60. > fNextCycleMin)
{
ResetHist1F(histm);
fNextCycleMin += 720.;
}
FillHist1F(hists,TSinSec,(3600./3600.));
FillHist1F(histm,TSinMin,(3600./720.)/60.);
}
else
{
Log.SetLevel(LogMessage::kWarning);
Log << "First TS : "<<fFirstTS<<" ; Last TS : "<<fLastTS<<" ; TS : "<<timestamp<< dolog;
}
fLastTS = timestamp;
}
}
void PSAHist::process_initialise (UInt_t *error_code)
{
Log.ClearMessage();
Log.GetProcessName() = gActualClass;
Log.SetProcessMethod("process_initialise");
Log.SetPID(GetPID());
*error_code = GetParameters(GetConfPath() + gActualClass + ".conf");
if(*error_code)
{
Log << dolog;
return;
}
// to get the input/output frames
if( fFrameCrystal ){
delete fFrameCrystal;
fFrameCrystal = NULL;
}
UInt_t rerr = 0;
std::cout << std::endl;
fFrameCrystal = fTrigger.Add("Agata", "data:psa"); // discard input data
if( fFrameCrystal )
{
// link named items with local variables.
GObject *glob = GetDataPointer<PSAInterface>(fFrameCrystal)->Global();
glob->LinkItem("CrystalID", &crystal_id);
glob->LinkItem("CoreE0", &CoreE[0]);
glob->LinkItem("CoreE1", &CoreE[1]);
glob->LinkItem("CoreT0", &CoreT[0]);
glob->LinkItem("CoreT1", &CoreT[1]);
}
else
rerr |= 8;
// the trigger is registered
if( !fFrameIO.Register(&fTrigger) )
rerr |= 1;
if(rerr)
{
std::cout << "Trigger definition error " << rerr << " in PSAHist::process_initialise()" << std::endl;
*error_code = 100 + rerr;
Log << dolog;
return;
}
// state set to kIdle so that the data can be treated
fFrameIO.SetStatus(BaseFrameIO::kIdle);
cServer.SetCommandFile(GetConfPath() + gActualClass + ".live");
cServer.Start(gActualClass);
InitSMZ(crystal_id);
Log << dolog;
}
Int_t PSAHist::SetInput()
{
Frame *frame_in = fFrameCrystal->GetFrame();
UInt_t bytes_in = frame_in->Read();
timestamp = ((AgataKey *)frame_in->GetKey())->GetTimeStamp();
evnumber = ((AgataKey *)frame_in->GetKey())->GetEventNumber();
PSAInterface *data = GetDataPointer<PSAInterface>(fFrameCrystal);
number_of_hits = data->GetNbHits();
for( UShort_t i=0u; i < data->GetNbHits(); i++ )
{
const Hit *hit = data->GetHit(i);
SegId[i] = hit->GetID(0);
SegE[i] = hit->GetE();
SegX[i] = hit->GetX();
SegY[i] = hit->GetY();
SegZ[i] = hit->GetZ();
SegR[i] = sqrt(SegX[i]*SegX[i]+SegY[i]*SegY[i]);
}
return 0;
}
UInt_t PSAHist::GetParameters(const std::string& confFile, Bool_t doList)
{
ConfReader conf;
conf.Add("Crystal", "Crystal name"
, &crystal_name);
conf.Add("RefreshTime", "Refresh time of the Shared Memory Zone (in seconds)"
, &fRefreshTime);
conf.Add("PlotAmpli", "Binning of the amplitude spectra"
, &fAmpliBinning.NBins, &fAmpliBinning.Min, &fAmpliBinning.Max);
conf.Add("PlotHitPaterns", "Plot hit paterns (XvsY per slice, ZvsY, ZvsR, hit multiplicity"
, &fPlotHitPaterns);
conf.Add("PlotCoreT", "Binning of the Core timing spectra"
, &fCoreTBinning.NBins, &fCoreTBinning.Min, &fCoreTBinning.Max);
conf.Add("PlotTimeStamps", "Plot Timestamp spectra, optionnal: define the ref T0 TimeStamp (1 TSRef)"
, &fPlotTimeStamps, &fFirstTS).SetRequired(1);
if(doList) {conf.Show(gActualClass); return 0;}
int rv = conf.Read(gActualClass, confFile);
crystal_id = GetCrystalIDFromName(crystal_name);
if(fAmpliBinning.NBins>0) fPlotAmpli = true;
if(fCoreTBinning.NBins>0) fPlotCoreT = true;
// To randomize the refresh time among the different crystals
fRefreshTime = fRefreshTime - 0.5 + ((double) rand() / (RAND_MAX));
return rv;
}
void PSAHist::InitSMZ(Int_t id)
{
ostringstream mapname;
mapname << "/" << gActualClass << "_" << setfill('0') << setw(3) << id;
string CrystalName = GetCrystalNameFromID(id);
cout<<"Build New Map for "<<gActualClass<<" level, crystal "<<id<<" ("<<CrystalName<<") : MapName = "<<mapname.str()<<endl;
ostringstream Name;
ostringstream Title;
ostringstream XTitle;
ostringstream YTitle;
ostringstream GruName;
PSAMap *map_ptr = nullptr;
Int_t PortNumber = fBasePortNumber*1000 + id;
map_ptr = static_cast<PSAMap*>(CreateNewSMz(mapname.str().data(),sizeof(PSAMap),PortNumber));
if(fPlotAmpli)
{
vector<void *>& list = fListOfHists[(Int_t)HistLib::Ampli];
for(auto i=0 ; i<kNSG ; i++)
{
Name<<"PSA_Ampli_Cry" << id << "_Seg" << i;
Title<<"PSA_Ampli_Cry"<<CrystalName.data()<<"_Seg"<<GetSegmentNameFromID(i).data();
XTitle<<"Energy (keV)";
GruName<<"PSA/Ampli/Cry"<<CrystalName.data();
Hist1F *hist1F = NewHist1F(Name.str(),Title.str(),XTitle.str(),GruName.str(),fAmpliBinning.NBins,fAmpliBinning.Min,fAmpliBinning.Max,map_ptr,PortNumber);
Name.str("");Title.str("");XTitle.str("");GruName.str("");
if(hist1F) list.push_back(hist1F);
}
for(auto i=0 ; i<kNCC ; i++)
{
Name<<"PSA_Ampli_Cry" << id << "_Core" << i;
Title<<"PSA_Ampli_Cry"<<CrystalName.data()<<"_"<<GetCoreNameFromID(i).data();
XTitle<<"Energy (keV)";
GruName<<"PSA/Ampli/Cry"<<CrystalName.data();
Hist1F *hist1F = NewHist1F(Name.str(),Title.str(),XTitle.str(),GruName.str(),fAmpliBinning.NBins,fAmpliBinning.Min,fAmpliBinning.Max,map_ptr,PortNumber);
Name.str("");Title.str("");XTitle.str("");GruName.str("");
if(hist1F) list.push_back(hist1F);
}
}
if(fPlotHitPaterns)
{
vector<void *>& list = fListOfHists[(Int_t)HistLib::HitPaterns];
for(int i=0 ; i<6 ; i++)
{
Name<<"PSA_YvsX_Cry" << id << "_Slice" << i;
Title<<"PSA_YvsX_Cry"<<CrystalName.data() << "_Slice" << i;
XTitle<<"X (mm)";
YTitle<<"Y (mm)";
GruName<<"PSA/HitPaterns/Cry"<<CrystalName.data();
Hist2F_PSA *hist2F = static_cast<Hist2F_PSA*>(NewHist2F(Name.str(),Title.str(),XTitle.str(),YTitle.str(),GruName.str(),
50,-50.,50.,
50,-50.,50.,
map_ptr,PortNumber));
Name.str("");Title.str("");XTitle.str("");YTitle.str("");GruName.str("");
if(hist2F) list.push_back(hist2F);
}
Name<<"PSA_ZvsX_Cry" << id;
Title<<"PSA_ZvsX_Cry"<<CrystalName.data();
XTitle<<"X (mm)";
YTitle<<"Z (mm)";
GruName<<"PSA/HitPaterns/Cry"<<CrystalName.data();
Hist2F_PSA *hist2F = static_cast<Hist2F_PSA*>(NewHist2F(Name.str(),Title.str(),XTitle.str(),YTitle.str(),GruName.str(),
50,-50.,50.,
45,0.,90.,
map_ptr,PortNumber));
Name.str("");Title.str("");XTitle.str("");YTitle.str("");GruName.str("");
if(hist2F) list.push_back(hist2F);
Name<<"PSA_ZvsR_Cry" << id;
Title<<"PSA_ZvsR_Cry"<<CrystalName.data();
XTitle<<"R (mm)";
YTitle<<"Z (mm)";
GruName<<"PSA/HitPaterns/Cry"<<CrystalName.data();
hist2F = static_cast<Hist2F_PSA*>(NewHist2F(Name.str(),Title.str(),XTitle.str(),YTitle.str(),GruName.str(),
25,0.,50.,
45,0.,90.,
map_ptr,PortNumber));
Name.str("");Title.str("");XTitle.str("");YTitle.str("");GruName.str("");
if(hist2F) list.push_back(hist2F);
Name<<"PSA_HitMult_Cry" << id;
Title<<"PSA_HitMult_Cry"<<CrystalName.data();
XTitle<<"Hit multiplicity";
GruName<<"PSA/HitPaterns/Cry"<<CrystalName.data();
Hist1F *hist1F = NewHist1F(Name.str(),Title.str(),XTitle.str(),GruName.str(),kNSG,0,kNSG,map_ptr,PortNumber);
Name.str("");Title.str("");XTitle.str("");GruName.str("");
if(hist1F) list.push_back(hist1F);
}
if(fPlotCoreT)
{
vector<void *>& list = fListOfHists[(Int_t)HistLib::CoreT];
for(auto i=0 ; i<kNCC ; i++)
{
Name<<"PSA_CoreT_Cry" << id << "_Core" << i;
Title<<"PSA_CoreT_Cry"<<CrystalName.data() <<"_"<<GetCoreNameFromID(i).data();
XTitle<<"core T"<<i<<" (TS units)";
GruName<<"PSA/CoreT/Cry"<<CrystalName.data();
Hist1F *hist1F = NewHist1F(Name.str(),Title.str(),XTitle.str(),GruName.str(),fCoreTBinning.NBins,fCoreTBinning.Min,fCoreTBinning.Max,map_ptr,PortNumber);
Name.str("");Title.str("");XTitle.str("");GruName.str("");
if(hist1F) list.push_back(hist1F);
}
}
if(fPlotTimeStamps)
{
vector<void *>& list = fListOfHists[(Int_t)HistLib::TimeStamps];
Name<<"PSA_TimeStamp_Cry" << id << "_1h";
Title<<"PSA_TS_Cry"<<CrystalName.data()<<"_1hour (1bin=1s)";
XTitle<<"Elapsed time on the last hour (sec)";
GruName<<"PSA/Timestamp/Cry"<<CrystalName.data();
Hist1F *hist1F = NewHist1F(Name.str(),Title.str(),XTitle.str(),GruName.str(),3600,0,3600,map_ptr,PortNumber);
Name.str("");Title.str("");XTitle.str("");
if(hist1F) list.push_back(hist1F);
Name<<"PSA_TimeStamp_Cry" << id << "_12h";
Title<<"PSA_TS_Cry"<<CrystalName.data()<<"_12hour (1bin=12s)";
XTitle<<"Elapsed time on the last 12 hour (min)";
hist1F = NewHist1F(Name.str(),Title.str(),XTitle.str(),GruName.str(),3600,0,720,map_ptr,PortNumber);
Name.str("");Title.str("");XTitle.str("");
if(hist1F) list.push_back(hist1F);
}
}
/***************************************************************************
* Copyright (C) 2018 by Jeremie Dudouet *
* jeremie.dudouet(AT)csnsm.in2p3.fr *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef _PSAHist
#define _PSAHist
#include "AGAPRO_Histogramer.h"
#include "NarvalInterface.h"
#include "CrystalFrame.h"
#include "Trigger.h"
#include "CycleServer.h"
//! PSA histogramer
/*!
*/
namespace AGAPRO {
class PSAHist : public Histogramer
{
protected: //Evt properties
ULong64_t fFirstTS = 0;
ULong64_t fLastTS = 0;
ADF::GeSegment *seg = nullptr;
ADF::GeCore *core = nullptr;
Float_t SegE[kNSG]; // in keV
Float_t CoreE[kNCC]; // in keV
Float_t CoreT[kNCC]; // in keV
Float_t SegX[kNSG];
Float_t SegY[kNSG];
Float_t SegZ[kNSG];
Float_t SegR[kNSG];
Int_t SegId[kNSG];
int number_of_hits;
private:
bool fPlotAmpli = false;
bool fPlotTimeStamps = false;
bool fPlotCoreT = false;
bool fPlotHitPaterns = false;
bool fPlotEvsT = false;
Float_t fNextCycleSec;
Float_t fNextCycleMin;
Float_t fNextCycleH;
binning_TH1 fAmpliBinning;
binning_TH1 fCoreTBinning;
binning_TH2 fEvsTBinning;
enum class HistLib: int { Ampli, HitPaterns, CoreT, TimeStamps };
public:
PSAHist();
virtual ~PSAHist();
virtual UInt_t Process();
virtual Int_t SetInput(); //! to init your local variables with the ones from the buffers
virtual void process_initialise ( UInt_t *error_code ); //! Constructor implementation
public:
virtual UInt_t GetParameters(const std::string& confFile, Bool_t doList=false) override;
private:
virtual void InitSMZ(Int_t id) override;
};
}
#endif
# CMake for module of AGAPRO
# O. Stezowski
cmake_minimum_required (VERSION 2.6)
#
project (PSAHist)
#
MESSAGE("[AGAPRO] + ${PROJECT_NAME}")
#
# internal and external dependencies
#
set( EXTRA_INTERNAL_LIBRARIES AgaProCommon )
set( EXTRA_EXTERNAL_LIBRARIES ${ADF_LIBRARY} )
#
# headers / sources
file(GLOB headers ${PROJECT_SOURCE_DIR}/*.h)
file(GLOB sources ${PROJECT_SOURCE_DIR}/*.cpp)
file(GLOB headers ${headers} ${PROJECT_SOURCE_DIR}/../*.h)
file(GLOB sources ${sources} ${PROJECT_SOURCE_DIR}/../*.cpp)
# Remove if any
if ( NOT DO_NARVAL_INTERFACE )
list(REMOVE_ITEM sources ${PROJECT_SOURCE_DIR}/libAGAPRO_PSAHist.cpp)
endif()
if ( HAS_SSE )
ADD_DEFINITIONS(-msse4)
MESSAGE("[AGAPRO] SSE FOUND ")
endif()
# add to includes
#
include_directories(${AGAPRO_INCLUDE_DIRS})
#----------------------------------------------------------------------------
#
add_library(AGAPRO_PSAHist SHARED ${sources})
#
target_link_libraries(AGAPRO_PSAHist ${EXTRA_EXTERNAL_LIBRARIES} ${EXTRA_INTERNAL_LIBRARIES})
#
set_target_properties(AGAPRO_PSAHist PROPERTIES ${AGAPRO_LIBRARY_PROPERTIES})
#
install(TARGETS AGAPRO_PSAHist RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
COMPONENT libraries)
install(FILES ${headers} DESTINATION include COMPONENT headers )
#
# copy headers file in a single directory
# because cmake2.6 does not provide COPY in file, do it another way
if( ${CMAKE_VERSION} VERSION_GREATER "2.8.0" )
file(COPY ${headers} DESTINATION ${CMAKE_BINARY_DIR}/include)
else()
if ( EXISTS ${CMAKE_BINARY_DIR}/include )
else()
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/include/ )
endif()
foreach ( f ${headers} )
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${f} ${CMAKE_BINARY_DIR}/include/ )
endforeach()
endif()