/*******************************************************************************
* Copyright (C) 2016 Vetle W. Ingeberg *
* Author: Vetle Wegner Ingeberg, v.w.ingeberg@fys.uio.no *
* *
* --------------------------------------------------------------------------- *
* 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 3 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 recived a copy of the GNU General Public License along with *
* the program. If not, see . *
* *
*******************************************************************************/
#include "UserSort.h"
#include "DefineFile.h"
#include "TDRWordBuffer.h"
#include "DetectorRead.h"
#include "Histogram1D.h"
#include "Histogram2D.h"
#include "Histograms.h"
#include "Event.h"
#include
#include
#include
#include
#include
#define BIT15TO13 0xE000
#define BIT12TO0 0x1FFF
inline uint16_t extract(const uint16_t &val, const int &begin, const int &end)
{
uint16_t mask = (1 << (end - begin)) - 1;
return (val >> begin) & mask;
}
void showBit16(uint16_t u){
int values[16];
for (int i = 0 ; i < 16 ; i++){
values[i] = u%2;
u = u/2;
}
for (int i = 15 ; i >= 0 ; i--){
std::cout << values[i];
} std::cout << std::endl;
}
double ExtractTime(const uint64_t ×tamp_100MHz, const uint16_t &cfddata)
{
uint64_t time_in_ns;
uint16_t cfdtrigsource = ((cfddata & 0xE000) >> 13 );
if (cfdtrigsource != 7){
time_in_ns = 2*(cfdtrigsource - 1) + 10*timestamp_100MHz;
} else {
time_in_ns = 10*timestamp_100MHz;
return static_cast(time_in_ns);
}
uint16_t timecfd = (cfddata & 0x1FFF) >> 0;
double correction = 2.0*static_cast(timecfd)/8192.0;
return static_cast(time_in_ns) + correction;
}
inline double ExtractCorrection(const uint16_t &cfddata)
{
uint16_t cfdtrigsource = ((cfddata & 0xE000) >> 13 );
double correction = 0.0;
if (cfdtrigsource != 7){
correction = 2.0*(int(cfdtrigsource) - 1);
} else {
return 0.0;
}
uint16_t timecfd = ((cfddata & 0x1FFF) >> 0);
correction += 2.0*timecfd/8192.0;
return correction;
}
bool UserSort::UserCommand(const std::string &cmd){
return true;
}
void UserSort::CreateSpectra()
{
for (int i = 0 ; i < NUM_LABR ; ++i){
energy[i] = Spec("energy_L"+std::to_string(i+1), "raw energy spectrum", 16384, 0, 16384, "Energy [ch]");
energy_cal[i] = Spec("energy_cal_L"+std::to_string(i+1), "Energy calibrated", 2000, 0, 10000, "Energy [keV]");
time[i] = Mat("time_L"+std::to_string(i+1), "time spectrum", 6000, -30000, 30000, "Timediff. [ps]", NUM_LABR+1, 0, NUM_LABR+1, "LaBr detector no.");
for (int j = 0 ; j < NUM_LABR ; ++j){
gg_spec[i][j] = Mat("gg_L"+std::to_string(i+1)+"_L"+std::to_string(j+1), "Gamma - gamma spectrum", 2000, 0, 10000, "Energy L"+std::to_string(i+1)+" [keV]",
2000, 0, 10000, "Energy L"+std::to_string(j+1)+" [keV]");
}
}
}
bool UserSort::Sort(const Event &event)
{
for (int i = 0 ; i < NUM_LABR ; ++i){
n_L[i] = 0;
}
for (int i = 0 ; i < event.length ; ++i){
__builtin_prefetch(&event.words[i+1]);
for (int j = 0 ; j < NUM_LABR ; ++j){
if (event.words[i].address == START_CHANNEL+j){
energy[j]->Fill(event.words[i].adcdata);
energy_cal[j]->Fill(GainEnergy(event.words[i].address, event.words[i].adcdata));
if (n_L[j] < 128){
w_L[j][n_L[j]] = event.words[i];
++n_L[j];
}
break;
}
}
}
double E0, t0_fine;
int64_t t0_course;
double E1, t1_fine;
int64_t t1_course;
double timediff_c, timediff_f, timediff;
for (int i = 0 ; i < NUM_LABR ; ++i){
for (int j = 0 ; j < n_L[i] ; ++j){
__builtin_prefetch(&w_L[i][j+1]);
E0 = GainEnergy(w_L[i][j].address, w_L[i][j].adcdata);
t0_course = w_L[i][j].timestamp*10;
t0_fine = ExtractCorrection(w_L[i][j].cfddata);
for (int n = 0 ; n < NUM_LABR ; ++n){
for (int m = 0 ; m < n_L[n] ; ++m){
__builtin_prefetch(&w_L[n][m+1]);
if (n == i && m == j){
break;
}
E1 = GainEnergy(w_L[n][m].address, w_L[n][m].adcdata);
t1_course = w_L[n][m].timestamp*10;
t1_fine = ExtractCorrection(w_L[n][m].cfddata);
timediff_c = t0_course - t1_course;
timediff_f = t0_fine - t1_fine;
timediff = (timediff_c + timediff_f)*1000.;
time[i]->Fill(timediff, n+0.5);
if ( (i != n) && GateTime(w_L[i][j].address, w_L[n][m].address, timediff) ){
gg_spec[i][n]->Fill(E0, E1);
}
}
}
}
}
return true;
}
bool UserSort::End()
{
return true;
}