Commit c66a5244 authored by Simon Spannagel's avatar Simon Spannagel
Browse files

Merge branch 'calib_flo' into 'master'

Calibration Reimplemented

See merge request simonspa/corryvreckan!14
parents 95e5dbec e63f56ac
Pipeline #256201 passed with stages
in 2 minutes and 59 seconds
......@@ -50,5 +50,5 @@ namespace corryvreckan {
std::string m_fileName;
std::string m_treeName;
};
}
} // namespace corryvreckan
#endif // DATAOUTPUT_H
......@@ -6,11 +6,11 @@
Replaces the existing reference timestamp (earliest hit on reference plane) by either the trigger timestamp (method 0) or the average track timestamp (method 1). For method 0 to work, a trigger timestamp has to be saved as SPIDR signal during data taking.
#### Parameters
* `m_method`: Determines which method to use. Trigger timestamp is 0, average track timestamp is 1. Default value is `1`.
* `m_source`: Determines which detector plane carries the trigger signals. Only relevant for method 0. Default value is `"W0013_G02"`.
* `improvementMethod`: Determines which method to use. Trigger timestamp is 0, average track timestamp is 1. Default value is `1`.
* `signalSource`: Determines which detector plane carries the trigger signals. Only relevant for method 0. Default value is `"W0013_G02"`.
#### Plots produced
No plots are produced.
#### Usage
```toml
......
......@@ -20,7 +20,7 @@ void Timepix3Clustering::initialise() {
name = "clusterWidthColumn_" + detector->name();
clusterWidthColumn[detector->name()] = new TH1F(name.c_str(), name.c_str(), 25, 0, 25);
name = "clusterTot_" + detector->name();
clusterTot[detector->name()] = new TH1F(name.c_str(), name.c_str(), 200, 0, 1000);
clusterTot[detector->name()] = new TH1F(name.c_str(), name.c_str(), 10000, 0, 100000);
name = "clusterPositionGlobal_" + detector->name();
clusterPositionGlobal[detector->name()] = new TH2F(name.c_str(), name.c_str(), 400, -10., 10., 400, -10., 10.);
}
......
## Timepix3EventLoader
**Maintainer**: Daniel Hynds (<daniel.hynds@cern.ch>)
**Status**: Outdated
**Maintainer**: Daniel Hynds (<daniel.hynds@cern.ch>)
**Status**: Outdated
#### Description
This algorithm loads raw data from a Timepix3 device and adds it to the clipboard. The input file must have extension `.dat` and are sorted into time order via the data file serial numbers. This code also identifies `trimdac` files and applies this mask to the pixels.
......@@ -16,15 +16,19 @@ The hit timestamps are derived from the 40 MHz TOA counter and the fast on-pixel
* `minNumberOfPlanes`: Minimum number of planes with loaded data required for each event to be stored. Default value is `1`.
* `eventLength`: Length in time for each event. Default value is `0.0`. This is only used if `eventLength` is present in the configuration file, otherwise the data is split into events using the `number_of_pixelhits` parameter.
* `number_of_pixelhits`: Maximum number of pixel hits on each detector per event. Default value is `2000`. This is only used if `eventLength` is not present in the configuration file, otherwise the data is split into events using the `eventLength` parameter.
* `calibrationPath`: Path to the calibration directory. If this parameter is set, calibration will be applied to the DUT. Assumed folder structure is `"[calibrationPath]/[detector name]/cal_thr_[thr dac]_ik_[ikrum dac]/[detector name]_cal_[tot/toa].txt"`. The assumed file structure is `[col | row | val1 | val2 | etc.]`.
* `DUT`: Name of the DUT plane.
#### Plots produced
No plots are produced.
* Histogram with pixel ToT before and after calibration
* Map for each calibration paramater if calibration is used
#### Usage
```toml
[Timepix3EventLoader]
inputDirectory = "path/to/directory"
calibrationPath = "path/to/calibration"
threshold = 1148
applyTimingCut = false
timingCut = 0.0
minNumberOfPlanes = 5
......
#include "Timepix3EventLoader.h"
#include <bitset>
#include <cmath>
#include <dirent.h>
#include <fstream>
#include <sstream>
......@@ -27,6 +28,10 @@ Timepix3EventLoader::Timepix3EventLoader(Configuration config, std::vector<Detec
// Check whether event length or pixel count should be used to separate events:
m_eventLength = m_config.get<double>("eventLength", 0.0);
m_numberPixelHits = m_config.get<int>("number_of_pixelhits", 2000);
// Calibration parameters
calibrationPath = m_config.get<std::string>("calibrationPath", "");
threshold = m_config.get<std::string>("threshold", "");
}
void Timepix3EventLoader::initialise() {
......@@ -179,6 +184,41 @@ void Timepix3EventLoader::initialise() {
for(auto& detector : m_files) {
m_file_iterator[detector.first] = detector.second.begin();
}
// Calibration
std::string nameb = "pixelToT_beforecalibration";
std::string namea = "pixelToT_aftercalibration";
pixelToT_beforecalibration = new TH1F(nameb.c_str(), nameb.c_str(), 100, 0, 200);
if(m_config.has("calibrationPath") && m_config.has("threshold")) {
LOG(INFO) << "Applying calibration from " << calibrationPath;
applyCalibration = true;
// get DUT plane name
std::string DUT = m_config.get<std::string>("DUT");
// make paths to calibration files and read
int ret = 0;
std::string tmp;
tmp = calibrationPath + "/" + DUT + "/cal_thr_" + threshold + "_ik_10/" + DUT + "_cal_tot.txt";
loadCalibration(tmp, ' ', vtot);
tmp = calibrationPath + "/" + DUT + "/cal_thr_" + threshold + "_ik_10/" + DUT + "_cal_toa.txt";
loadCalibration(tmp, ' ', vtoa);
// make graphs of calibration parameters
LOG(DEBUG) << "Creating calibration graphs";
pixelTOTParamaterA = new TH2F("hist_par_a_tot", "hist_par_a_tot", 256, 0, 256, 256, 0, 256);
pixelTOTParamaterB = new TH2F("hist_par_b_tot", "hist_par_b_tot", 256, 0, 256, 256, 0, 256);
pixelTOTParamaterC = new TH2F("hist_par_c_tot", "hist_par_c_tot", 256, 0, 256, 256, 0, 256);
pixelTOTParamaterT = new TH2F("hist_par_t_tot", "hist_par_t_tot", 256, 0, 256, 256, 0, 256);
pixelTOAParamaterC = new TH2F("hist_par_c_toa", "hist_par_c_toa", 256, 0, 256, 256, 0, 256);
pixelTOAParamaterD = new TH2F("hist_par_d_toa", "hist_par_d_toa", 256, 0, 256, 256, 0, 256);
pixelTOAParamaterT = new TH2F("hist_par_t_toa", "hist_par_t_toa", 256, 0, 256, 256, 0, 256);
pixelToT_aftercalibration = new TH1F(namea.c_str(), namea.c_str(), 2000, 0, 20000);
} else {
LOG(INFO) << "No calibration file path given, data will be uncalibrated.";
applyCalibration = false;
}
}
StatusCode Timepix3EventLoader::run(Clipboard* clipboard) {
......@@ -271,6 +311,47 @@ void Timepix3EventLoader::maskPixels(Detector* detector, string trimdacfile) {
trimdacs.close();
}
// Function to load calibration data
void Timepix3EventLoader::loadCalibration(std::string path, char delim, std::vector<std::vector<float>>& dat) {
std::ifstream f;
f.open(path);
dat.clear();
// check if file is open
if(!f.is_open()) {
LOG(ERROR) << "Cannot open input file:\n\t" << path;
throw InvalidValueError(m_config, "calibrationPath", "Parsing error in calibration file.");
}
// read file line by line
int i = 0;
std::string line;
while(!f.eof()) {
std::getline(f, line);
// check if line is empty or a comment
// if not write to output vector
if(line.size() > 0 && isdigit(line.at(0))) {
std::stringstream ss(line);
std::string word;
std::vector<float> row;
while(std::getline(ss, word, delim)) {
i += 1;
row.push_back(stof(word));
}
dat.push_back(row);
}
}
// warn if too few entries
if(dat.size() != 256 * 256) {
LOG(ERROR) << "Something went wrong. Found only " << i << " entries. Not enough for TPX3.\n\t";
throw InvalidValueError(m_config, "calibrationPath", "Parsing error in calibration file.");
}
f.close();
}
// Function to load data for a given device, into the relevant container
bool Timepix3EventLoader::loadData(Clipboard* clipboard, Detector* detector, Pixels* devicedata, SpidrSignals* spidrData) {
......@@ -536,9 +617,59 @@ bool Timepix3EventLoader::loadData(Clipboard* clipboard, Detector* detector, Pix
}
// Otherwise create a new pixel object
Pixel* pixel = new Pixel(detectorID, row, col, (int)tot, time);
devicedata->push_back(pixel);
// bufferedData[detectorID]->push_back(pixel);
pixelToT_beforecalibration->Fill((int)tot);
// Apply calibration if applyCalibration is true
if(applyCalibration && detectorID == m_config.get<std::string>("DUT")) {
LOG(DEBUG) << "Applying calibration to DUT";
float a = vtot[256 * row + col][2];
float b = vtot[256 * row + col][3];
float c = vtot[256 * row + col][4];
float t = vtot[256 * row + col][5];
float toa_c = vtoa[256 * row + col][2];
float toa_t = vtoa[256 * row + col][3];
float toa_d = vtoa[256 * row + col][4];
// Calculating calibrated tot and toa
float fvolts =
(sqrt(a * a * t * t + 2 * a * b * t + 4 * a * c - 2 * a * t * tot + b * b - 2 * b * tot + tot * tot) +
a * t - b + tot) /
(2 * a);
float fcharge = fvolts * 1e-3 * 3e-15 * 6241.509 * 1e15; // capacitance is 3 fF or 18.7 e-/mV
/* Note 1: fvolts is the inverse to f(x) = a*x + b - c/(x-t). Note the +/- signs! */
/* Note 2: The capacitance is actually smaller than 3 fC, more like 2.5 fC. But there is an offset when when
* using testpulses. Multiplying the voltage value with 20 [e-/mV] is a good approximation but means one is
* over estimating the input capacitance to compensate the missing information of the offset. */
float t_shift = toa_c / (fvolts - toa_t) + toa_d;
long long int ftime =
time - ((t_shift * 1e-9 /* - _planeLatencyVec[detectorID]*1e-9*/) * (4096. * 40000000.));
if(col == 123 && row == 138) {
std::cout << col << " " << row << " " << a << " " << b << " " << fvolts << " " << fcharge << " "
<< t_shift << std::endl;
}
// creating new pixel object with calibrated values of tot and toa
Pixel* pixel = new Pixel(detectorID, row, col, fcharge, ftime);
devicedata->push_back(pixel);
LOG(DEBUG) << "Pixel Charge = " << fcharge << "; ToT value = " << tot;
pixelToT_aftercalibration->Fill(fcharge);
pixelTOTParamaterA->Fill(col, row, a);
pixelTOTParamaterB->Fill(col, row, b);
pixelTOTParamaterC->Fill(col, row, c);
pixelTOTParamaterT->Fill(col, row, t);
pixelTOAParamaterC->Fill(col, row, toa_c);
pixelTOAParamaterD->Fill(col, row, toa_d);
pixelTOAParamaterT->Fill(col, row, toa_t);
} else {
// creating new pixel object with non-calibrated values of tot and toa
Pixel* pixel = new Pixel(detectorID, row, col, (int)tot, time);
devicedata->push_back(pixel);
}
// bufferedData[detectorID]->push_back(pixel);
m_prevTime = time;
}
......
......@@ -2,6 +2,9 @@
#define TIMEPIX3EVENTLOADER_H 1
#include <stdio.h>
#include "TCanvas.h"
#include "TH1F.h"
#include "TH2F.h"
#include "core/algorithm/Algorithm.h"
#include "objects/Pixel.h"
#include "objects/SpidrSignal.h"
......@@ -19,8 +22,20 @@ namespace corryvreckan {
StatusCode run(Clipboard* clipboard);
void finalise();
// ROOT graphs
TH1F* pixelToT_beforecalibration;
TH1F* pixelToT_aftercalibration;
TH2F* pixelTOTParamaterA;
TH2F* pixelTOTParamaterB;
TH2F* pixelTOTParamaterC;
TH2F* pixelTOTParamaterT;
TH2F* pixelTOAParamaterC;
TH2F* pixelTOAParamaterD;
TH2F* pixelTOAParamaterT;
private:
bool loadData(Clipboard* clipboard, Detector* detector, Pixels*, SpidrSignals*);
void loadCalibration(std::string path, char delim, std::vector<std::vector<float>>& dat);
void maskPixels(Detector*, std::string);
// cofngiuration paramaters:
......@@ -34,6 +49,13 @@ namespace corryvreckan {
double m_eventLength;
int m_numberPixelHits;
bool applyCalibration;
std::string calibrationPath;
std::string threshold;
std::vector<std::vector<float>> vtot;
std::vector<std::vector<float>> vtoa;
// Member variables
std::map<std::string, std::vector<std::unique_ptr<std::ifstream>>> m_files;
std::map<std::string, std::vector<std::unique_ptr<std::ifstream>>::iterator> m_file_iterator;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment