M3settings (#228)

* added temp m3 settings files

* renames settings noise to trim

* get threshold for M3

* some changes to compile on RH7 and in the server to load the default chip status register at startup

* Updated mythen3DeectorServer_developer executable with correct initialization at startup

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
Co-authored-by: Anna Bergamaschi <anna.bergamaschi@psi.ch>
This commit is contained in:
Dhanya Thattil
2021-01-14 12:34:13 +01:00
committed by GitHub
parent a62e068a9a
commit f9f50f1d84
89 changed files with 1715 additions and 8446 deletions

View File

@ -2,6 +2,7 @@
#include "SharedMemory.h"
#include "sls/ClientSocket.h"
#include "sls/ToString.h"
#include "sls/bit_utils.h"
#include "sls/container_utils.h"
#include "sls/file_utils.h"
#include "sls/network_utils.h"
@ -9,7 +10,6 @@
#include "sls/sls_detector_funcs.h"
#include "sls/string_utils.h"
#include "sls/versionAPI.h"
#include <algorithm>
#include <array>
#include <bitset>
@ -152,16 +152,237 @@ void Module::setSettings(detectorSettings isettings) {
sendToDetector<int>(F_SET_SETTINGS, isettings);
}
int Module::getThresholdEnergy() const {
return sendToDetector<int>(F_GET_THRESHOLD_ENERGY);
}
std::array<int, 3> Module::getAllThresholdEnergy() const {
return sendToDetector<std::array<int, 3>>(F_GET_ALL_THRESHOLD_ENERGY);
}
void Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
bool trimbits) {
// verify e_eV exists in trimEneregies[]
if (shm()->trimEnergies.empty() || (e_eV < shm()->trimEnergies.front()) ||
(e_eV > shm()->trimEnergies.back())) {
throw RuntimeError("This energy " + std::to_string(e_eV) +
" not defined for this module!");
}
bool interpolate =
std::all_of(shm()->trimEnergies.begin(), shm()->trimEnergies.end(),
[e_eV](const int &e) { return e != e_eV; });
sls_detector_module myMod{shm()->myDetectorType};
if (!interpolate) {
std::string settingsfname = getTrimbitFilename(isettings, e_eV);
LOG(logDEBUG1) << "Settings File is " << settingsfname;
myMod = readSettingsFile(settingsfname, trimbits);
} else {
// find the trim values
int trim1 = -1, trim2 = -1;
for (size_t i = 0; i < shm()->trimEnergies.size(); ++i) {
if (e_eV < shm()->trimEnergies[i]) {
trim2 = shm()->trimEnergies[i];
trim1 = shm()->trimEnergies[i - 1];
break;
}
}
std::string settingsfname1 = getTrimbitFilename(isettings, trim1);
std::string settingsfname2 = getTrimbitFilename(isettings, trim2);
LOG(logDEBUG1) << "Settings Files are " << settingsfname1 << " and "
<< settingsfname2;
auto myMod1 = readSettingsFile(settingsfname1, trimbits);
auto myMod2 = readSettingsFile(settingsfname2, trimbits);
if (myMod1.iodelay != myMod2.iodelay) {
throw RuntimeError("setThresholdEnergyAndSettings: Iodelays do not "
"match between files");
}
myMod = interpolateTrim(&myMod1, &myMod2, e_eV, trim1, trim2, trimbits);
myMod.iodelay = myMod1.iodelay;
myMod.tau =
linearInterpolation(e_eV, trim1, trim2, myMod1.tau, myMod2.tau);
}
myMod.reg = isettings;
myMod.eV[0] = e_eV;
setModule(myMod, trimbits);
if (getSettings() != isettings) {
throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
"settings in detector");
}
if (shm()->useReceiverFlag) {
sendToReceiver(F_RECEIVER_SET_THRESHOLD, e_eV, nullptr);
}
}
void Module::setAllThresholdEnergy(std::array<int, 3> e_eV,
detectorSettings isettings, bool trimbits) {
if (shm()->trimEnergies.empty()) {
throw RuntimeError(
"Trim energies have not been defined for this module yet!");
}
auto counters = getSetBits(getCounterMask());
enum mythen3_DacIndex {
M_VCASSH,
M_VTH2,
M_VRSHAPER,
M_VRSHAPER_N,
M_VIPRE_OUT,
M_VTH3,
M_VTH1,
M_VICIN,
M_VCAS,
M_VRPREAMP,
M_VCAL_N,
M_VIPRE,
M_VISHAPER,
M_VCAL_P,
M_VTRIM,
M_VDCSH
};
std::vector<sls_detector_module> myMods{shm()->myDetectorType};
std::vector<int> energy(e_eV.begin(), e_eV.end());
// if all energies are same
if (allEqualTo(energy, energy[0])) {
energy.resize(1);
}
myMods.resize(energy.size());
// for each threshold
for (size_t i = 0; i < energy.size(); ++i) {
// don't interpolate
if (shm()->trimEnergies.anyEqualTo(energy[i])) {
std::string settingsfname =
getTrimbitFilename(isettings, energy[i]);
LOG(logDEBUG1) << "Settings File is " << settingsfname;
myMods[i] = readSettingsFile(settingsfname, trimbits);
}
// interpolate
else {
if (shm()->trimEnergies.size() < 2) {
throw RuntimeError(
"Cannot interpolate with less than 2 trim energies");
}
// find the trim values
int trim1 = -1, trim2 = -1;
if (energy[i] < shm()->trimEnergies[0]) {
trim1 = shm()->trimEnergies[0];
trim2 = shm()->trimEnergies[1];
} else if (energy[i] >
shm()->trimEnergies[shm()->trimEnergies.size() - 1]) {
trim1 = shm()->trimEnergies[shm()->trimEnergies.size() - 2];
trim2 = shm()->trimEnergies[shm()->trimEnergies.size() - 1];
} else {
for (size_t j = 0; j < shm()->trimEnergies.size(); ++j) {
// std::cout << "checking " << energy[i] << " and "
// << shm()->trimEnergies[j] << std::endl;
if (energy[i] < shm()->trimEnergies[j]) {
trim1 = shm()->trimEnergies[j - 1];
trim2 = shm()->trimEnergies[j];
break;
}
}
}
LOG(logINFO) << "e_eV:" << energy[i] << " [" << trim1 << ", "
<< trim2 << "]";
std::string settingsfname1 = getTrimbitFilename(isettings, trim1);
std::string settingsfname2 = getTrimbitFilename(isettings, trim2);
LOG(logDEBUG1) << "Settings Files are " << settingsfname1 << " and "
<< settingsfname2;
auto myMod1 = readSettingsFile(settingsfname1, trimbits);
auto myMod2 = readSettingsFile(settingsfname2, trimbits);
myMods[i] = interpolateTrim(&myMod1, &myMod2, energy[i], trim1,
trim2, trimbits);
}
}
sls_detector_module myMod{shm()->myDetectorType};
myMod = myMods[0];
// if multiple thresholds, combine
if (myMods.size() > 1) {
// average vtrim of enabled counters
int sum = 0;
for (size_t i = 0; i < counters.size(); ++i) {
sum += myMods[counters[i]].dacs[M_VTRIM];
}
myMod.dacs[M_VTRIM] = sum / counters.size();
// copy vth1, vth2 and vth3 from the correct threshold mods
myMod.dacs[VTH1] = myMods[0].dacs[VTH1];
myMod.dacs[VTH2] = myMods[1].dacs[VTH2];
myMod.dacs[VTH3] = myMods[2].dacs[VTH3];
// check if dacs are different
for (size_t j = 0; j < 16; ++j) {
if (j == M_VTRIM || j == M_VTH1 || j == M_VTH2 || j == M_VTH3)
continue;
if (myMods[0].dacs[j] != myMods[1].dacs[j]) {
throw RuntimeError("Dac Index " + std::to_string(j) +
" differs for threshold[0]:[" +
std::to_string(myMods[0].dacs[j]) +
"] and threshold[1]:" +
std::to_string(myMods[1].dacs[j]) + "]");
}
if (myMods[1].dacs[j] != myMods[2].dacs[j]) {
throw RuntimeError("Dac Index " + std::to_string(j) +
" differs for threshold[1]:[" +
std::to_string(myMods[1].dacs[j]) +
"] and threshold[2]:" +
std::to_string(myMods[2].dacs[j]) + "]");
}
}
// replace correct trim values (interleaved)
for (int i = 0; i < myMod.nchan; ++i) {
myMod.chanregs[i] = myMods[i % 3].chanregs[i];
}
}
myMod.reg = isettings;
std::copy(e_eV.begin(), e_eV.end(), myMod.eV);
LOG(logDEBUG) << "ev:" << ToString(myMod.eV);
setModule(myMod, trimbits);
if (getSettings() != isettings) {
throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
"settings in detector");
}
if (shm()->useReceiverFlag) {
sendToReceiver(F_RECEIVER_SET_ALL_THRESHOLD, e_eV, nullptr);
}
}
std::string Module::getSettingsDir() const {
return std::string(shm()->settingsDir);
}
std::string Module::setSettingsDir(const std::string &dir) {
sls::strcpy_safe(shm()->settingsDir, dir.c_str());
return shm()->settingsDir;
}
void Module::loadSettingsFile(const std::string &fname) {
// find specific file if it has detid in file name (.snxxx)
if (shm()->myDetectorType == EIGER || shm()->myDetectorType == MYTHEN3) {
std::ostringstream ostfn;
ostfn << fname;
if (fname.find(".sn") == std::string::npos &&
fname.find(".trim") == std::string::npos &&
fname.find(".settings") == std::string::npos) {
ostfn << ".sn" << std::setfill('0') << std::setw(3) << std::dec
<< getSerialNumber();
int serialNumberWidth = 3;
if (shm()->myDetectorType == MYTHEN3) {
serialNumberWidth = 4;
}
if (fname.find(".sn") == std::string::npos) {
ostfn << ".sn" << std::setfill('0') << std::setw(serialNumberWidth)
<< std::dec << getSerialNumber();
}
auto myMod = readSettingsFile(ostfn.str());
setModule(myMod);
@ -178,6 +399,30 @@ void Module::setAllTrimbits(int val) {
sendToDetector<int>(F_SET_ALL_TRIMBITS, val);
}
std::vector<int> Module::getTrimEn() const {
if (shm()->myDetectorType != EIGER && shm()->myDetectorType != MYTHEN3) {
throw RuntimeError("getTrimEn not implemented for this detector.");
}
return std::vector<int>(shm()->trimEnergies.begin(),
shm()->trimEnergies.end());
}
int Module::setTrimEn(const std::vector<int> &energies) {
if (shm()->myDetectorType != EIGER && shm()->myDetectorType != MYTHEN3) {
throw RuntimeError("setTrimEn not implemented for this detector.");
}
if (energies.size() > MAX_TRIMEN) {
std::ostringstream os;
os << "Size of trim energies: " << energies.size()
<< " exceeds what can be stored in shared memory: " << MAX_TRIMEN
<< "\n";
throw RuntimeError(os.str());
}
shm()->trimEnergies = energies;
std::sort(shm()->trimEnergies.begin(), shm()->trimEnergies.end());
return shm()->trimEnergies.size();
}
bool Module::isVirtualDetectorServer() const {
return sendToDetector<int>(F_IS_VIRTUAL);
}
@ -1095,33 +1340,6 @@ void Module::setSubDeadTime(int64_t value) {
}
}
int Module::getThresholdEnergy() const {
return sendToDetector<int>(F_GET_THRESHOLD_ENERGY);
}
void Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
bool trimbits) {
// check as there is client processing
if (shm()->myDetectorType == EIGER) {
setThresholdEnergyAndSettings(e_eV, isettings, trimbits);
if (shm()->useReceiverFlag) {
sendToReceiver(F_RECEIVER_SET_THRESHOLD, e_eV, nullptr);
}
} else {
throw RuntimeError(
"Set threshold energy not implemented for this detector");
}
}
std::string Module::getSettingsDir() const {
return std::string(shm()->settingsDir);
}
std::string Module::setSettingsDir(const std::string &dir) {
sls::strcpy_safe(shm()->settingsDir, dir.c_str());
return shm()->settingsDir;
}
bool Module::getOverFlowMode() const {
return sendToDetector<int>(F_GET_OVERFLOW_MODE);
}
@ -1138,29 +1356,6 @@ void Module::setFlippedDataX(bool value) {
sendToReceiver<int>(F_SET_FLIPPED_DATA_RECEIVER, static_cast<int>(value));
}
std::vector<int> Module::getTrimEn() const {
if (shm()->myDetectorType != EIGER) {
throw RuntimeError("getTrimEn not implemented for this detector.");
}
return std::vector<int>(shm()->trimEnergies.begin(),
shm()->trimEnergies.end());
}
int Module::setTrimEn(const std::vector<int> &energies) {
if (shm()->myDetectorType != EIGER) {
throw RuntimeError("setTrimEn not implemented for this detector.");
}
if (energies.size() > MAX_TRIMEN) {
std::ostringstream os;
os << "Size of trim energies: " << energies.size()
<< " exceeds what can be stored in shared memory: " << MAX_TRIMEN
<< "\n";
throw RuntimeError(os.str());
}
shm()->trimEnergies = energies;
return shm()->trimEnergies.size();
}
int64_t Module::getRateCorrection() const {
return sendToDetector<int64_t>(F_GET_RATE_CORRECT);
}
@ -2749,9 +2944,9 @@ int Module::sendModule(sls_detector_module *myMod, sls::ClientSocket &client) {
ts += n;
LOG(level) << "tau sent. " << n << " bytes. tau: " << myMod->tau;
n = client.Send(&(myMod->eV), sizeof(myMod->eV));
n = client.Send(myMod->eV, sizeof(myMod->eV));
ts += n;
LOG(level) << "ev sent. " << n << " bytes. ev: " << myMod->eV;
LOG(level) << "ev sent. " << n << " bytes. ev: " << ToString(myMod->eV);
n = client.Send(myMod->dacs, sizeof(int) * (myMod->ndac));
ts += n;
@ -2799,68 +2994,12 @@ void Module::updateRateCorrection() {
sendToDetector(F_UPDATE_RATE_CORRECTION);
}
void Module::setThresholdEnergyAndSettings(int e_eV, detectorSettings isettings,
bool trimbits) {
// verify e_eV exists in trimEneregies[]
if (shm()->trimEnergies.empty() || (e_eV < shm()->trimEnergies.front()) ||
(e_eV > shm()->trimEnergies.back())) {
throw RuntimeError("This energy " + std::to_string(e_eV) +
" not defined for this module!");
}
bool interpolate =
std::all_of(shm()->trimEnergies.begin(), shm()->trimEnergies.end(),
[e_eV](const int &e) { return e != e_eV; });
sls_detector_module myMod{shm()->myDetectorType};
if (!interpolate) {
std::string settingsfname = getTrimbitFilename(isettings, e_eV);
LOG(logDEBUG1) << "Settings File is " << settingsfname;
myMod = readSettingsFile(settingsfname, trimbits);
} else {
// find the trim values
int trim1 = -1, trim2 = -1;
for (size_t i = 0; i < shm()->trimEnergies.size(); ++i) {
if (e_eV < shm()->trimEnergies[i]) {
trim2 = shm()->trimEnergies[i];
trim1 = shm()->trimEnergies[i - 1];
break;
}
}
std::string settingsfname1 = getTrimbitFilename(isettings, trim1);
std::string settingsfname2 = getTrimbitFilename(isettings, trim2);
LOG(logDEBUG1) << "Settings Files are " << settingsfname1 << " and "
<< settingsfname2;
auto myMod1 = readSettingsFile(settingsfname1, trimbits);
auto myMod2 = readSettingsFile(settingsfname2, trimbits);
if (myMod1.iodelay != myMod2.iodelay) {
throw RuntimeError("setThresholdEnergyAndSettings: Iodelays do not "
"match between files");
}
myMod = interpolateTrim(&myMod1, &myMod2, e_eV, trim1, trim2, trimbits);
myMod.iodelay = myMod1.iodelay;
myMod.tau =
linearInterpolation(e_eV, trim1, trim2, myMod1.tau, myMod2.tau);
}
myMod.reg = isettings;
myMod.eV = e_eV;
setModule(myMod, trimbits);
if (getSettings() != isettings) {
throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
"settings in detector");
}
}
sls_detector_module Module::interpolateTrim(sls_detector_module *a,
sls_detector_module *b,
const int energy, const int e1,
const int e2, bool trimbits) {
// only implemented for eiger currently (in terms of which dacs)
if (shm()->myDetectorType != EIGER) {
// dacs specified only for eiger and mythen3
if (shm()->myDetectorType != EIGER && shm()->myDetectorType != MYTHEN3) {
throw NotImplementedError(
"Interpolation of Trim values not implemented for this detector!");
}
@ -2884,36 +3023,72 @@ sls_detector_module Module::interpolateTrim(sls_detector_module *a,
E_VCN,
E_VIS
};
enum mythen3_DacIndex {
M_VCASSH,
M_VTH2,
M_VRSHAPER,
M_VRSHAPER_N,
M_VIPRE_OUT,
M_VTH3,
M_VTH1,
M_VICIN,
M_VCAS,
M_VRPREAMP,
M_VCAL_N,
M_VIPRE,
M_VISHAPER,
M_VCAL_P,
M_VTRIM,
M_VDCSH
};
// Copy other dacs
int dacs_to_copy[] = {E_SVP, E_VTR, E_SVN, E_VTGSTV,
E_RXB_RB, E_RXB_LB, E_VCN, E_VIS};
int num_dacs_to_copy = sizeof(dacs_to_copy) / sizeof(dacs_to_copy[0]);
for (int i = 0; i < num_dacs_to_copy; ++i) {
// create copy and interpolate dac lists
std::vector<int> dacs_to_copy, dacs_to_interpolate;
if (shm()->myDetectorType == EIGER) {
dacs_to_copy.insert(
dacs_to_copy.end(),
{E_SVP, E_VTR, E_SVN, E_VTGSTV, E_RXB_RB, E_RXB_LB, E_VCN, E_VIS});
// interpolate vrf, vcmp, vcp
dacs_to_interpolate.insert(
dacs_to_interpolate.end(),
{E_VRF, E_VCMP_LL, E_VCMP_LR, E_VCMP_RL, E_VCMP_RR, E_VCP, E_VRS});
} else {
dacs_to_copy.insert(dacs_to_copy.end(),
{M_VCASSH, M_VRSHAPER, M_VRSHAPER_N, M_VIPRE_OUT,
M_VICIN, M_VCAS, M_VRPREAMP, M_VCAL_N, M_VIPRE,
M_VISHAPER, M_VCAL_P, M_VDCSH});
// interpolate vtrim, vth1, vth2, vth3
dacs_to_interpolate.insert(dacs_to_interpolate.end(),
{M_VTH1, M_VTH2, M_VTH3, M_VTRIM});
}
// Copy Dacs
for (size_t i = 0; i < dacs_to_copy.size(); ++i) {
if (a->dacs[dacs_to_copy[i]] != b->dacs[dacs_to_copy[i]]) {
throw RuntimeError("Interpolate module: dacs different");
throw RuntimeError("Interpolate module: dacs " + std::to_string(i) +
" different");
}
myMod.dacs[dacs_to_copy[i]] = a->dacs[dacs_to_copy[i]];
}
// Copy irrelevant dacs (without failing): CAL
if (a->dacs[E_CAL] != b->dacs[E_CAL]) {
LOG(logWARNING) << "DAC CAL differs in both energies ("
<< a->dacs[E_CAL] << "," << b->dacs[E_CAL]
<< ")!\nTaking first: " << a->dacs[E_CAL];
}
myMod.dacs[E_CAL] = a->dacs[E_CAL];
// Interpolate vrf, vcmp, vcp
int dacs_to_interpolate[] = {E_VRF, E_VCMP_LL, E_VCMP_LR, E_VCMP_RL,
E_VCMP_RR, E_VCP, E_VRS};
int num_dacs_to_interpolate =
sizeof(dacs_to_interpolate) / sizeof(dacs_to_interpolate[0]);
for (int i = 0; i < num_dacs_to_interpolate; ++i) {
// Interpolate Dacs
for (size_t i = 0; i < dacs_to_interpolate.size(); ++i) {
myMod.dacs[dacs_to_interpolate[i]] =
linearInterpolation(energy, e1, e2, a->dacs[dacs_to_interpolate[i]],
b->dacs[dacs_to_interpolate[i]]);
}
// Copy irrelevant dacs (without failing)
if (shm()->myDetectorType == EIGER) {
// CAL
if (a->dacs[E_CAL] != b->dacs[E_CAL]) {
LOG(logWARNING)
<< "DAC CAL differs in both energies (" << a->dacs[E_CAL] << ","
<< b->dacs[E_CAL] << ")!\nTaking first: " << a->dacs[E_CAL];
}
myMod.dacs[E_CAL] = a->dacs[E_CAL];
}
// Interpolate all trimbits
if (trimbits) {
for (int i = 0; i < myMod.nchan; ++i) {
@ -2930,6 +3105,9 @@ std::string Module::getTrimbitFilename(detectorSettings s, int e_eV) {
case STANDARD:
ssettings = "/standard";
break;
case FAST:
ssettings = "/fast";
break;
case HIGHGAIN:
ssettings = "/highgain";
break;
@ -2948,8 +3126,20 @@ std::string Module::getTrimbitFilename(detectorSettings s, int e_eV) {
throw RuntimeError(ss.str());
}
std::ostringstream ostfn;
ostfn << shm()->settingsDir << ssettings << "/" << e_eV << "eV"
<< "/noise.sn" << std::setfill('0') << std::setw(3) << std::dec
ostfn << shm()->settingsDir << ssettings << "/" << e_eV << "eV";
if (shm()->myDetectorType == EIGER) {
ostfn << "/noise.sn";
} else if (shm()->myDetectorType == MYTHEN3) {
ostfn << "/trim.sn";
} else {
throw RuntimeError(
"Settings or trimbit files not defined for this detector.");
}
int serialNumberWidth = 3;
if (shm()->myDetectorType == MYTHEN3) {
serialNumberWidth = 4;
}
ostfn << std::setfill('0') << std::setw(serialNumberWidth) << std::dec
<< getSerialNumber() << std::setbase(10);
return ostfn.str();
}
@ -2976,6 +3166,11 @@ sls_detector_module Module::readSettingsFile(const std::string &fname,
infile.read(reinterpret_cast<char *>(&myMod.iodelay),
sizeof(myMod.iodelay));
infile.read(reinterpret_cast<char *>(&myMod.tau), sizeof(myMod.tau));
for (int i = 0; i < myMod.ndac; ++i) {
LOG(logDEBUG1) << "dac " << i << ":" << myMod.dacs[i];
}
LOG(logDEBUG1) << "iodelay:" << myMod.iodelay;
LOG(logDEBUG1) << "tau:" << myMod.tau;
if (trimbits) {
infile.read(reinterpret_cast<char *>(myMod.chanregs),
sizeof(int) * (myMod.nchan));
@ -2985,28 +3180,24 @@ sls_detector_module Module::readSettingsFile(const std::string &fname,
"for settings for " +
fname);
}
for (int i = 0; i < myMod.ndac; ++i) {
LOG(logDEBUG1) << "dac " << i << ":" << myMod.dacs[i];
}
LOG(logDEBUG1) << "iodelay:" << myMod.iodelay;
LOG(logDEBUG1) << "tau:" << myMod.tau;
}
// mythen3 (dacs, trimbits)
else if (shm()->myDetectorType == MYTHEN3) {
infile.read(reinterpret_cast<char *>(myMod.dacs),
sizeof(int) * (myMod.ndac));
infile.read(reinterpret_cast<char *>(myMod.chanregs),
sizeof(int) * (myMod.nchan));
for (int i = 0; i < myMod.ndac; ++i) {
LOG(logDEBUG) << "dac " << i << ":" << myMod.dacs[i];
}
if (trimbits) {
infile.read(reinterpret_cast<char *>(myMod.chanregs),
sizeof(int) * (myMod.nchan));
}
if (!infile) {
throw RuntimeError("readSettingsFile: Could not load all values "
"for settings for " +
fname);
}
for (int i = 0; i < myMod.ndac; ++i) {
LOG(logDEBUG1) << "dac " << i << ":" << myMod.dacs[i];
}
}
else {