diff --git a/ana/tot/s-curves.py b/ana/tot/s-curves.py index 8e715c58e..569b0d585 100644 --- a/ana/tot/s-curves.py +++ b/ana/tot/s-curves.py @@ -45,7 +45,7 @@ def toa_conv(df): ax[1].plot(ch_df['calib'], toa_conv(ch_df)) plt.show() -quit() +#quit() if (args.plot_adc): fig, ax = plt.subplots(1,1) @@ -73,6 +73,7 @@ def toa_conv(df): fig_toa, ax_toa = plt.subplots(1, 2, sharey=True) fig_tot, ax_tot = plt.subplots(1, 2, sharey=True) fig_adc, ax_adc = plt.subplots(1, 1) +fig_ch, ax_ch = plt.subplots(8,9, sharex=True) # Efficiency calculation def efficiency(vals): @@ -110,7 +111,7 @@ def condition_max(vals): max_non_saturated = 0 for ch_id, ch_df in ch_group: if ch_id == 0: - ax_toa[0].plot(ch_df['calib'], ch_df['toa_eff'], label=f'channels') + ax_toa[0].plot(ch_df['calib'], ch_df['toa_eff'], label=f'channels', linewidth = 0.2) ax_tot[0].plot(ch_df['calib'], ch_df['tot_eff'], label=f'channels') ax_toa[1].plot(ch_df['max_adc'], ch_df['toa_eff'], label=f'channels') ax_tot[1].plot(ch_df['max_adc'], ch_df['tot_eff'], label=f'channels') @@ -125,6 +126,7 @@ def condition_max(vals): max_val = temp_df['max_adc'].max() if (max_val > max_non_saturated): max_non_saturated = max_val + ax_ch[ch_id // 9, ch_id % 9].plot(ch_df['calib'], ch_df['toa_eff'], label=ch_id) ax_adc.axhline(y = max_non_saturated, linestyle='--', color='b', label=f'max non-saturated at {max_non_saturated}') @@ -144,6 +146,7 @@ def condition_max(vals): fig_toa.savefig("toa_s_curve.png", dpi=400) fig_tot.savefig("tot_s_curve.png", dpi=400) fig_adc.savefig("adc_linearity.png", dpi=400) +#fig_ch.savefig("toa_s_curve_channel.png", dpi=400) plt.show() #fig_toa.savefig('toa_efficiency.png', dpi=400, bbox_inches='tight') #fig_tot.savefig('tot_efficiency.png', dpi=400, bbox_inches='tight') diff --git a/app/tool/algorithm/get_calibs.cxx b/app/tool/algorithm/get_calibs.cxx deleted file mode 100644 index 0f9b3c24c..000000000 --- a/app/tool/algorithm/get_calibs.cxx +++ /dev/null @@ -1,82 +0,0 @@ -#include "get_calibs.h" - -#include -#include - -#include "../daq_run.h" -#include "pflib/utility/efficiency.h" -#include "pflib/utility/string_format.h" - -namespace pflib::algorithm { - -std::array get_calibs(Target* tgt, ROC& roc, size_t& n_events, - int& target_adc) { - static auto the_log_{::pflib::logging::get("get_calibs")}; - std::array calibs; - /// reserve a vector of the appropriate size to avoid repeating allocation - /// time for all 72 channels - DecodeAndBuffer buffer{1, 2}; - for (int ch{0}; ch < 72; ch++) { - // Set up for highrange charge injection on channel - pflib_log(info) << "Getting calib for channel " << ch; - // TODO 348 - int i_link = ch / 36; - auto refvol_page = - pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); - auto ch_page = pflib::utility::string_format("CH_%d", ch); - // We don't want TOT to trigger because our ADC will go to -1. We therefore - // set the TOA_VREF to 0. This is not pretty but I couldn't find any other - // parameter to set to turn of the TOT overwriting the ADC. - auto test_param_handle = roc.testParameters() - .add(refvol_page, "INTCTEST", 1) - .add(refvol_page, "CHOICE_CINJ", 1) - .add(ch_page, "HIGHRANGE", 1) - .add(refvol_page, "TOA_VREF", 0) - .apply(); - // Here we're starting at a value well above the saturation of the adc - // Would prefer to set this in reference to the pedestal for extra safety. - int calib = 1000; - int nr_bx = 3; - while (true) { - pflib_log(info) << "Testing calib = " << calib; - auto calib_handle = - roc.testParameters().add(refvol_page, "CALIB", calib).apply(); - usleep(10); - std::vector adcs; - auto central_charge_to_l1a = tgt->fc().fc_get_setup_calib(); - // We need to scan different BXs because the max adc is not neccessarilly - // in the first one. Need to add phase scan here as well. Currently the bx - // scan is not working for some reason. Needs a fix. - // for (int bx = 0; bx < nr_bx; bx++) { - // tgt->fc().fc_setup_calib(central_charge_to_l1a + bx); - // usleep(10); - // tgt->daq_run("CHARGE", buffer, 1, 100); - // auto data = buffer.get_buffer(); - // for (std::size_t i{0}; i < data.size(); i++) { - // adcs.push_back(data[i].channel(ch).adc()); - // } - //} - daq_run(tgt, "CHARGE", buffer, n_events, 100); - auto data = buffer.get_buffer(); - for (std::size_t i{0}; i < data.size(); i++) { - adcs.push_back( - data[i].samples[data[i].i_soi].channel(i_link, ch % 36).adc()); - } - int max_adc = *std::max_element(adcs.begin(), adcs.end()); - if (std::abs(max_adc - target_adc) <= 2) { - calibs[ch] = calib; - pflib_log(info) << "Final calib = " << calib; - break; - } else if (max_adc > target_adc) { - calib -= 50; - continue; - } else if (max_adc < target_adc) { - calib += 1; - } - } - } - pflib_log(info) << "Calib retrieved for all channels"; - return calibs; -} - -} // namespace pflib::algorithm diff --git a/app/tool/algorithm/global_pedestal_level.cxx b/app/tool/algorithm/global_pedestal_level.cxx index 628bb6e8a..cf1295a40 100644 --- a/app/tool/algorithm/global_pedestal_level.cxx +++ b/app/tool/algorithm/global_pedestal_level.cxx @@ -26,8 +26,10 @@ void DataFitter::sort_and_append(std::vector& inv_vrefs, }; std::vector slope_points; + // derivs should be around -1.4 in the linear region. These upper and lower + // bounds sort outliers. double flat_threshold = 0.1; - double linear_threshold = 10; + double linear_threshold = 5; std::vector LH_derivs; std::vector LH_stdevs; std::vector RH_derivs; @@ -125,8 +127,8 @@ int DataFitter::linear_fit(int& target) { pflib_log(info) << "Fitting Data"; // preform a linear fit - int x_sum = 0; - int y_sum = 0; + double x_sum = 0; + double y_sum = 0; for (const auto& p : linear_) { x_sum += p.x_; @@ -246,7 +248,7 @@ global_pedestal_level(Target* tgt) { } } - int target_adc = 200; + int target_adc = 150; DecodeAndBuffer buffer{nevents, tgt->nrocs() * 2}; diff --git a/app/tool/algorithm/toa_scan.cxx b/app/tool/algorithm/toa_scan.cxx new file mode 100644 index 000000000..9f7b45dc8 --- /dev/null +++ b/app/tool/algorithm/toa_scan.cxx @@ -0,0 +1,250 @@ + +#include "toa_scan.h" + +#include "../daq_run.h" +#include "../tasks/toa_scan.h" +#include "pflib/utility/median.h" +#include "pflib/utility/string_format.h" + +namespace pflib::algorithm { + +std::map>> toa_scan( + Target* tgt) { + static auto the_log_{::pflib::logging::get("toa_scan")}; + + // define parameters + size_t n_events = pftool::readline_int("How many events per time point?", 10); + int target_calib = pftool::readline_int("Target calib?", 1200); + int vref_buffer = pftool::readline_int("Vref buffer?", 5); + std::map> trim_targets; + const pflib::packing::SingleECONDRocErxMapping& mapping = + tgt->getRocErxMapping(); + DecodeAndBuffer buffer{n_events, tgt->nrocs() * 2}; + tgt->setup_run(1, Target::DaqFormat::ECOND_SW_HEADERS, 1); + + // set parameters to find target vrefs + int trim_toa_initial = 63; // gives us space to change trim_toa + std::map> calibs; + std::map> parameters; + + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + parameters[ch_page]["TRIM_TOA"] = trim_toa_initial; + } + auto test_params = tgt->tempApplyAllROCs(parameters); + + std::map> vrefs; + for (int i_roc : tgt->roc_ids()) { + vrefs[i_roc] = {-1, -1}; + } + + // loop over runs, from toa_vref = 0 to = 255 + for (int toa_vref{255}; toa_vref >= 0; toa_vref--) { + // looks for highest toa_vref where pedestals activate toa + std::map> vref_parameters; + vref_parameters["REFERENCEVOLTAGE_0"]["TOA_VREF"] = toa_vref; + vref_parameters["REFERENCEVOLTAGE_1"]["TOA_VREF"] = toa_vref; + auto vref_test_params = tgt->tempApplyAllROCs(vref_parameters); + usleep(10); + + daq_run(tgt, "PEDESTAL", buffer, n_events, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + + for (int i_roc : tgt->roc_ids()) { + for (int ch{0}; ch < 72; ch++) { + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, ch); + for (std::size_t i{0}; i < data.size(); i++) { + double toa = data[i].soi().channel(i_erx, i_ch).toa(); + if ((toa > 0) && (vrefs[i_roc][ch / 36] == -1)) { + vrefs[i_roc][ch / 36] = toa_vref + vref_buffer; + pflib_log(info) << "Roc: " << i_roc << " link: " << ch / 36 + << " vref: " << vrefs[i_roc][ch / 36]; + } + } + } + } + bool done = true; + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + if (vrefs[i_roc][i_link] == -1) { + done = false; + } + } + } + if (done) { + pflib_log(info) << "First sweep done"; + break; + } + } + + // set parameters to center target vref around target calib + std::map> vref_targets; + for (int i_roc : tgt->roc_ids()) { + vref_targets[i_roc] = {-1, -1}; + } + + std::map>> + buffer_parameters; + + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + std::string refvol_page{ + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link)}; + buffer_parameters[i_roc][refvol_page]["INTCTEST"] = 1; + buffer_parameters[i_roc][refvol_page]["CHOICE_CINJ"] = 1; + } + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + buffer_parameters[i_roc][ch_page]["TRIM_TOA"] = 31; + } + } + auto buffer_test_params = tgt->tempApplyAllROCs(buffer_parameters); + + bool complete = false; + + // increases target vref until half of channels are below 0.5 eff at trim_toa + // = 32 + while (!complete) { + std::map>> + buffer_vrefs; + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + std::string refvol_page{ + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link)}; + buffer_vrefs[i_roc][refvol_page]["TOA_VREF"] = vrefs[i_roc][i_link]; + buffer_vrefs[i_roc][refvol_page]["CALIB"] = target_calib; + } + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + buffer_vrefs[i_roc][ch_page]["HIGHRANGE"] = 0; + buffer_vrefs[i_roc][ch_page]["LOWRANGE"] = 1; + } + } + auto buffer_test_vrefs = tgt->tempApplyAllROCs(buffer_vrefs); + usleep(10); + + daq_run(tgt, "CHARGE", buffer, n_events, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + for (int i_roc : tgt->roc_ids()) { + std::array low_ch = {0, 0}; + for (int ch{0}; ch < 72; ch++) { + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, ch); + double sum = 0; + for (std::size_t i{0}; i < data.size(); i++) { + double toa = data[i].soi().channel(i_erx, i_ch).toa(); + if (toa > 0) { + sum += 1; + } + } + double eff = sum / data.size(); + if (eff <= 0.5) { + low_ch[ch / 36] += 1; + } + } + for (int i_link{0}; i_link < 2; i_link++) { + // pflib_log(info) << "link: " << i_link << " vref: " << + // vrefs[i_roc][i_link] << " low: " << low_ch[i_link]; + if ((low_ch[i_link] >= 18) && (vref_targets[i_roc][i_link] == -1)) { + vref_targets[i_roc][i_link] = vrefs[i_roc][i_link]; + pflib_log(info) << "Roc: " << i_roc << " link: " << i_link + << " vref: " << vref_targets[i_roc][i_link]; + } else if (vref_targets[i_roc][i_link] == -1) { + vrefs[i_roc][i_link] += 1; + } + } + } + complete = true; + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + if (vref_targets[i_roc][i_link] == -1) { + complete = false; + } + } + } + } + pflib_log(info) << "Second sweep done"; + + // set parameters to find trim_toa + std::map>> + link_parameters; + + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + std::string refvol_page{ + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link)}; + link_parameters[i_roc][refvol_page]["INTCTEST"] = 1; + link_parameters[i_roc][refvol_page]["CHOICE_CINJ"] = 1; + link_parameters[i_roc][refvol_page]["TOA_VREF"] = + vref_targets[i_roc][i_link]; + link_parameters[i_roc][refvol_page]["CALIB"] = target_calib; + } + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + link_parameters[i_roc][ch_page]["HIGHRANGE"] = 0; + link_parameters[i_roc][ch_page]["LOWRANGE"] = 1; + } + } + auto link_test_params = tgt->tempApplyAllROCs(link_parameters); + + // finds eff by trim_toa + std::map, 72>> effs; + for (int trim_toa{0}; trim_toa < 64; trim_toa++) { + pflib_log(info) << "Finding effs for trim_toa: " << trim_toa; + std::map> toa_parameters; + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + toa_parameters[ch_page]["TRIM_TOA"] = trim_toa; + } + auto toa_test_params = tgt->tempApplyAllROCs(toa_parameters); + usleep(10); + + daq_run(tgt, "CHARGE", buffer, n_events, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + + for (int i_roc : tgt->roc_ids()) { + for (int ch{0}; ch < 72; ch++) { + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, ch); + double sum = 0; + for (std::size_t i{0}; i < data.size(); i++) { + double toa = data[i].soi().channel(i_erx, i_ch).toa(); + if (toa > 0) { + sum += 1; + } + } + effs[i_roc][ch][trim_toa] = sum / data.size(); + } + } + } + + // finds trim_toa right before toa reaches 0.5 eff + for (int i_roc : tgt->roc_ids()) { + pflib_log(info) << "Finding trim_toa for roc " << i_roc; + for (int ch{0}; ch < 72; ch++) { + for (int trim_toa{63}; trim_toa >= 0; trim_toa--) { + if ((effs[i_roc][ch][trim_toa] <= 0.5) || (trim_toa == 0)) { + pflib_log(info) << "trim_toa for ch " << ch << ": " << trim_toa; + trim_targets[i_roc][ch] = trim_toa; + break; + } + } + } + } + + // create settings page + std::map>> + settings; + for (int i_roc : tgt->roc_ids()) { + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + settings[i_roc][ch_page]["TRIM_TOA"] = trim_targets[i_roc][ch]; + } + for (int i_link = 0; i_link < 2; i_link++) { + auto refvol_page = + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); + settings[i_roc][refvol_page]["TOA_VREF"] = vref_targets[i_roc][i_link]; + } + } + return settings; +} + +} // namespace pflib::algorithm diff --git a/app/tool/algorithm/tot_vref_scan.h b/app/tool/algorithm/toa_scan.h similarity index 57% rename from app/tool/algorithm/tot_vref_scan.h rename to app/tool/algorithm/toa_scan.h index a2c0253d4..cd8f9a639 100644 --- a/app/tool/algorithm/tot_vref_scan.h +++ b/app/tool/algorithm/toa_scan.h @@ -9,13 +9,13 @@ namespace pflib::algorithm { /** - * Find TOT threshold voltage + * Find toa_vref per link + * Find trim_toa per channel * * @param[in] tgt pointer to Target to interact with * - * @note Only functional for single-ROC targets */ -std::map> tot_vref_scan( - Target* tgt, ROC roc, size_t n_events_calib); +std::map>> toa_scan( + Target* tgt); } // namespace pflib::algorithm diff --git a/app/tool/algorithm/tot_scan.cxx b/app/tool/algorithm/tot_scan.cxx new file mode 100644 index 000000000..920e64d75 --- /dev/null +++ b/app/tool/algorithm/tot_scan.cxx @@ -0,0 +1,311 @@ +#include "tot_scan.h" + +#include "../daq_run.h" +#include "../tasks/tot_scan.h" +#include "pflib/utility/median.h" +#include "pflib/utility/string_format.h" + +namespace pflib::algorithm { + +std::map>> tot_scan( + Target* tgt) { + static auto the_log_{::pflib::logging::get("tot_scan")}; + + size_t n_events = pftool::readline_int("How many events per time point?", 10); + int target_calib = + pftool::readline_int("At which calib should tot activate?", 455); + + std::map> vref_targets; + std::map> trim_targets; + const pflib::packing::SingleECONDRocErxMapping& mapping = + tgt->getRocErxMapping(); + DecodeAndBuffer buffer{n_events, tgt->nrocs() * 2}; + tgt->setup_run(1, Target::DaqFormat::ECOND_SW_HEADERS, 1); + + // find target calibs + int tot_vref_initial = 420; + int trim_tot_initial = 31; + std::map> calibs; + std::map> parameters; + + // applies test parameters + for (int i_link{0}; i_link < 2; i_link++) { + std::string refvol_page{ + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link)}; + parameters[refvol_page]["TOT_VREF"] = tot_vref_initial; + parameters[refvol_page]["INTCTEST"] = 1; + parameters[refvol_page]["CHOICE_CINJ"] = 1; + } + + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + parameters[ch_page]["TRIM_TOT"] = trim_tot_initial; + parameters[ch_page]["LOWRANGE"] = 0; + parameters[ch_page]["HIGHRANGE"] = 0; + } + auto test_params = tgt->tempApplyAllROCs(parameters); + + // binary search through calib, finding calib just before tot activation + for (int i_roc : tgt->roc_ids()) { + calibs[i_roc].resize(72); + } + for (int ch{0}; ch < 72; ch++) { + std::map>> + calib_parameters; + bool complete = false; + auto ch_page = pflib::utility::string_format("CH_%d", ch); + std::map low; + std::map high; + std::map mid; + for (int i_roc : tgt->roc_ids()) { + low[i_roc] = 0; + high[i_roc] = 1000; + calibs[i_roc][ch] = -1; + } + while (!complete) { + for (int i_roc : tgt->roc_ids()) { + if (calibs[i_roc][ch] != -1) { + continue; + } + mid[i_roc] = (low[i_roc] + high[i_roc] + 1) / 2; + if (ch / 36 == 0) { + calib_parameters[i_roc]["REFERENCEVOLTAGE_0"]["CALIB"] = mid[i_roc]; + calib_parameters[i_roc][ch_page]["HIGHRANGE"] = 1; + } else { + calib_parameters[i_roc]["REFERENCEVOLTAGE_1"]["CALIB"] = mid[i_roc]; + calib_parameters[i_roc][ch_page]["HIGHRANGE"] = 1; + } + } + auto calib_test_params = tgt->tempApplyAllROCs(calib_parameters); + usleep(10); + daq_run(tgt, "CHARGE", buffer, n_events, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + + for (int i_roc : tgt->roc_ids()) { + if (calibs[i_roc][ch] != -1) { + continue; + } + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, ch); + double sum = 0; + for (std::size_t i{0}; i < data.size(); i++) { + double tot = data[i].soi().channel(i_erx, i_ch).tot(); + if (tot >= 0) { + sum += 1; + } + } + double eff = sum / data.size(); + if (eff <= 0.5) { + low[i_roc] = mid[i_roc]; + } else { + high[i_roc] = mid[i_roc] - 1; + } + if (low[i_roc] == high[i_roc]) { + calibs[i_roc][ch] = low[i_roc]; + } + } + complete = true; + for (int i_roc : tgt->roc_ids()) { + if (calibs[i_roc][ch] == -1) { + complete = false; + } + } + } + for (int i_roc : tgt->roc_ids()) { + pflib_log(info) << "Calib for ch " << ch << ": " << calibs[i_roc][ch]; + } + } + // finds and stores middle calib for each link + std::map> channels; + for (int i_roc : tgt->roc_ids()) { + std::vector l0(calibs[i_roc].begin(), calibs[i_roc].begin() + 36); + std::vector l1(calibs[i_roc].begin() + 36, calibs[i_roc].end()); + + int median_calib_l0 = pflib::utility::median(l0); + int median_calib_l1 = pflib::utility::median(l1); + + pflib_log(info) << "Roc: " << i_roc; + pflib_log(info) << "L0 median calib: " << median_calib_l0; + pflib_log(info) << "L1 median calib: " << median_calib_l1; + + std::vector filtered_l0; + for (int val : l0) { + if (std::abs(val - median_calib_l0) <= 100) { + filtered_l0.push_back(val); + } + } + std::vector filtered_l1; + for (int val : l1) { + if (std::abs(val - median_calib_l1) <= 100) { + filtered_l1.push_back(val); + } + } + int target_l0 = + (*std::min_element(filtered_l0.begin(), filtered_l0.end()) + + *std::max_element(filtered_l0.begin(), filtered_l0.end())) / + 2; + + int target_l1 = + (*std::min_element(filtered_l1.begin(), filtered_l1.end()) + + *std::max_element(filtered_l1.begin(), filtered_l1.end())) / + 2; + + auto it_l0 = + std::min_element(l0.begin(), l0.end(), [target_l0](int a, int b) { + return std::abs(a - target_l0) < std::abs(b - target_l0); + }); + channels[i_roc][0] = std::distance(l0.begin(), it_l0); + + auto it_l1 = + std::min_element(l1.begin(), l1.end(), [target_l1](int a, int b) { + return std::abs(a - target_l1) < std::abs(b - target_l1); + }); + channels[i_roc][1] = std::distance(l1.begin(), it_l1) + 36; + + pflib_log(info) << "Using channel: " << channels[i_roc][0]; + pflib_log(info) << "Using channel: " << channels[i_roc][1]; + } + + // finds tot_vref per link which causes 0.5 tot eff on target calib + // uses the channel with median calib found before to calibrate + for (int i_roc : tgt->roc_ids()) { + pflib_log(info) << "Getting tot_vref for roc: " << i_roc; + for (int i_link = 0; i_link < 2; i_link++) { + pflib_log(info) << "link: " << i_link; + std::map> vref_parameters; + bool complete = false; + int tot_vref = 1000; + auto ch_page = + pflib::utility::string_format("CH_%d", channels[i_roc][i_link]); + auto refvol_page = + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); + int tot_decrease = 50; + while (!complete) { + pflib_log(info) << "Testing tot_vref: " << tot_vref; + vref_parameters[ch_page]["TRIM_TOT"] = 31; + vref_parameters[ch_page]["HIGHRANGE"] = 1; + vref_parameters[refvol_page]["CALIB"] = target_calib; + vref_parameters[refvol_page]["TOT_VREF"] = tot_vref; + auto vref_test_params = tgt->tempApplyAllROCs(vref_parameters); + usleep(10); + + daq_run(tgt, "CHARGE", buffer, n_events, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + auto [i_erx, i_ch] = + mapping.toErxChannel(i_roc, channels[i_roc][i_link]); + double sum = 0; + for (std::size_t i{0}; i < data.size(); i++) { + double tot = data[i].soi().channel(i_erx, i_ch).tot(); + if (tot >= 0) { + sum += 1; + } + } + double eff = sum / data.size(); + if (eff >= 0.5) { + complete = true; + ; + } + if ((complete == true) && (tot_decrease != 1)) { + tot_vref += 50; + tot_decrease = 1; + complete = false; + } else if (((complete == true) && (tot_decrease == 1)) || + (tot_vref == 0)) { + break; + } + tot_vref -= tot_decrease; + } + pflib_log(info) << "tot_vref for link " << i_link << ": " << tot_vref; + vref_targets[i_roc][i_link] = tot_vref; + } + } + // finds trim_tot right before tot reaches 0.5 eff for each channel + std::map>> + pre_tot_parameters; + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + auto refvol_page = + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); + pre_tot_parameters[i_roc][refvol_page]["CALIB"] = target_calib; + pre_tot_parameters[i_roc][refvol_page]["TOT_VREF"] = + vref_targets[i_roc][i_link]; + } + } + auto pre_tot_test_params = tgt->tempApplyAllROCs(pre_tot_parameters); + + for (int i_roc : tgt->roc_ids()) { + trim_targets[i_roc].fill(-1); + } + + for (int ch{0}; ch < 72; ch++) { + pflib_log(info) << "Getting trim values for channel " << ch; + auto ch_page = pflib::utility::string_format("CH_%d", ch); + bool complete = false; + std::map>> + tot_parameters; + for (int trim_tot = 63; trim_tot >= 0; trim_tot--) { + for (int i_roc : tgt->roc_ids()) { + if (trim_targets[i_roc][ch] != -1) { + continue; + } + if (ch / 36 == 0) { + tot_parameters[i_roc][ch_page]["HIGHRANGE"] = 1; + tot_parameters[i_roc][ch_page]["TRIM_TOT"] = trim_tot; + } else { + tot_parameters[i_roc][ch_page]["HIGHRANGE"] = 1; + tot_parameters[i_roc][ch_page]["TRIM_TOT"] = trim_tot; + } + } + auto tot_test_params = tgt->tempApplyAllROCs(tot_parameters); + usleep(10); + + daq_run(tgt, "CHARGE", buffer, n_events, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + for (int i_roc : tgt->roc_ids()) { + if (trim_targets[i_roc][ch] != -1) { + continue; + } + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, ch); + double sum = 0; + for (std::size_t i{0}; i < data.size(); i++) { + double tot = data[i].soi().channel(i_erx, i_ch).tot(); + if (tot >= 0) { + sum += 1; + } + } + double eff = sum / data.size(); + if ((eff <= 0.5) || (trim_tot == 0)) { + trim_targets[i_roc][ch] = trim_tot; + } + } + bool complete = true; + for (int i_roc : tgt->roc_ids()) { + if (trim_targets[i_roc][ch] == -1) { + complete = false; + break; + } + } + if (complete == true) { + break; + } + } + } + + // create settings page + std::map>> + settings; + for (int i_roc : tgt->roc_ids()) { + for (int i_link{0}; i_link < 2; i_link++) { + auto refvol_page = + pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); + settings[i_roc][refvol_page]["TOT_VREF"] = vref_targets[i_roc][i_link]; + } + + for (int ch{0}; ch < 72; ch++) { + auto ch_page = pflib::utility::string_format("CH_%d", ch); + settings[i_roc][ch_page]["TRIM_TOT"] = trim_targets[i_roc][ch]; + } + } + return settings; +} + +} // namespace pflib::algorithm diff --git a/app/tool/algorithm/get_calibs.h b/app/tool/algorithm/tot_scan.h similarity index 50% rename from app/tool/algorithm/get_calibs.h rename to app/tool/algorithm/tot_scan.h index 1d51ad849..d14017f64 100644 --- a/app/tool/algorithm/get_calibs.h +++ b/app/tool/algorithm/tot_scan.h @@ -9,13 +9,12 @@ namespace pflib::algorithm { /** - * Find calib value where the max adc corresponds to a target value + * Find tot_vref per link and trim_tot per channel * * @param[in] tgt pointer to Target to interact with - * roc for setting params - * target calib value + * */ -std::array get_calibs(Target* tgt, ROC& roc, size_t& n_events, - int& target_adc); +std::map>> tot_scan( + Target* tgt); } // namespace pflib::algorithm diff --git a/app/tool/algorithm/tot_vref_scan.cxx b/app/tool/algorithm/tot_vref_scan.cxx deleted file mode 100644 index be1864be0..000000000 --- a/app/tool/algorithm/tot_vref_scan.cxx +++ /dev/null @@ -1,58 +0,0 @@ -#include "tot_vref_scan.h" - -#include "../daq_run.h" -#include "../tasks/tot_vref_scan.h" -#include "get_calibs.h" -#include "pflib/utility/string_format.h" -#include "tp50_scan.h" -#include "trim_tot_scan.h" - -namespace pflib::algorithm { - -std::map> tot_vref_scan( - Target* tgt, ROC roc, size_t n_events_calib) { - static auto the_log_{::pflib::logging::get("tot_vref_scan")}; - - // Iterate through each channel. First, find the CALIB that corresponds to - // a maximum ADC of 950. Second, do an efficiency scan to find the 50% - // efficiency mark. Set the tot_vref to the point closest to this mark. Then, - // move on to the next channel. Find the CALIB. Scan the efficiency for the - // current tot_vref. If the efficiency is < 0.5, then move on the the next - // channel. If the efficiency is > 0.5, raise the tot_vref by increments of 1 - // until the efficiency is < 0.5. - // Find the trim values to set the tot threshold where it is just below 0.5 - // efficiency. - - // Get the calibs for all channels - int target_adc = 950; // What target does CMS use? This should be hardcoded - - std::array calibs; - std::array - vref_targets; // tot_vref is a global parameter (1 value per link) - std::array trim_targets; - - size_t n_events = 100; - - tgt->setup_run(1, Target::DaqFormat::ECOND_SW_HEADERS, 1); - - calibs = get_calibs(tgt, roc, n_events_calib, target_adc); - vref_targets = tp50_scan(tgt, roc, n_events, calibs, vref_targets); - trim_targets = - trim_tot_scan(tgt, roc, n_events, calibs, vref_targets, trim_targets); - - std::map> settings; - for (int i_link{0}; i_link < 2; i_link++) { - auto refvol_page = - pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); - settings[refvol_page]["TOT_VREF"] = vref_targets[i_link]; - } - - for (int ch{0}; ch < 72; ch++) { - auto ch_page = pflib::utility::string_format("CH_%d", ch); - settings[ch_page]["TRIM_TOT"] = trim_targets[ch]; - } - - return settings; -} - -} // namespace pflib::algorithm diff --git a/app/tool/algorithm/tp50_scan.cxx b/app/tool/algorithm/tp50_scan.cxx deleted file mode 100644 index aa678bf08..000000000 --- a/app/tool/algorithm/tp50_scan.cxx +++ /dev/null @@ -1,173 +0,0 @@ -#include "tp50_scan.h" - -#include - -#include "../daq_run.h" -#include "pflib/utility/efficiency.h" -#include "pflib/utility/string_format.h" -#include "tp50_scan.h" - -namespace pflib::algorithm { - -double eff_scan(Target* tgt, ROC& roc, int& channel, int& vref_value, - size_t& n_events, auto& refvol_page, auto& buffer, - int& i_link) { // will the script understand auto refvol_page - // and auto buffer? - static auto the_log_{::pflib::logging::get("tp50_scan:eff_scan")}; - auto vref_test_param = roc.testParameters() - .add(refvol_page, "TOT_VREF", vref_value) - .apply(); // applying relevant parameters - usleep(10); - - // daq run - daq_run(tgt, "CHARGE", buffer, n_events, 100); - - auto data = buffer.get_buffer(); - std::vector tot_list; - for (std::size_t i{0}; i < data.size(); i++) { - // TODO 348 - double tot = - data[i].samples[data[i].i_soi].channel(i_link, channel % 36).tot(); - if (tot >= 0) { // tot = -1 when it is not triggered - tot_list.push_back(tot); - } - } - - double tot_eff = static_cast(tot_list.size()) / - n_events; // calculating tot efficiency - return tot_eff; -} - -int global_vref_scan(Target* tgt, ROC& roc, int& channel, size_t& n_events, - auto& refvol_page, auto& buffer, int& i_link) { - static auto the_log_{::pflib::logging::get("tp50_scan:global_vref_scan")}; - std::vector tot_eff_list; - std::vector vref_list = {0, 600}; - int vref_value{100000}; - double tol{0.3}; - int max_its = 40; - - while (true) { - if (std::abs(vref_list.back() - vref_list.front()) <= 1) { - pflib_log(info) << "Search converged"; - break; - } - // Bisectional search - if (!tot_eff_list.empty()) { - if (tot_eff_list.back() > 0.5) { - vref_list.front() = vref_value; - } else { - vref_list.back() = vref_value; - } - vref_value = (vref_list.back() + vref_list.front()) / 2; - } else { - vref_value = (vref_list.back() + vref_list.front()) / 2; - } - pflib_log(info) << "the vref value is " << vref_value; - double efficiency = eff_scan(tgt, roc, channel, vref_value, n_events, - refvol_page, buffer, i_link); - pflib_log(info) << "tot efficiency is " << efficiency; - if (std::abs(efficiency - 0.5) < tol) { - pflib_log(info) << "Efficiency within tolerance!"; - break; - } - - if (vref_value == 0 || vref_value == 600) { - pflib_log(info) << "No tp_50 was found! Channel " << channel; - vref_value = -1; - break; - } - - tot_eff_list.push_back( - efficiency); // vref with tot_eff was found, but tot_eff - 0.5 !< tol - - // if the tot_eff is consistently above tolerance, we limit the iterations - if (tot_eff_list.size() > max_its) { - pflib_log(info) << "Ended after " << max_its << " iterations!" << '\n' - << "Final vref is : " << vref_value - << " with tot_eff = " << efficiency - << " for channel : " << channel; - break; - } - } - pflib_log(info) << "Final vref value is " << vref_value; - if (vref_value == -1) { - throw std::invalid_argument( - "No TOT values found on this channel! Have you set TOA parameters?"); - } - return vref_value; -} - -int local_vref_scan(Target* tgt, ROC& roc, int& channel, int& vref_value, - size_t& n_events, auto& refvol_page, auto& buffer, - int& i_link) { - // Increase vref value until eff < 0.5 - static auto the_log_{::pflib::logging::get("tp50_scan:local_vref_scan")}; - for (int vref = vref_value; vref <= 600; vref++) { - pflib_log(info) << "Testing vref = " << vref; - double efficiency = eff_scan(tgt, roc, channel, vref, n_events, refvol_page, - buffer, i_link); - pflib_log(info) << "tot efficiency is " << efficiency; - if (efficiency < 0.5) { - return vref; - } - } - pflib_log(info) << "No vref found for this channel!"; - return vref_value; -} - -std::array tp50_scan(Target* tgt, ROC& roc, size_t& n_events, - std::array& calib, - std::array& link_vref_list) { - static auto the_log_{::pflib::logging::get("tp50_scan")}; - - // TODO 348 - link_vref_list = { - -1, -1}; // results array, which will hold the best vref for each link - - for (int channel{0}; channel < 72; channel++) { - pflib_log(info) << "Scanning channel " << channel << " for tp50, " - << "using CALIB " << calib[channel]; - - int i_link = channel / 36; - auto channel_page = pflib::utility::string_format("CH_%d", channel); - auto refvol_page = - pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); - auto test_param_handle = roc.testParameters() - .add(refvol_page, "INTCTEST", 1) - .add(refvol_page, "CHOICE_CINJ", 1) - .add(refvol_page, "CALIB", calib[channel]) - .add(channel_page, "HIGHRANGE", 1) - .apply(); - - DecodeAndBuffer buffer{n_events, 2}; - - int vref = link_vref_list[i_link]; - - if (vref == -1) { - pflib_log(info) << "Doing a global scan"; - vref = global_vref_scan(tgt, roc, channel, n_events, refvol_page, buffer, - i_link); - link_vref_list[i_link] = vref; - pflib_log(info) << "vref = " << vref; - continue; - } - double channel_eff = eff_scan(tgt, roc, channel, vref, n_events, - refvol_page, buffer, i_link); - - if (channel_eff < 0.5) { - pflib_log(info) << "Channel accounted for by previous vref!"; - continue; - } else { - pflib_log(info) - << "Scanning vref's local neighbourhood for a more suitable vref..."; - int channel_vref = local_vref_scan(tgt, roc, channel, vref, n_events, - refvol_page, buffer, i_link); - pflib_log(info) << "New vref is " << channel_vref; - link_vref_list[i_link] = channel_vref; - } - } - return link_vref_list; -} - -} // namespace pflib::algorithm diff --git a/app/tool/algorithm/tp50_scan.h b/app/tool/algorithm/tp50_scan.h deleted file mode 100644 index d9acce7f3..000000000 --- a/app/tool/algorithm/tp50_scan.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "pflib/Target.h" - -/** - * @namespace pflib::algorithm - * housing of higher-level methods for repeatable tasks - */ -namespace pflib::algorithm { - -/** - * Find TOT threshold voltage that corresponds to 50% efficiency for a given - * pulse - * - * @param[in] tgt pointer to Target to interact with - * roc - * calib: target calib - * tot_vref: previously set tot_vref - * - * @note Only functional for single-ROC targets - */ -std::array tp50_scan(Target* tgt, ROC& roc, size_t& n_events, - std::array& calibs, - std::array& link_vref_list); - -} // namespace pflib::algorithm diff --git a/app/tool/algorithm/trim_tot_scan.cxx b/app/tool/algorithm/trim_tot_scan.cxx deleted file mode 100644 index 3e45df8f2..000000000 --- a/app/tool/algorithm/trim_tot_scan.cxx +++ /dev/null @@ -1,72 +0,0 @@ -#include "trim_tot_scan.h" - -#include - -#include "../daq_run.h" -#include "pflib/utility/efficiency.h" -#include "pflib/utility/string_format.h" - -namespace pflib::algorithm { - -std::array trim_tot_scan(Target* tgt, ROC& roc, size_t& n_events, - std::array& calibs, - std::array& tot_vrefs, - std::array& tot_trims) { - static auto the_log_{::pflib::logging::get("trim_tot_scan")}; - - // Iterate through each channel. For each channel, trim down the tot threshold - // and set the parameter to the point which minimizes abs(tot_efficiency-0.5). - - auto tot_vref_handle = roc.testParameters(); - for (int i{0}; i < 2; i++) { - auto refvol_page = pflib::utility::string_format("REFERENCEVOLTAGE_%d", i); - tot_vref_handle.add(refvol_page, "TOT_VREF", tot_vrefs[i]) - .add(refvol_page, "INTCTEST", 1) - .add(refvol_page, "CHOICE_CINJ", 1); - } - auto tot_vref_params = tot_vref_handle.apply(); - - // TODO 348 - DecodeAndBuffer buffer{n_events, 2}; // working in buffer, not in writer - - for (int ch{0}; ch < 72; ch++) { - pflib_log(info) << "scanning channel " << ch; - int target{0}; - // Set the calib value - int i_link = ch / 36; - auto refvol_page = - pflib::utility::string_format("REFERENCEVOLTAGE_%d", i_link); - auto ch_page = pflib::utility::string_format("CH_%d", ch); - auto calib_handle = roc.testParameters() - .add(refvol_page, "CALIB", calibs[ch]) - .add(ch_page, "HIGHRANGE", 1) - .apply(); - // Run the threshold scan TP50 that gives the tot_vref value as output - for (int trim_tot{0}; trim_tot < 64; trim_tot++) { - pflib_log(info) << "testing trim_tot = " << trim_tot; - auto test_handle = - roc.testParameters().add(ch_page, "TRIM_TOT", trim_tot).apply(); - usleep(10); - daq_run(tgt, "CHARGE", buffer, n_events, 100); - auto data = buffer.get_buffer(); - std::vector tots(data.size()); - for (std::size_t i{0}; i < tots.size(); i++) { - tots[i] = data[i].samples[data[i].i_soi].channel(i_link, ch % 36).tot(); - } - auto efficiency = pflib::utility::efficiency(tots); - pflib_log(info) << "tot efficiency is " << efficiency; - if (efficiency < 0.5) { - target = trim_tot; - continue; - } else { - break; // We want the threshold slightly below 0.5, so use last val. - } - } - pflib_log(info) << "Final trim_tot = " << target; - tot_trims[ch] = target; - } - pflib_log(info) << "Trim_tot retrieved for all channels"; - return tot_trims; -} - -} // namespace pflib::algorithm diff --git a/app/tool/algorithm/trim_tot_scan.h b/app/tool/algorithm/trim_tot_scan.h deleted file mode 100644 index 2cc431965..000000000 --- a/app/tool/algorithm/trim_tot_scan.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "pflib/Target.h" - -/** - * @namespace pflib::algorithm - * housing of higher-level methods for repeatable tasks - */ -namespace pflib::algorithm { - -/** - * Find trim_toa to align TOA for each channel - * - * @param[in] tgt pointer to Target to interact with - * - * @note Only functional for single-ROC targets - */ -std::array trim_tot_scan(Target* tgt, ROC& roc, size_t& n_events, - std::array& calibs, - std::array& tot_vrefs, - std::array& tot_trims); - -} // namespace pflib::algorithm diff --git a/app/tool/tasks/channel_wise_calib_scan.cxx b/app/tool/tasks/channel_wise_calib_scan.cxx index 7016babe8..31cc2938d 100644 --- a/app/tool/tasks/channel_wise_calib_scan.cxx +++ b/app/tool/tasks/channel_wise_calib_scan.cxx @@ -33,8 +33,10 @@ void channel_wise_calib_scan(Target* tgt) { for (int ch = 0; ch < 72; ch++) { auto ch_page = pflib::utility::string_format("CH_%d", ch); setup_parameters[ch_page]["LOWRANGE"] = 0; + setup_parameters[ch_page]["HIGHRANGE"] = 0; } auto test_setup_params = tgt->tempApplyAllROCs(setup_parameters); + int central_charge_to_l1a; int charge_to_l1a{0}; int phase_strobe{0}; @@ -45,6 +47,7 @@ void channel_wise_calib_scan(Target* tgt) { int n_links{tgt->nrocs() * 2}; int calib{0}; int ch{0}; + std::map fnames; std::map outputs; for (int i_roc : tgt->roc_ids()) { @@ -54,6 +57,7 @@ void channel_wise_calib_scan(Target* tgt) { outputs[i_roc] << "time,calib,channel," << pflib::packing::Sample::to_csv_header << '\n'; } + DecodeAndWriteToCSV writer{ "channel-wise-calib-scan", [&](std::ofstream&) {}, [&](std::ofstream&, @@ -74,7 +78,7 @@ void channel_wise_calib_scan(Target* tgt) { pflib_log(info) << "Scanning channel " << ch; auto channel_page = pflib::utility::string_format("CH_%d", ch); for (calib = min_calib; calib < max_calib; calib += stepsize) { - // pflib_log(info) << "CALIB = " << calib; + pflib_log(info) << "CALIB = " << calib; std::map> parameters; if (ch < 36) { parameters["REFERENCEVOLTAGE_0"]["CALIB"] = calib; @@ -95,7 +99,7 @@ void channel_wise_calib_scan(Target* tgt) { phase_parameters; phase_parameters["TOP"]["PHASE_STROBE"] = phase_strobe; auto test_phase_params = tgt->tempApplyAllROCs(phase_parameters); - // pflib_log(info) << "TOP.PHASE_STROBE = " << phase_strobe; + pflib_log(info) << "TOP.PHASE_STROBE = " << phase_strobe; usleep(10); // make sure parameters are applied time = (charge_to_l1a - central_charge_to_l1a + offset) * clock_cycle - diff --git a/app/tool/tasks/examine_phase.cxx b/app/tool/tasks/examine_phase.cxx new file mode 100644 index 000000000..42c604d54 --- /dev/null +++ b/app/tool/tasks/examine_phase.cxx @@ -0,0 +1,165 @@ +#include "examine_phase.h" + +#include +#include + +#include "../daq_run.h" +#include "pflib/utility/efficiency.h" +#include "pflib/utility/mean.h" +#include "pflib/utility/string_format.h" + +void scan_phase_strobe(Target* tgt, pflib::ROC& roc, int i_roc, + DecodeAndBuffer& buffer, int nevents) { + static auto the_log_{::pflib::logging::get("scan_phase_strobe")}; + // scans and prints the effect of phase_strobe + int nr_bx = 5; + int central_charge_to_l1a = tgt->fc().fc_get_setup_calib(); + if (central_charge_to_l1a > 3) { + tgt->fc().fc_setup_calib(central_charge_to_l1a - 2); + } else if (central_charge_to_l1a == 3) { + tgt->fc().fc_setup_calib(central_charge_to_l1a - 1); + } + pflib::DAQ& daq = tgt->daq(); + int initial_nr_bx = daq.samples_per_ror(); + daq.setup(daq.econid(), nr_bx, daq.soi()); + tgt->fc().setL1AperROR(nr_bx); + + pflib_log(info) << "Scanning phase_strobe"; + for (int phase_strobe = 0; phase_strobe < 16; phase_strobe++) { + pflib_log(info) << "Phase_strobe: " << phase_strobe; + auto test_param = roc.testParameters() + .add("REFERENCEVOLTAGE_0", "INTCTEST", 1) + .add("REFERENCEVOLTAGE_0", "CHOICE_CINJ", 1) + .add("CH_17", "HIGHRANGE", 1) + .add("REFERENCEVOLTAGE_0", "TOA_VREF", 0) + .add("REFERENCEVOLTAGE_0", "CALIB", 400) + .add("TOP", "PHASE_STROBE", phase_strobe) + .apply(); + + std::map> adcs; + usleep(10); + daq_run(tgt, "CHARGE", buffer, nevents, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + auto mapping = tgt->getRocErxMapping(); + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, 17); + for (std::size_t i{0}; i < data.size(); i++) { + for (int j = 0; j < nr_bx; j++) { + adcs[j].push_back(data[i].samples.at(j).channel(i_erx, i_ch).adc()); + } + } + pflib_log(info) << "phase_strobe: " << phase_strobe; + for (int j = 0; j < nr_bx; j++) { + int mean_adc = pflib::utility::mean(adcs[j]); + pflib_log(info) << "bx: " << tgt->fc().fc_get_setup_calib() + j + << " adc: " << mean_adc; + } + } + tgt->fc().fc_setup_calib(central_charge_to_l1a); + daq.setup(daq.econid(), initial_nr_bx, daq.soi()); + tgt->fc().setL1AperROR(initial_nr_bx); +} + +void scan_phase_ck(Target* tgt, DecodeAndBuffer& buffer, int nevents) { + static auto the_log_{::pflib::logging::get("scan_phase_ck")}; + // Scans and prints the effect of phase_ck + + for (int phase_ck = 0; phase_ck < 16; phase_ck++) { + pflib_log(info) << "Scanning phase_ck = " << phase_ck; + + std::map> parameters; + parameters["TOP"]["PHASE_CK"] = phase_ck; + + auto test_params = tgt->tempApplyAllROCs(parameters); + usleep(10); + + daq_run(tgt, "PEDESTAL", buffer, nevents, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + std::map> adcs; + + for (int i_roc : tgt->roc_ids()) { + pflib_log(info) << "Roc: " << i_roc; + const pflib::packing::SingleECONDRocErxMapping& mapping = + tgt->getRocErxMapping(); + for (int ch = 0; ch < 72; ch++) { + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, ch); + for (std::size_t i{0}; i < data.size(); i++) { + adcs[i_roc].push_back(data[i].soi().channel(i_erx, i_ch).adc()); + } + } + pflib_log(info) << "phase_ck: " << phase_ck + << " adc: " << pflib::utility::mean(adcs[i_roc]); + } + } +} + +int peak_bx(Target* tgt, pflib::ROC& roc, int i_roc, DecodeAndBuffer& buffer, + int nevents) { + static auto the_log_{::pflib::logging::get("peak_bx")}; + // finds bx of charge injection peak + bool keep_going = true; + int bx_calib = 1000; + while (keep_going) { + for (int bx = 1; bx <= 100; bx++) { + std::vector adcs; + // set parameters + auto test_param = roc.testParameters() + .add("REFERENCEVOLTAGE_0", "INTCTEST", 1) + .add("REFERENCEVOLTAGE_0", "CHOICE_CINJ", 1) + .add("CH_17", "HIGHRANGE", 1) + .add("REFERENCEVOLTAGE_0", "TOA_VREF", 0) + .add("REFERENCEVOLTAGE_0", "CALIB", bx_calib) + .add("TOP", "PHASE_STROBE", 0) + .apply(); + tgt->fc().fc_setup_calib(bx); + pflib_log(info) << "Testing bx: " << tgt->fc().fc_get_setup_calib(); + usleep(10); + + // do a run and collect data + daq_run(tgt, "CHARGE", buffer, nevents, pftool::state.daq_rate); + auto data = buffer.get_buffer(); + auto mapping = tgt->getRocErxMapping(); + auto [i_erx, i_ch] = mapping.toErxChannel(i_roc, 17); + for (std::size_t i{0}; i < data.size(); i++) { + adcs.push_back(data[i].soi().channel(i_erx, i_ch).adc()); + } + + // determine if we have reached the peak + int max_adc = *std::max_element(adcs.begin(), adcs.end()); + pflib_log(info) << "max adc: " << max_adc; + if (max_adc == 1023) { + keep_going = false; + break; + } + } + + if (keep_going == true && bx_calib < 4000) { + bx_calib += 100; + } else { + break; + } + } + auto central_charge_to_l1a = tgt->fc().fc_get_setup_calib(); + pflib_log(info) << "Final bx: " << central_charge_to_l1a; + return central_charge_to_l1a; +} + +void examine_phase(Target* tgt) { + static auto the_log_{::pflib::logging::get("examine_phase")}; + static const std::size_t nevents = + pftool::readline_int("How many events per time point? ", 100); + pflib::ROC roc{tgt->roc(pftool::state.iroc)}; + int i_roc = pftool::state.iroc; + DecodeAndBuffer buffer{nevents, 2 * tgt->nrocs()}; + tgt->setup_run(1, Target::DaqFormat::ECOND_SW_HEADERS, 1); + + // find bx of charge pulse + int central_charge_to_l1a = peak_bx(tgt, roc, i_roc, buffer, nevents); + + // scan phase_ck + scan_phase_ck(tgt, buffer, nevents); + + // scan phase_strobe + scan_phase_strobe(tgt, roc, i_roc, buffer, nevents); + + pflib_log(info) << "bx is set to " << tgt->fc().fc_get_setup_calib(); +} diff --git a/app/tool/tasks/examine_phase.h b/app/tool/tasks/examine_phase.h new file mode 100644 index 000000000..ec9f81e32 --- /dev/null +++ b/app/tool/tasks/examine_phase.h @@ -0,0 +1,20 @@ + +#pragma once + +#include "../daq_run.h" +#include "../pftool.h" + +/** + * TASKS.EXAMINE_PHASE + * + * Scans over charge_to_l1a and finds bx location of charge pulse. + * Scans over phase_ck and prints values. Optimal phase_ck is when pedestal adc + * is at a maximum. Scans over phase_strobe and prints values. charge_to_l1a + * should be placed at the phase_strobe and bx where adc is at a maximum. + */ +void scan_phase_strobe(Target* tgt, pflib::ROC& roc, int i_roc, + DecodeAndBuffer& buffer, int nevents); +void scan_phase_ck(Target* tgt, DecodeAndBuffer& buffer, int nevents); +int peak_bx(Target* tgt, pflib::ROC& roc, int i_roc, DecodeAndBuffer& buffer, + int nevents); +void examine_phase(Target* tgt); diff --git a/app/tool/tasks/global_pedestal_level.cxx b/app/tool/tasks/global_pedestal_level.cxx index d411fff8a..8e1440678 100644 --- a/app/tool/tasks/global_pedestal_level.cxx +++ b/app/tool/tasks/global_pedestal_level.cxx @@ -22,7 +22,7 @@ void global_pedestal_level(Target* tgt) { } out << YAML::EndMap; - if (pftool::readline_bool("View deduced settings? ", true)) { + if (pftool::readline_bool("View deduced settings? ", false)) { std::cout << out.c_str() << std::endl; } diff --git a/app/tool/tasks/tasks.cxx b/app/tool/tasks/tasks.cxx index 4c6ce8034..84363ce97 100644 --- a/app/tool/tasks/tasks.cxx +++ b/app/tool/tasks/tasks.cxx @@ -7,6 +7,7 @@ #include "../pftool.h" #include "channel_wise_calib_scan.h" #include "charge_timescan.h" +#include "examine_phase.h" #include "expert/scan_orbit.h" #include "gen_scan.h" #include "get_lpgbt_temps.h" @@ -24,7 +25,7 @@ #include "setup/check_lpgbt_backend.h" #include "toa_scan.h" #include "toa_vref_scan.h" -#include "tot_vref_scan.h" +#include "tot_scan.h" #include "trim_inv_dacb_scan.h" #include "trim_toa_scan.h" #include "vref_2d_scan.h" @@ -54,6 +55,7 @@ auto menu_tasks = vref_2d_scan) ->line("NOINV_VREF_SCAN", "scan over NOINV_VREF parameter", noinv_vref_scan) + ->line("EXAMINE_PHASE", "scan over phase parameters", examine_phase) ->line("SAMPLING_PHASE_SCAN", "scan phase_ck, pedestal for clock phase alignment", sampling_phase_scan) @@ -69,14 +71,13 @@ auto menu_tasks = local_pedestal_level) ->line("TOA_VREF_SCAN", "scan over VREF parameters for TOA calibration", toa_vref_scan) - ->line("TOA_SCAN", - "just does that bro (changes CALIB while saving only TOA)", - toa_scan) ->line("TOT_SCAN", "scan over VREF and TRIM parameters for TOT calibration", - tot_vref_scan) + tot_scan) ->line("TRIM_TOA_SCAN", - "calibrate TRIM_TOA parameters for each channel", trim_toa_scan); + "calibrate TRIM_TOA parameters for each channel", trim_toa_scan) + ->line("TOA_SCAN", "calibrate TRIM_TOA parameters for each channel", + toa_scan); auto menu_expert_tasks = menu_tasks->submenu("EXPERT", "low-level but complicated tasks") diff --git a/app/tool/tasks/toa_scan.cxx b/app/tool/tasks/toa_scan.cxx index 3bee476ef..25d18ab20 100644 --- a/app/tool/tasks/toa_scan.cxx +++ b/app/tool/tasks/toa_scan.cxx @@ -1,65 +1,44 @@ #include "toa_scan.h" -#include +#include -#include "../daq_run.h" +#include -ENABLE_LOGGING(); +#include "../algorithm/toa_scan.h" void toa_scan(Target* tgt) { - int nevents = pftool::readline_int("Number of events per point: ", 100); - - std::string output_filepath = pftool::readline_path("toa_scan", ".csv"); - - auto roc = tgt->roc(pftool::state.iroc); - int calib = 0; - int n_links = 2 * tgt->nrocs(); - DecodeAndWriteToCSV writer{ - output_filepath, - [&](std::ofstream& f) { - nlohmann::json header; - header["scan_type"] = "CH_#.TOA sweep"; - header["trigger"] = "CHARGE"; - header["nevents_per_point"] = nevents; - f << "# " << header << "\n" - << "CALIB"; - for (int ch{0}; ch < 72; ch++) { - f << "," << ch; - } - f << "\n"; - }, - [&](std::ofstream& f, - const pflib::packing::MultiSampleECONDEventPacket& ep) { - f << calib; - // Write the TOA values for each channel - for (int ch{0}; ch < 72; ch++) { - // TODO 348 - f << "," << ep.soi().channel(ch / 36, ch % 36).toa(); - } - f << "\n"; - }, - n_links}; - - tgt->setup_run(1, Target::DaqFormat::ECOND_SW_HEADERS, 1); - - // Take a charge injection run. - auto setup_builder = roc.testParameters() - .add("REFERENCEVOLTAGE_0", "CALIB", calib) - .add("REFERENCEVOLTAGE_1", "CALIB", calib) - .add("REFERENCEVOLTAGE_0", "INTCTEST", 1) - .add("REFERENCEVOLTAGE_1", "INTCTEST", 1); - for (int ch{0}; ch < 72; ch++) { - setup_builder.add("CH_" + std::to_string(ch), "LOWRANGE", 1); - } - auto setup_test = setup_builder.apply(); - - for (calib = 0; calib < 800; calib += 4) { - pflib_log(info) << "Running CALIB = " << calib; - // Set the CALIB parameters for both halves - auto calib_test = roc.testParameters() - .add("REFERENCEVOLTAGE_0", "CALIB", calib) - .add("REFERENCEVOLTAGE_1", "CALIB", calib) - .apply(); - daq_run(tgt, "CHARGE", writer, nevents, pftool::state.daq_rate); + auto settings = pflib::algorithm::toa_scan(tgt); + for (const auto& [i_roc, parameters] : settings) { + auto roc{tgt->roc(i_roc)}; + YAML::Emitter out; + out << YAML::BeginMap; + for (const auto& page : parameters) { + out << YAML::Key << page.first; + out << YAML::Value << YAML::BeginMap; + for (const auto& param : page.second) { + out << YAML::Key << param.first << YAML::Value << param.second; + } + out << YAML::EndMap; + } + out << YAML::EndMap; + + if (pftool::readline_bool("View deduced settings? ", false)) { + std::cout << out.c_str() << std::endl; + } + + if (pftool::readline_bool("Apply settings to the chip? ", true)) { + roc.applyParameters(parameters); + } + + if (pftool::readline_bool("Save settings to a file? ", false)) { + std::string fname = pftool::readline_path( + "toa_scan-roc-" + std::to_string(i_roc) + "-settings", ".yaml"); + + std::ofstream f{fname}; + if (not f.is_open()) { + PFEXCEPTION_RAISE("File", "Unable to open file " + fname + "."); + } + f << out.c_str() << std::endl; + } } } diff --git a/app/tool/tasks/toa_scan.h b/app/tool/tasks/toa_scan.h index 48d1b5f9b..44bd20896 100644 --- a/app/tool/tasks/toa_scan.h +++ b/app/tool/tasks/toa_scan.h @@ -1,11 +1,12 @@ #pragma once - #include "../pftool.h" /** * TASKS.TOA_SCAN * - * Just a simple scan that measures toa FOR a range of CALIB. Use to look - * at results of the TRIM_TOA_SCAN and get_trim_toa.py files + * Scan TOA_VREF for all links + * Scan TRIM_TOA for all channels + * + * */ void toa_scan(Target* tgt); diff --git a/app/tool/tasks/tot_scan.cxx b/app/tool/tasks/tot_scan.cxx new file mode 100644 index 000000000..4bc9530cf --- /dev/null +++ b/app/tool/tasks/tot_scan.cxx @@ -0,0 +1,45 @@ +#include "tot_scan.h" + +#include + +#include + +#include "../algorithm/tot_scan.h" + +void tot_scan(Target* tgt) { + auto settings = pflib::algorithm::tot_scan(tgt); + for (const auto& [i_roc, parameters] : settings) { + auto roc{tgt->roc(i_roc)}; + YAML::Emitter out; + out << YAML::BeginMap; + for (const auto& page : parameters) { + out << YAML::Key << page.first; + out << YAML::Value << YAML::BeginMap; + for (const auto& param : page.second) { + out << YAML::Key << param.first << YAML::Value << param.second; + } + out << YAML::EndMap; + } + out << YAML::EndMap; + + if (pftool::readline_bool("View deduced settings? ", false)) { + std::cout << out.c_str() << std::endl; + } + + if (pftool::readline_bool("Apply settings to the chip? ", true)) { + roc.applyParameters(parameters); + } + + if (pftool::readline_bool("Save settings to a file? ", false)) { + std::string fname = pftool::readline_path( + "global_pedestal_level-roc-" + std::to_string(i_roc) + "-settings", + ".yaml"); + + std::ofstream f{fname}; + if (not f.is_open()) { + PFEXCEPTION_RAISE("File", "Unable to open file " + fname + "."); + } + f << out.c_str() << std::endl; + } + } +} diff --git a/app/tool/tasks/tot_vref_scan.h b/app/tool/tasks/tot_scan.h similarity index 70% rename from app/tool/tasks/tot_vref_scan.h rename to app/tool/tasks/tot_scan.h index 9ea337a04..ca107212f 100644 --- a/app/tool/tasks/tot_vref_scan.h +++ b/app/tool/tasks/tot_scan.h @@ -2,11 +2,11 @@ #include "../pftool.h" /** - * TASKS.TOT_VREF_SCAN + * TASKS.TOT_SCAN * * Scan TOT_VREF for both halves of the chip * Scan TRIM_TOT for all channels * * */ -void tot_vref_scan(Target* tgt); +void tot_scan(Target* tgt); diff --git a/app/tool/tasks/tot_vref_scan.cxx b/app/tool/tasks/tot_vref_scan.cxx deleted file mode 100644 index b72cc1e8a..000000000 --- a/app/tool/tasks/tot_vref_scan.cxx +++ /dev/null @@ -1,45 +0,0 @@ -#include "tot_vref_scan.h" - -#include - -#include - -#include "../algorithm/tot_vref_scan.h" - -void tot_vref_scan(Target* tgt) { - auto roc{tgt->roc(pftool::state.iroc)}; - size_t n_events_calib = pftool::readline_int( - "How many events per time point for finding the target calibs?", 100); - auto settings = pflib::algorithm::tot_vref_scan(tgt, roc, n_events_calib); - YAML::Emitter out; - out << YAML::BeginMap; - for (const auto& page : settings) { - out << YAML::Key << page.first; - out << YAML::Value << YAML::BeginMap; - for (const auto& param : page.second) { - out << YAML::Key << param.first << YAML::Value << param.second; - } - out << YAML::EndMap; - } - out << YAML::EndMap; - - if (pftool::readline_bool("View deduced settings? ", true)) { - std::cout << out.c_str() << std::endl; - } - - if (pftool::readline_bool("Apply settings to the chip? ", true)) { - roc.applyParameters(settings); - } - - if (pftool::readline_bool("Save settings to a file? ", false)) { - std::string fname = pftool::readline_path( - "tot-vref-scan-" + std::to_string(pftool::state.iroc) + "-settings", - ".yaml"); - - std::ofstream f{fname}; - if (not f.is_open()) { - PFEXCEPTION_RAISE("File", "Unable to open file " + fname + "."); - } - f << out.c_str() << std::endl; - } -}