Commit 77ad67db authored by Simon Spannagel's avatar Simon Spannagel
Browse files

Merge branch 'detectortypes' into 'master'

Introducing Detector Roles

See merge request !52
parents 85bced38 07454d31
Pipeline #545271 passed with stages
in 7 minutes and 14 seconds
......@@ -106,6 +106,9 @@ void Analysis::load() {
void Analysis::load_detectors() {
// Flag for the reference detector
bool found_reference = false;
std::vector<std::string> detectors_files = global_config.getPathArray("detectors_file");
for(auto& detectors_file : detectors_files) {
......@@ -127,11 +130,24 @@ void Analysis::load_detectors() {
LOG(INFO) << "Detector: " << name;
Detector* det_parm = new Detector(detector);
// Check if we already found a reference plane:
if(found_reference && det_parm->role() == DetectorRole::REFERENCE) {
throw InvalidValueError(global_config, "detectors_file", "Found more than one reference detector");
}
// Switch flag if we found the reference plane:
found_reference |= (det_parm->role() == DetectorRole::REFERENCE);
// Add the new detector to the global list:
detectors.push_back(det_parm);
}
}
// Check that exactly one detector is marked as reference:
if(!found_reference) {
throw InvalidValueError(global_config, "detectors_file", "Found no detector marked as reference");
}
LOG(STATUS) << "Loaded " << detectors.size() << " detectors";
// Finally, sort the list of detectors by z position (from lowest to highest)
......
......@@ -22,10 +22,27 @@ using namespace ROOT::Math;
using namespace corryvreckan;
Detector::Detector(const Configuration& config) {
// Get information from the conditions file:
// Role of this detector:
auto role = config.get<std::string>("role", "none");
std::transform(role.begin(), role.end(), role.begin(), ::tolower);
if(role == "none") {
m_role = DetectorRole::NONE;
} else if(role == "reference") {
m_role = DetectorRole::REFERENCE;
} else if(role == "dut") {
m_role = DetectorRole::DUT;
} else {
throw InvalidValueError(config, "role", "Detector role does not exist.");
}
// Detector position and orientation
m_displacement = config.get<ROOT::Math::XYZPoint>("position", ROOT::Math::XYZPoint());
m_orientation = config.get<ROOT::Math::XYZVector>("orientation", ROOT::Math::XYZVector());
m_orientation_mode = config.get<std::string>("orientation_mode", "xyz");
if(m_orientation_mode != "xyz" && m_orientation_mode != "zyx") {
throw InvalidValueError(config, "orientation_mode", "Invalid detector orientation mode");
}
// Number of pixels
auto npixels = config.get<ROOT::Math::DisplacementVector2D<Cartesian2D<int>>>("number_of_pixels");
......@@ -39,9 +56,8 @@ Detector::Detector(const Configuration& config) {
if(Units::convert(m_pitch.X(), "mm") >= 1 or Units::convert(m_pitch.Y(), "mm") >= 1 or
Units::convert(m_pitch.X(), "um") <= 1 or Units::convert(m_pitch.Y(), "um") <= 1) {
LOG(WARNING) << "Pixel pitch unphysical for detector " << m_detectorName << ".";
LOG(WARNING) << "Pitch X = " << Units::display(m_pitch.X(), {"nm", "um", "mm"})
<< " ; Pitch Y = " << Units::display(m_pitch.Y(), {"nm", "um", "mm"});
LOG(WARNING) << "Pixel pitch unphysical for detector " << m_detectorName << ": " << std::endl
<< Units::display(m_pitch, {"nm", "um", "mm"});
}
m_detectorType = config.get<std::string>("type");
......@@ -69,6 +85,14 @@ Detector::Detector(const Configuration& config) {
}
}
bool Detector::isReference() {
return m_role == DetectorRole::REFERENCE;
}
bool Detector::isDUT() {
return m_role == DetectorRole::DUT;
}
// Functions to set and check channel masking
void Detector::setMaskFile(std::string file) {
m_maskfile = file;
......@@ -133,8 +157,6 @@ void Detector::initialise() {
ROOT::Math::RotationX(m_orientation.X()));
} else if(m_orientation_mode == "zyx") {
rotations = Rotation3D(ROOT::Math::RotationZYX(m_orientation.x(), m_orientation.y(), m_orientation.x()));
} else {
throw RuntimeError("Invalid detector orientation mode: " + m_orientation_mode);
}
m_localToGlobal = Transform3D(rotations, translations);
......@@ -160,6 +182,13 @@ Configuration Detector::getConfiguration() {
Configuration config(name());
config.set("type", m_detectorType);
// Store the role of the detector
if(m_role == DetectorRole::REFERENCE) {
config.set("role", "reference");
} else if(m_role == DetectorRole::DUT) {
config.set("role", "dut");
}
config.set("position", m_displacement, {"um", "mm"});
config.set("orientation_mode", m_orientation_mode);
config.set("orientation", m_orientation, {"deg"});
......
......@@ -27,7 +27,21 @@
using namespace ROOT::Math;
namespace corryvreckan {
// Class containing just the detector parameters
/**
* @brief Role of the detector
*/
enum class DetectorRole {
NONE = 0, ///< No specific detector role
REFERENCE, ///< Reference detector
DUT, ///< Detector used as device under test
};
/**
* @brief Detector representation in the reconstruction chain
*
* Contains the detector with all its properties such as type, name, position and orientation, pitch, resolution etc.
*/
class Detector {
public:
// Constructors and desctructors
......@@ -39,6 +53,11 @@ namespace corryvreckan {
std::string type() { return m_detectorType; }
std::string name() { return m_detectorName; }
// Detector role and helper functions
DetectorRole role() { return m_role; }
bool isReference();
bool isDUT();
Configuration getConfiguration();
ROOT::Math::XYVector size() { return ROOT::Math::XYVector(m_pitch.X() * m_nPixelsX, m_pitch.Y() * m_nPixelsY); }
......@@ -108,7 +127,8 @@ namespace corryvreckan {
bool isWithinROI(Cluster* cluster);
private:
// Member variables
DetectorRole m_role;
// Detector information
std::string m_detectorType;
std::string m_detectorName;
......
......@@ -34,6 +34,20 @@ Detector* Module::get_detector(std::string name) {
return (*it);
}
Detector* Module::get_reference() {
auto it = find_if(m_detectors.begin(), m_detectors.end(), [](Detector* obj) { return obj->isReference(); });
return (*it);
}
Detector* Module::get_dut() {
auto it = find_if(m_detectors.begin(), m_detectors.end(), [](Detector* obj) { return obj->isDUT(); });
if(it == m_detectors.end()) {
return nullptr;
}
return (*it);
}
bool Module::has_detector(std::string name) {
auto it = find_if(m_detectors.begin(), m_detectors.end(), [&name](Detector* obj) { return obj->name() == name; });
if(it == m_detectors.end()) {
......
......@@ -134,6 +134,19 @@ namespace corryvreckan {
*/
Detector* get_detector(std::string name);
/**
* @brief Get the reference detector for this setup
* @return Pointer to the reference detector
*/
Detector* get_reference();
/**
* @brief Get the device under test
* @return Pointer to the DUT detector. A nullptr is returned if no DUT is found.
* FIXME This should allow retrieval of a vector of DUTs
*/
Detector* get_dut();
/**
* @brief Check if this module should act on a given detector
* @param name Name of the detector to check
......
......@@ -41,7 +41,7 @@ void ATLASpixEventLoader::initialise() {
// File structure is RunX/ATLASpix/data.dat
// Assume that the ATLASpix is the DUT (if running this algorithm
m_detectorID = m_config.get<std::string>("DUT");
// Open the root directory
DIR* directory = opendir(m_inputDirectory.c_str());
if(directory == NULL) {
......@@ -112,7 +112,7 @@ void ATLASpixEventLoader::initialise() {
}
// Make histograms for debugging
auto det = get_detector(m_detectorID);
auto det = get_dut();
hHitMap = new TH2F("hitMap", "hitMap", det->nPixelsX(), 0, det->nPixelsX(), det->nPixelsY(), 0, det->nPixelsY());
// hPixelToT = new TH1F("pixelToT", "pixelToT", 100, 0, 100);
// std::string totTitle = "pixelToT;x ToT in " + string(m_clockCycle) + " ns units";
......@@ -188,7 +188,7 @@ StatusCode ATLASpixEventLoader::run(Clipboard* clipboard) {
// Put the data on the clipboard
if(!pixels->empty()) {
clipboard->put(m_detectorID, "pixels", (Objects*)pixels);
clipboard->put(get_dut()->name(), "pixels", (Objects*)pixels);
} else {
return NoData;
}
......@@ -206,9 +206,7 @@ Pixels* ATLASpixEventLoader::read_caribou_data(double start_time, double end_tim
Pixels* pixels = new Pixels();
// Detector we're looking at:
auto detector = get_detector(m_detectorID);
// double timestamp = 0;
auto detector = get_dut();
// Read file and load data
uint32_t datain;
......@@ -325,7 +323,7 @@ Pixels* ATLASpixEventLoader::read_caribou_data(double start_time, double end_tim
<< "\tTS_FULL: " << hit_ts << "\t" << Units::display(timestamp, {"s", "us", "ns"})
<< "\tTOT: " << tot; // << "\t" << Units::display(tot_ns, {"s", "us", "ns"});
Pixel* pixel = new Pixel(m_detectorID, row, col, tot, timestamp);
Pixel* pixel = new Pixel(get_dut()->name(), row, col, tot, timestamp);
LOG(DEBUG) << "PIXEL:\t" << *pixel;
pixels->push_back(pixel);
......@@ -507,7 +505,7 @@ Pixels* ATLASpixEventLoader::read_legacy_data(double, double) {
m_file >> col >> row >> ts >> tot >> dummy >> dummy >> bincounter >> TriggerDebugTS;
auto detector = get_detector(m_detectorID);
auto detector = get_dut();
// If this pixel is masked, do not save it
if(detector->masked(col, row)) {
continue;
......@@ -560,7 +558,7 @@ Pixels* ATLASpixEventLoader::read_legacy_data(double, double) {
// Convert TOA to nanoseconds:
toa /= (4096. * 0.04);
Pixel* pixel = new Pixel(m_detectorID, row, col, cal_tot, toa);
Pixel* pixel = new Pixel(get_dut()->name(), row, col, cal_tot, toa);
pixel->setCharge(cal_tot);
pixels->push_back(pixel);
}
......
......@@ -50,7 +50,6 @@ namespace corryvreckan {
int m_eventNumber;
unsigned long long int m_oldtoa;
unsigned long long int m_overflowcounter;
std::string detectorID;
std::string m_filename;
std::ifstream m_file;
......@@ -76,7 +75,6 @@ namespace corryvreckan {
double m_eventLength;
double m_startTime;
bool m_toaMode;
std::string m_detectorID;
bool m_legacyFormat;
double m_clockCycle;
// int m_clkdivendM;
......
......@@ -26,4 +26,3 @@ This module requires either another event loader of another detector type before
DUT = "W0005_H03"
inputDirectory = /user/data/directory
```
Parameters to be used in multiple modules can also be defined globally at the top of the configuration file. This is highly encouraged for parameters such as `DUT` and `reference`.
......@@ -36,7 +36,7 @@ Alignment::Alignment(Configuration config, std::vector<Detector*> detectors)
if(m_config.has("detectorToAlign")) {
detectorToAlign = m_config.get<std::string>("detectorToAlign");
} else {
detectorToAlign = m_config.get<std::string>("DUT");
detectorToAlign = get_dut()->name();
}
LOG(INFO) << "Aligning detector \"" << detectorToAlign << "\"";
} else {
......@@ -399,8 +399,7 @@ void Alignment::finalise() {
string detectorID = detector->name();
// Do not align the reference plane
if(detectorID == m_config.get<std::string>("reference") ||
(m_config.has("DUT") && detectorID == m_config.get<std::string>("DUT"))) {
if(detector->isReference() || detector->isDUT()) {
continue;
}
......@@ -493,8 +492,7 @@ void Alignment::finalise() {
// Now list the new alignment parameters
for(auto& detector : get_detectors()) {
// Do not align the reference plane
if(detector->name() == m_config.get<std::string>("reference") ||
(m_config.has("DUT") && detector->name() == m_config.get<std::string>("DUT"))) {
if(detector->isReference() || detector->isDUT()) {
continue;
}
......
......@@ -55,4 +55,3 @@ alignmentMethod = 0
number_of_tracks = 1000000
log_level = INFO
```
Parameters to be used in multiple modules can also be defined globally at the top of the configuration file. This is highly encouraged for parameters such as `DUT` and `reference`.
......@@ -12,9 +12,7 @@ BasicTracking::BasicTracking(Configuration config, std::vector<Detector*> detect
timingCut = m_config.get<double>("timingCut", Units::convert(200, "ns"));
spatialCut = m_config.get<double>("spatialCut", Units::convert(0.2, "mm"));
minHitsOnTrack = m_config.get<int>("minHitsOnTrack", 6);
// checking if DUT parameter is in the configuration file, if so then check if the the DUT should be excluded, if not
// then set exclude the DUT
excludeDUT = (m_config.has("DUT") ? m_config.get<bool>("excludeDUT", true) : true);
excludeDUT = m_config.get<bool>("excludeDUT", true);
}
void BasicTracking::initialise() {
......@@ -74,7 +72,7 @@ StatusCode BasicTracking::run(Clipboard* clipboard) {
} else {
// Store them
LOG(DEBUG) << "Picked up " << tempClusters->size() << " clusters from " << detectorID;
if(firstDetector && (!m_config.has("DUT") || detectorID != m_config.get<std::string>("DUT"))) {
if(firstDetector && !detector->isDUT()) {
referenceClusters = tempClusters;
seedPlane = detector->name();
LOG(DEBUG) << "Seed plane is " << seedPlane;
......@@ -112,9 +110,11 @@ StatusCode BasicTracking::run(Clipboard* clipboard) {
// Loop over each subsequent plane and look for a cluster within the timing cuts
for(auto& detectorID : detectors) {
// Get the detector
auto det = get_detector(detectorID);
// Check if the DUT should be excluded and obey:
if(m_config.has("DUT") && excludeDUT && detectorID == m_config.get<std::string>("DUT")) {
if(excludeDUT && det->isDUT()) {
LOG(DEBUG) << "Skipping DUT plane.";
continue;
}
......@@ -138,8 +138,6 @@ StatusCode BasicTracking::run(Clipboard* clipboard) {
if(track->nClusters() > 1) {
track->fit();
// Get the detector
auto det = get_detector(detectorID);
PositionVector3D<Cartesian3D<double>> interceptPoint = det->getIntercept(track);
interceptX = interceptPoint.X();
interceptY = interceptPoint.Y();
......@@ -244,5 +242,3 @@ Cluster* BasicTracking::getNearestCluster(long long int timestamp, Clusters clus
return bestCluster;
}
void BasicTracking::finalise() {}
......@@ -23,7 +23,6 @@ namespace corryvreckan {
// Functions
void initialise();
StatusCode run(Clipboard* clipboard);
void finalise();
private:
// Cluster* getNearestCluster(Cluster*, map<Cluster*, bool>, Clusters*);
......@@ -52,8 +51,6 @@ namespace corryvreckan {
double spatialCut;
int minHitsOnTrack;
bool excludeDUT;
int associatedClusters;
};
} // namespace corryvreckan
#endif // BASICTRACKING_H
......@@ -42,4 +42,3 @@ DUT = "W13_01"
timingCut = 200ns
excludeDUT = true
```
Parameters to be used in multiple modules can also be defined globally at the top of the configuration file. This is highly encouraged for parameters such as `DUT` and `reference`.
......@@ -8,7 +8,6 @@ using namespace corryvreckan;
CLICpix2Analysis::CLICpix2Analysis(Configuration config, std::vector<Detector*> detectors)
: Module(std::move(config), std::move(detectors)) {
m_DUT = m_config.get<std::string>("DUT");
m_timeCutFrameEdge = m_config.get<double>("timeCutFrameEdge", Units::convert(20, "ns"));
......@@ -19,7 +18,7 @@ CLICpix2Analysis::CLICpix2Analysis(Configuration config, std::vector<Detector*>
void CLICpix2Analysis::initialise() {
// Get DUT detector:
auto det = get_detector(m_DUT);
auto det = get_dut();
hClusterMapAssoc = new TH2F(
"clusterMapAssoc", "clusterMapAssoc", det->nPixelsX(), 0, det->nPixelsX(), det->nPixelsY(), 0, det->nPixelsY());
......@@ -162,7 +161,7 @@ StatusCode CLICpix2Analysis::run(Clipboard* clipboard) {
}
// Get the DUT detector:
auto detector = get_detector(m_DUT);
auto detector = get_dut();
// Loop over all tracks
for(auto& track : (*tracks)) {
......@@ -218,7 +217,7 @@ StatusCode CLICpix2Analysis::run(Clipboard* clipboard) {
double ymod = Units::convert(detector->inPixelY(localIntercept), "um");
// Get the DUT clusters from the clipboard
Clusters* clusters = (Clusters*)clipboard->get(m_DUT, "clusters");
Clusters* clusters = (Clusters*)clipboard->get(get_dut()->name(), "clusters");
if(clusters == NULL) {
LOG(DEBUG) << " - no DUT clusters";
} else {
......
......@@ -59,7 +59,6 @@ namespace corryvreckan {
TH2F* hUnassociatedTracksGlobalPosition;
// Member variables
std::string m_DUT;
double spatialCut, m_timeCutFrameEdge;
double chi2ndofCut;
};
......
......@@ -36,4 +36,3 @@ Analysis module for CLICpix2 prototypes. This module is still work in progress,
timeCutFrameEdge = 50ns
```
Parameters to be used in multiple algorithms can also be defined globally at the top of the configuration file. This is highly encouraged for parameters such as `DUT` and `reference`.
......@@ -9,8 +9,6 @@ CLICpixEventLoader::CLICpixEventLoader(Configuration config, std::vector<Detecto
}
void CLICpixEventLoader::initialise() {
// Assume that the CLICpix is the DUT (if running this algorithm
detectorID = m_config.get<std::string>("DUT");
// File structure is RunX/CLICpix/RunX.dat
// Take input directory from global parameters
......@@ -50,7 +48,8 @@ void CLICpixEventLoader::initialise() {
StatusCode CLICpixEventLoader::run(Clipboard* clipboard) {
// LOG(TRACE) <<"Running"
// Assume that the CLICpix is the DUT (if running this algorithm
auto detector = get_dut();
// If have reached the end of file, close it and exit program running
if(m_file.eof()) {
......@@ -109,9 +108,9 @@ StatusCode CLICpixEventLoader::run(Clipboard* clipboard) {
LOG(TRACE) << "New pixel: " << col << "," << row << " with tot " << tot;
// If this pixel is masked, do not save it
if(get_detector(detectorID)->masked(col, row))
if(detector->masked(col, row))
continue;
Pixel* pixel = new Pixel(detectorID, row, col, tot, 0);
Pixel* pixel = new Pixel(detector->name(), row, col, tot, 0);
pixels->push_back(pixel);
npixels++;
hHitMap->Fill(col, row);
......@@ -126,7 +125,7 @@ StatusCode CLICpixEventLoader::run(Clipboard* clipboard) {
LOG(TRACE) << "Loaded " << npixels << " pixels";
// Put the data on the clipboard
if(pixels->size() > 0)
clipboard->put(detectorID, "pixels", (Objects*)pixels);
clipboard->put(detector->name(), "pixels", (Objects*)pixels);
// Fill histograms
hPixelsPerFrame->Fill(npixels);
......
......@@ -32,7 +32,6 @@ namespace corryvreckan {
// Member variables
int m_eventNumber;
std::string m_filename;
std::string detectorID;
std::ifstream m_file;
TH2F* hHitMap;
......
......@@ -23,4 +23,3 @@ The module opens and reads one data file in the specified input directory with t
DUT = "W0005_H03"
inputDirectory = /user/data/directory
```
Parameters to be used in multiple modules can also be defined globally at the top of the configuration file. This is highly encouraged for parameters such as `DUT` and `reference`.
# Define module and return the generated name as MODULE_NAME
CORRYVRECKAN_MODULE(MODULE_NAME)
# Add source files to library
CORRYVRECKAN_MODULE_SOURCES(${MODULE_NAME}
Clicpix2Correlator.cpp
# ADD SOURCE FILES HERE...
)
# Provide standard install target
CORRYVRECKAN_MODULE_INSTALL(${MODULE_NAME})
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