diff --git a/.gitignore b/.gitignore index 6fc74fb..01223ec 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,12 @@ *.cpp.b *.so *_C.d - +build +*.swp +*.bins +*.idxf +*.modf +*.rawf +*.trim +*.root +*.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 726b759..5a2d802 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,11 @@ configure_file("src/petsys_util/acquire_qdc_calibration_fixed" "acquire_qdc_cali configure_file("src/petsys_util/acquire_sipm_data" "acquire_sipm_data" COPYONLY) configure_file("src/petsys_util/acquire_sipm_data_basic" "acquire_sipm_data_basic" COPYONLY) configure_file("src/petsys_util/acquire_sipm_data_scan" "acquire_sipm_data_scan" COPYONLY) +configure_file("src/petsys_util/acquire_sipm_IV_scan" "acquire_sipm_IV_scan" COPYONLY) +configure_file("src/petsys_util/acquire_sipm_stressTest" "acquire_sipm_stressTest" COPYONLY) +configure_file("src/petsys_util/scan_aldo_hv" "scan_aldo_hv" COPYONLY) configure_file("src/petsys_util/convert.py" "convert.py" COPYONLY) +configure_file("src/petsys_util/create_ALDO_calibration_combined.py" "create_ALDO_calibration_combined.py" COPYONLY) configure_file("src/petsys_util/make_bias_calibration_table" "make_bias_calibration_table" COPYONLY) configure_file("src/petsys_util/make_simple_bias_settings_table" "make_simple_bias_settings_table" COPYONLY) configure_file("src/petsys_util/make_simple_channel_map" "make_simple_channel_map" COPYONLY) diff --git a/README b/README new file mode 100644 index 0000000..3a4fd93 --- /dev/null +++ b/README @@ -0,0 +1,128 @@ +TOFHIR2 Data Taking Instructions +================================ + +This repository contains code to calibrate and take data from TOFHIR2 chips. +This README has instructions for how to install, calibrate, and take data. + +Installation +------------ + + $ cd + $ mkdir tofhir + $ git clone https://github.com/Lab5015/sw_daq_tofhir2.git + $ git clone https://github.com/Lab5015/Lab5015Utils.git + $ sudo pip install minimalmodbus==1.0.1 + $ sudo pip install simple-pid + $ git clone https://github.com/Lab5015/Lab5015Analysis.git + $ cd sw_daq_tofhir2 + $ mkdir build + $ cd build + $ cmake .. + $ make -j4 + +Running +------- + +First, we need to start the daq daemon. Make sure you have all the correct +power to the FEB/D. + + $ cd ~/tofhir/sw_daq_tofhir2/build + $ rm /tmp/d.sock + $ rm /dev/shm/daqd_shm + $ ./daqd --socket-name /tmp/d.sock --daq-type GBE + +You should see the following output + + Size of frame is 16384 + Got FPGA reply + FrameServer::startWorker called... + FrameServer::startWorker exiting... + UDPFrameServer::runWorker starting... + +This command will continue running the whole time you are communicating with +the FEB/D and/or TOFHIR. So now you should open a new terminal. Now, we can try +to initialize the system: + + $ cd ~/tofhir/sw_daq_tofhir2/build + $ python set_system_mode.py --mode tofhir2x + +or, if you are running with a TOFHIR2B: + + $ python set_system_mode.py --mode tofhir2b + +Now, we can initialize the system: + + $ ./init_system + +With one active ASIC connected, you should see the following: + + INFO: active units on ports: 0 + INFO: TGR unit is ( 0, 0) + INFO: FEB/D ( 0, 0) has 1 active ASICs: 0 + +Now, we start the QDC, TDC, and threshold calibrations: + + $ cd ~/tofhir/sw_daq_tofhir2/build + $ ./make_bias_calibration_table -o ../config/bias_calibration.tsv + $ ./make_simple_bias_settings_table --config ../config/config.ini --offset 0.0 --prebd 30 --bd 38.5 --over 3.5 -o ../config/bias_settings.tsv + $ sh ../configuration.template.sh ../config + +You should now see the following calibration files in the config directory: + + bias_calibration.tsv qdc_calibration.idxf + bias_settings.tsv qdc_calibration.modf + config.ini qdc_calibration.rawf + disc_calibration_00_00_00.pdf qdc_calibration.trim + disc_calibration_baseline.tsv qdc_calibration.tsv + disc_calibration_dark.tsv tdc_calibration_00_00_00.pdf + disc_calibration_noise.tsv tdc_calibration_00_00_00.png + disc_calibration.root tdc_calibration_00_00_00.root + disc_calibration.tsv tdc_calibration.bins + disc_settings.tsv tdc_calibration.idxf + qdc_calibration_00_00_00.pdf tdc_calibration.modf + qdc_calibration_00_00_00.png tdc_calibration.rawf + qdc_calibration_00_00_00.root tdc_calibration.tsv + qdc_calibration.bins + +Next we do the ALDO calibrations. Run the following commands and physically +connect the mutlimeter to the outputs of ALDO A and B as directed by the +terminal output. Note that the IP address will depend on your specific setup; +you can find it on a Keithley 2450 under MENU:Communication:IP Adress + + $ cd ~/tofhir/sw_daq_tofhir2/build + $ ./scan_aldo_hv --config ../config/config.ini -o aldo_scan --keithley-model 2450 --keithley-ip-address 10.168.233.197 + $ ./create_ALDO_calibration_combined.py aldo_scan_ASIC*tsv --dest-dir ../config + +scan_aldo_hv creates two tsv files for each ALDO in the current directory, and +create_ALDO_calibration_combined combines tsv files to include all active ASICs +and place the resulting files in dest-dir. + +Next we apply a constant bias to the SiPMs and observe the current. If you are +injecting light with a laser, this can be used to estimate the number of pe. +Connect the multimeter to measure voltage across the SiPM current measurement +resistors for ALDO A and B in turn. + + $ ./acquire_sipm_stressTest --config ../config/config.ini --bv 42 --ch 0 --time 10 --label test --asic 0 --aldoA --keithley-model 2450 --verbose + $ ./acquire_sipm_stressTest --config ../config/config.ini --bv 42 --ch 0 --time 10 --label test --asic 0 --aldoB --keithley-model 2450 --verbose + +To run an IV scan to determine the breakdown voltage of the SiPMs you can run +the following commands. You will need to connect the multimeter to read across +the SiPM current measurement resistors as before, and you may need to expose +the SiPMs to light to get enough current: + + $ ./acquire_sipm_IV_scan --config ../config/config.ini --aldo A --keithley-model 2450 --verbose --bvMin 36 --bvMax 39 + $ ./acquire_sipm_IV_scan --config ../config/config.ini --aldo B --keithley-model 2450 --verbose --bvMin 36 --bvMax 39 + +Based on the observed breakdown voltage, you can update ~/tofhir/sw_daq_tofhir2/config/bias_settings_aldo.tsv. + +We are now ready to take data. The following command will acquire data for one +second at OV=3.5V while self-triggering on ith1: + + $ python acquire_sipm_data_scan --config ../config/config.ini --time 1 --ith1 10 --ith2 1 --ithe 1 --ov 3.5 --trigger none --aldo --data-dir ../../data + +The data will be stored in the specified data directory, and the run number +will be incremented automatically. You can then convert the data into a ttree +with the following command. Note that the run number and data directory should +be updated as needed. + + $ python convert.py --config ../config/config.ini -r run0001 --mode e --data-dir ../../data/ diff --git a/README.md b/README.md new file mode 120000 index 0000000..100b938 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +README \ No newline at end of file diff --git a/config.ini b/config.ini deleted file mode 100644 index 1bc4ac4..0000000 --- a/config.ini +++ /dev/null @@ -1,27 +0,0 @@ -[main] -bias_calibration_table = %CDIR%/bias_calibration.tsv -bias_settings_table = %CDIR%/bias_settings.tsv - -tdc_calibration_table = %CDIR%/tdc_calibration.tsv -qdc_calibration_table = %CDIR%/qdc_calibration.tsv -disc_calibration_table = %CDIR%/disc_calibration.tsv - -acquisition_mode_table = %CDIR%/acquisition_mode_settings.tsv -#energy_calibration_table = %CDIR%/energy_calibration.tsv -disc_settings_table = %CDIR%/disc_settings.tsv - -channel_map = %CDIR%/map_channel.tsv -trigger_map = %CDIR%/map_trigger.tsv - -[hw_trigger] -type = builtin -threshold = 1 -pre_window = 3 -post_window = 15 -coincidence_window = 3 -single_fraction = 0 - -[asic_parameters] - - - diff --git a/config/bias_settings_aldo.tsv b/config/bias_settings_aldo.tsv new file mode 100644 index 0000000..e7b217c --- /dev/null +++ b/config/bias_settings_aldo.tsv @@ -0,0 +1,5 @@ +#portID slaveID chipID aldo Breakdown Overvoltage +0 0 0 A 38.50 3.50 +0 0 0 B 38.50 3.50 +0 0 2 A 38.50 3.50 +0 0 2 B 38.50 3.50 diff --git a/config/config.ini b/config/config.ini new file mode 100644 index 0000000..8f73432 --- /dev/null +++ b/config/config.ini @@ -0,0 +1,59 @@ +[main] +bias_calibration_table = %CDIR%/bias_calibration.tsv +bias_settings_table = %CDIR%/bias_settings.tsv +bias_settings_table_aldo = %CDIR%/bias_settings_aldo.tsv + +tdc_calibration_table = %CDIR%/tdc_calibration.tsv +qdc_calibration_table = %CDIR%/qdc_calibration.tsv +disc_calibration_table = %CDIR%/disc_calibration.tsv + +acquisition_mode_table = %CDIR%/acquisition_mode_settings.tsv +#energy_calibration_table = %CDIR%/energy_calibration.tsv +disc_settings_table = %CDIR%/disc_settings.tsv + +channel_map = %CDIR%/map_channel.tsv +trigger_map = %CDIR%/map_trigger.tsv + +aldo_A_calibration = %CDIR%/aldo_scan_ALDO_A_high.tsv +aldo_B_calibration = %CDIR%/aldo_scan_ALDO_B_high.tsv + +[hw_trigger] +type = builtin +threshold = 1 +pre_window = 3 +post_window = 15 +coincidence_window = 3 +single_fraction = 0 + +[sw_trigger] +coincidence_time_window = 20 +group_time_window = 20 + +[asic_parameters] +global.Valdo_A_Gain = 1 +global.Valdo_B_Gain = 1 + +channel.cfg_a2_dcr_delay_t = 0b01111111 +channel.cfg_a2_dcr_delay_e = 0b1111111 + +channel.cfg_a2_pulse_trim_t = 15 +channel.cfg_a2_pulse_trim_e = 19 + +channel.cfg_a2_attenuator_gain = 0 + +channel.c_max_v_en = 0 +channel.c_min_q = 5 +channel.c_max_q = 5 + +# using t1 for timing +channel.cfg_a3_range_t1 = 1 +channel.cfg_a3_range_t2 = 3 +channel.c_tgr_t1 = 0b00 +channel.c_tgr_q = 0b00 +channel.c_tgr_t2 = 0b00 +channel.c_tgr_V = 0b00 +channel.c_tgr_B = 0b000 + +# pre-amp scaling; uncomment when running with TOFHIR2B +#channel.cfg_a1_scaling = 1 + diff --git a/config/map_channel.tsv b/config/map_channel.tsv new file mode 100644 index 0000000..d7e37db --- /dev/null +++ b/config/map_channel.tsv @@ -0,0 +1,512 @@ +0 0 0 0 0 0 0 0.0 0.0 0.0 +0 0 0 1 0 0 0 0.0 0.0 0.0 +0 0 0 2 0 0 0 0.0 0.0 0.0 +0 0 0 3 0 0 0 0.0 0.0 0.0 +0 0 0 4 0 0 0 0.0 0.0 0.0 +0 0 0 5 0 0 0 0.0 0.0 0.0 +0 0 0 6 0 0 0 0.0 0.0 0.0 +0 0 0 7 0 0 0 0.0 0.0 0.0 +0 0 0 8 0 0 0 0.0 0.0 0.0 +0 0 0 9 0 0 0 0.0 0.0 0.0 +0 0 0 10 0 0 0 0.0 0.0 0.0 +0 0 0 11 0 0 0 0.0 0.0 0.0 +0 0 0 12 0 0 0 0.0 0.0 0.0 +0 0 0 13 0 0 0 0.0 0.0 0.0 +0 0 0 14 0 0 0 0.0 0.0 0.0 +0 0 0 15 0 0 0 0.0 0.0 0.0 +0 0 0 16 0 0 0 0.0 0.0 0.0 +0 0 0 17 0 0 0 0.0 0.0 0.0 +0 0 0 18 0 0 0 0.0 0.0 0.0 +0 0 0 19 0 0 0 0.0 0.0 0.0 +0 0 0 20 0 0 0 0.0 0.0 0.0 +0 0 0 21 0 0 0 0.0 0.0 0.0 +0 0 0 22 0 0 0 0.0 0.0 0.0 +0 0 0 23 0 0 0 0.0 0.0 0.0 +0 0 0 24 0 0 0 0.0 0.0 0.0 +0 0 0 25 0 0 0 0.0 0.0 0.0 +0 0 0 26 0 0 0 0.0 0.0 0.0 +0 0 0 27 0 0 0 0.0 0.0 0.0 +0 0 0 28 0 0 0 0.0 0.0 0.0 +0 0 0 29 0 0 0 0.0 0.0 0.0 +0 0 0 30 0 0 0 0.0 0.0 0.0 +0 0 0 31 0 0 0 0.0 0.0 0.0 +0 0 1 0 0 0 0 0.0 0.0 0.0 +0 0 1 1 0 0 0 0.0 0.0 0.0 +0 0 1 2 0 0 0 0.0 0.0 0.0 +0 0 1 3 0 0 0 0.0 0.0 0.0 +0 0 1 4 0 0 0 0.0 0.0 0.0 +0 0 1 5 0 0 0 0.0 0.0 0.0 +0 0 1 6 0 0 0 0.0 0.0 0.0 +0 0 1 7 0 0 0 0.0 0.0 0.0 +0 0 1 8 0 0 0 0.0 0.0 0.0 +0 0 1 9 0 0 0 0.0 0.0 0.0 +0 0 1 10 0 0 0 0.0 0.0 0.0 +0 0 1 11 0 0 0 0.0 0.0 0.0 +0 0 1 12 0 0 0 0.0 0.0 0.0 +0 0 1 13 0 0 0 0.0 0.0 0.0 +0 0 1 14 0 0 0 0.0 0.0 0.0 +0 0 1 15 0 0 0 0.0 0.0 0.0 +0 0 1 16 0 0 0 0.0 0.0 0.0 +0 0 1 17 0 0 0 0.0 0.0 0.0 +0 0 1 18 0 0 0 0.0 0.0 0.0 +0 0 1 19 0 0 0 0.0 0.0 0.0 +0 0 1 20 0 0 0 0.0 0.0 0.0 +0 0 1 21 0 0 0 0.0 0.0 0.0 +0 0 1 22 0 0 0 0.0 0.0 0.0 +0 0 1 23 0 0 0 0.0 0.0 0.0 +0 0 1 24 0 0 0 0.0 0.0 0.0 +0 0 1 25 0 0 0 0.0 0.0 0.0 +0 0 1 26 0 0 0 0.0 0.0 0.0 +0 0 1 27 0 0 0 0.0 0.0 0.0 +0 0 1 28 0 0 0 0.0 0.0 0.0 +0 0 1 29 0 0 0 0.0 0.0 0.0 +0 0 1 30 0 0 0 0.0 0.0 0.0 +0 0 1 31 0 0 0 0.0 0.0 0.0 +0 0 2 0 0 0 0 0.0 0.0 0.0 +0 0 2 1 0 0 0 0.0 0.0 0.0 +0 0 2 2 0 0 0 0.0 0.0 0.0 +0 0 2 3 0 0 0 0.0 0.0 0.0 +0 0 2 4 0 0 0 0.0 0.0 0.0 +0 0 2 5 0 0 0 0.0 0.0 0.0 +0 0 2 6 0 0 0 0.0 0.0 0.0 +0 0 2 7 0 0 0 0.0 0.0 0.0 +0 0 2 8 0 0 0 0.0 0.0 0.0 +0 0 2 9 0 0 0 0.0 0.0 0.0 +0 0 2 10 0 0 0 0.0 0.0 0.0 +0 0 2 11 0 0 0 0.0 0.0 0.0 +0 0 2 12 0 0 0 0.0 0.0 0.0 +0 0 2 13 0 0 0 0.0 0.0 0.0 +0 0 2 14 0 0 0 0.0 0.0 0.0 +0 0 2 15 0 0 0 0.0 0.0 0.0 +0 0 2 16 0 0 0 0.0 0.0 0.0 +0 0 2 17 0 0 0 0.0 0.0 0.0 +0 0 2 18 0 0 0 0.0 0.0 0.0 +0 0 2 19 0 0 0 0.0 0.0 0.0 +0 0 2 20 0 0 0 0.0 0.0 0.0 +0 0 2 21 0 0 0 0.0 0.0 0.0 +0 0 2 22 0 0 0 0.0 0.0 0.0 +0 0 2 23 0 0 0 0.0 0.0 0.0 +0 0 2 24 0 0 0 0.0 0.0 0.0 +0 0 2 25 0 0 0 0.0 0.0 0.0 +0 0 2 26 0 0 0 0.0 0.0 0.0 +0 0 2 27 0 0 0 0.0 0.0 0.0 +0 0 2 28 0 0 0 0.0 0.0 0.0 +0 0 2 29 0 0 0 0.0 0.0 0.0 +0 0 2 30 0 0 0 0.0 0.0 0.0 +0 0 2 31 0 0 0 0.0 0.0 0.0 +0 0 3 0 0 0 0 0.0 0.0 0.0 +0 0 3 1 0 0 0 0.0 0.0 0.0 +0 0 3 2 0 0 0 0.0 0.0 0.0 +0 0 3 3 0 0 0 0.0 0.0 0.0 +0 0 3 4 0 0 0 0.0 0.0 0.0 +0 0 3 5 0 0 0 0.0 0.0 0.0 +0 0 3 6 0 0 0 0.0 0.0 0.0 +0 0 3 7 0 0 0 0.0 0.0 0.0 +0 0 3 8 0 0 0 0.0 0.0 0.0 +0 0 3 9 0 0 0 0.0 0.0 0.0 +0 0 3 10 0 0 0 0.0 0.0 0.0 +0 0 3 11 0 0 0 0.0 0.0 0.0 +0 0 3 12 0 0 0 0.0 0.0 0.0 +0 0 3 13 0 0 0 0.0 0.0 0.0 +0 0 3 14 0 0 0 0.0 0.0 0.0 +0 0 3 15 0 0 0 0.0 0.0 0.0 +0 0 3 16 0 0 0 0.0 0.0 0.0 +0 0 3 17 0 0 0 0.0 0.0 0.0 +0 0 3 18 0 0 0 0.0 0.0 0.0 +0 0 3 19 0 0 0 0.0 0.0 0.0 +0 0 3 20 0 0 0 0.0 0.0 0.0 +0 0 3 21 0 0 0 0.0 0.0 0.0 +0 0 3 22 0 0 0 0.0 0.0 0.0 +0 0 3 23 0 0 0 0.0 0.0 0.0 +0 0 3 24 0 0 0 0.0 0.0 0.0 +0 0 3 25 0 0 0 0.0 0.0 0.0 +0 0 3 26 0 0 0 0.0 0.0 0.0 +0 0 3 27 0 0 0 0.0 0.0 0.0 +0 0 3 28 0 0 0 0.0 0.0 0.0 +0 0 3 29 0 0 0 0.0 0.0 0.0 +0 0 3 30 0 0 0 0.0 0.0 0.0 +0 0 3 31 0 0 0 0.0 0.0 0.0 +0 0 4 0 1 0 0 0.0 0.0 0.0 +0 0 4 1 1 0 0 0.0 0.0 0.0 +0 0 4 2 1 0 0 0.0 0.0 0.0 +0 0 4 3 1 0 0 0.0 0.0 0.0 +0 0 4 4 1 0 0 0.0 0.0 0.0 +0 0 4 5 1 0 0 0.0 0.0 0.0 +0 0 4 6 1 0 0 0.0 0.0 0.0 +0 0 4 7 1 0 0 0.0 0.0 0.0 +0 0 4 8 1 0 0 0.0 0.0 0.0 +0 0 4 9 1 0 0 0.0 0.0 0.0 +0 0 4 10 1 0 0 0.0 0.0 0.0 +0 0 4 11 1 0 0 0.0 0.0 0.0 +0 0 4 12 1 0 0 0.0 0.0 0.0 +0 0 4 13 1 0 0 0.0 0.0 0.0 +0 0 4 14 1 0 0 0.0 0.0 0.0 +0 0 4 15 1 0 0 0.0 0.0 0.0 +0 0 4 16 1 0 0 0.0 0.0 0.0 +0 0 4 17 1 0 0 0.0 0.0 0.0 +0 0 4 18 1 0 0 0.0 0.0 0.0 +0 0 4 19 1 0 0 0.0 0.0 0.0 +0 0 4 20 1 0 0 0.0 0.0 0.0 +0 0 4 21 1 0 0 0.0 0.0 0.0 +0 0 4 22 1 0 0 0.0 0.0 0.0 +0 0 4 23 1 0 0 0.0 0.0 0.0 +0 0 4 24 1 0 0 0.0 0.0 0.0 +0 0 4 25 1 0 0 0.0 0.0 0.0 +0 0 4 26 1 0 0 0.0 0.0 0.0 +0 0 4 27 1 0 0 0.0 0.0 0.0 +0 0 4 28 1 0 0 0.0 0.0 0.0 +0 0 4 29 1 0 0 0.0 0.0 0.0 +0 0 4 30 1 0 0 0.0 0.0 0.0 +0 0 4 31 1 0 0 0.0 0.0 0.0 +0 0 5 0 1 0 0 0.0 0.0 0.0 +0 0 5 1 1 0 0 0.0 0.0 0.0 +0 0 5 2 1 0 0 0.0 0.0 0.0 +0 0 5 3 1 0 0 0.0 0.0 0.0 +0 0 5 4 1 0 0 0.0 0.0 0.0 +0 0 5 5 1 0 0 0.0 0.0 0.0 +0 0 5 6 1 0 0 0.0 0.0 0.0 +0 0 5 7 1 0 0 0.0 0.0 0.0 +0 0 5 8 1 0 0 0.0 0.0 0.0 +0 0 5 9 1 0 0 0.0 0.0 0.0 +0 0 5 10 1 0 0 0.0 0.0 0.0 +0 0 5 11 1 0 0 0.0 0.0 0.0 +0 0 5 12 1 0 0 0.0 0.0 0.0 +0 0 5 13 1 0 0 0.0 0.0 0.0 +0 0 5 14 1 0 0 0.0 0.0 0.0 +0 0 5 15 1 0 0 0.0 0.0 0.0 +0 0 5 16 1 0 0 0.0 0.0 0.0 +0 0 5 17 1 0 0 0.0 0.0 0.0 +0 0 5 18 1 0 0 0.0 0.0 0.0 +0 0 5 19 1 0 0 0.0 0.0 0.0 +0 0 5 20 1 0 0 0.0 0.0 0.0 +0 0 5 21 1 0 0 0.0 0.0 0.0 +0 0 5 22 1 0 0 0.0 0.0 0.0 +0 0 5 23 1 0 0 0.0 0.0 0.0 +0 0 5 24 1 0 0 0.0 0.0 0.0 +0 0 5 25 1 0 0 0.0 0.0 0.0 +0 0 5 26 1 0 0 0.0 0.0 0.0 +0 0 5 27 1 0 0 0.0 0.0 0.0 +0 0 5 28 1 0 0 0.0 0.0 0.0 +0 0 5 29 1 0 0 0.0 0.0 0.0 +0 0 5 30 1 0 0 0.0 0.0 0.0 +0 0 5 31 1 0 0 0.0 0.0 0.0 +0 0 6 0 1 0 0 0.0 0.0 0.0 +0 0 6 1 1 0 0 0.0 0.0 0.0 +0 0 6 2 1 0 0 0.0 0.0 0.0 +0 0 6 3 1 0 0 0.0 0.0 0.0 +0 0 6 4 1 0 0 0.0 0.0 0.0 +0 0 6 5 1 0 0 0.0 0.0 0.0 +0 0 6 6 1 0 0 0.0 0.0 0.0 +0 0 6 7 1 0 0 0.0 0.0 0.0 +0 0 6 8 1 0 0 0.0 0.0 0.0 +0 0 6 9 1 0 0 0.0 0.0 0.0 +0 0 6 10 1 0 0 0.0 0.0 0.0 +0 0 6 11 1 0 0 0.0 0.0 0.0 +0 0 6 12 1 0 0 0.0 0.0 0.0 +0 0 6 13 1 0 0 0.0 0.0 0.0 +0 0 6 14 1 0 0 0.0 0.0 0.0 +0 0 6 15 1 0 0 0.0 0.0 0.0 +0 0 6 16 1 0 0 0.0 0.0 0.0 +0 0 6 17 1 0 0 0.0 0.0 0.0 +0 0 6 18 1 0 0 0.0 0.0 0.0 +0 0 6 19 1 0 0 0.0 0.0 0.0 +0 0 6 20 1 0 0 0.0 0.0 0.0 +0 0 6 21 1 0 0 0.0 0.0 0.0 +0 0 6 22 1 0 0 0.0 0.0 0.0 +0 0 6 23 1 0 0 0.0 0.0 0.0 +0 0 6 24 1 0 0 0.0 0.0 0.0 +0 0 6 25 1 0 0 0.0 0.0 0.0 +0 0 6 26 1 0 0 0.0 0.0 0.0 +0 0 6 27 1 0 0 0.0 0.0 0.0 +0 0 6 28 1 0 0 0.0 0.0 0.0 +0 0 6 29 1 0 0 0.0 0.0 0.0 +0 0 6 30 1 0 0 0.0 0.0 0.0 +0 0 6 31 1 0 0 0.0 0.0 0.0 +0 0 7 0 1 0 0 0.0 0.0 0.0 +0 0 7 1 1 0 0 0.0 0.0 0.0 +0 0 7 2 1 0 0 0.0 0.0 0.0 +0 0 7 3 1 0 0 0.0 0.0 0.0 +0 0 7 4 1 0 0 0.0 0.0 0.0 +0 0 7 5 1 0 0 0.0 0.0 0.0 +0 0 7 6 1 0 0 0.0 0.0 0.0 +0 0 7 7 1 0 0 0.0 0.0 0.0 +0 0 7 8 1 0 0 0.0 0.0 0.0 +0 0 7 9 1 0 0 0.0 0.0 0.0 +0 0 7 10 1 0 0 0.0 0.0 0.0 +0 0 7 11 1 0 0 0.0 0.0 0.0 +0 0 7 12 1 0 0 0.0 0.0 0.0 +0 0 7 13 1 0 0 0.0 0.0 0.0 +0 0 7 14 1 0 0 0.0 0.0 0.0 +0 0 7 15 1 0 0 0.0 0.0 0.0 +0 0 7 16 1 0 0 0.0 0.0 0.0 +0 0 7 17 1 0 0 0.0 0.0 0.0 +0 0 7 18 1 0 0 0.0 0.0 0.0 +0 0 7 19 1 0 0 0.0 0.0 0.0 +0 0 7 20 1 0 0 0.0 0.0 0.0 +0 0 7 21 1 0 0 0.0 0.0 0.0 +0 0 7 22 1 0 0 0.0 0.0 0.0 +0 0 7 23 1 0 0 0.0 0.0 0.0 +0 0 7 24 1 0 0 0.0 0.0 0.0 +0 0 7 25 1 0 0 0.0 0.0 0.0 +0 0 7 26 1 0 0 0.0 0.0 0.0 +0 0 7 27 1 0 0 0.0 0.0 0.0 +0 0 7 28 1 0 0 0.0 0.0 0.0 +0 0 7 29 1 0 0 0.0 0.0 0.0 +0 0 7 30 1 0 0 0.0 0.0 0.0 +0 0 7 31 1 0 0 0.0 0.0 0.0 +0 0 8 0 2 0 0 0.0 0.0 0.0 +0 0 8 1 2 0 0 0.0 0.0 0.0 +0 0 8 2 2 0 0 0.0 0.0 0.0 +0 0 8 3 2 0 0 0.0 0.0 0.0 +0 0 8 4 2 0 0 0.0 0.0 0.0 +0 0 8 5 2 0 0 0.0 0.0 0.0 +0 0 8 6 2 0 0 0.0 0.0 0.0 +0 0 8 7 2 0 0 0.0 0.0 0.0 +0 0 8 8 2 0 0 0.0 0.0 0.0 +0 0 8 9 2 0 0 0.0 0.0 0.0 +0 0 8 10 2 0 0 0.0 0.0 0.0 +0 0 8 11 2 0 0 0.0 0.0 0.0 +0 0 8 12 2 0 0 0.0 0.0 0.0 +0 0 8 13 2 0 0 0.0 0.0 0.0 +0 0 8 14 2 0 0 0.0 0.0 0.0 +0 0 8 15 2 0 0 0.0 0.0 0.0 +0 0 8 16 2 0 0 0.0 0.0 0.0 +0 0 8 17 2 0 0 0.0 0.0 0.0 +0 0 8 18 2 0 0 0.0 0.0 0.0 +0 0 8 19 2 0 0 0.0 0.0 0.0 +0 0 8 20 2 0 0 0.0 0.0 0.0 +0 0 8 21 2 0 0 0.0 0.0 0.0 +0 0 8 22 2 0 0 0.0 0.0 0.0 +0 0 8 23 2 0 0 0.0 0.0 0.0 +0 0 8 24 2 0 0 0.0 0.0 0.0 +0 0 8 25 2 0 0 0.0 0.0 0.0 +0 0 8 26 2 0 0 0.0 0.0 0.0 +0 0 8 27 2 0 0 0.0 0.0 0.0 +0 0 8 28 2 0 0 0.0 0.0 0.0 +0 0 8 29 2 0 0 0.0 0.0 0.0 +0 0 8 30 2 0 0 0.0 0.0 0.0 +0 0 8 31 2 0 0 0.0 0.0 0.0 +0 0 9 0 2 0 0 0.0 0.0 0.0 +0 0 9 1 2 0 0 0.0 0.0 0.0 +0 0 9 2 2 0 0 0.0 0.0 0.0 +0 0 9 3 2 0 0 0.0 0.0 0.0 +0 0 9 4 2 0 0 0.0 0.0 0.0 +0 0 9 5 2 0 0 0.0 0.0 0.0 +0 0 9 6 2 0 0 0.0 0.0 0.0 +0 0 9 7 2 0 0 0.0 0.0 0.0 +0 0 9 8 2 0 0 0.0 0.0 0.0 +0 0 9 9 2 0 0 0.0 0.0 0.0 +0 0 9 10 2 0 0 0.0 0.0 0.0 +0 0 9 11 2 0 0 0.0 0.0 0.0 +0 0 9 12 2 0 0 0.0 0.0 0.0 +0 0 9 13 2 0 0 0.0 0.0 0.0 +0 0 9 14 2 0 0 0.0 0.0 0.0 +0 0 9 15 2 0 0 0.0 0.0 0.0 +0 0 9 16 2 0 0 0.0 0.0 0.0 +0 0 9 17 2 0 0 0.0 0.0 0.0 +0 0 9 18 2 0 0 0.0 0.0 0.0 +0 0 9 19 2 0 0 0.0 0.0 0.0 +0 0 9 20 2 0 0 0.0 0.0 0.0 +0 0 9 21 2 0 0 0.0 0.0 0.0 +0 0 9 22 2 0 0 0.0 0.0 0.0 +0 0 9 23 2 0 0 0.0 0.0 0.0 +0 0 9 24 2 0 0 0.0 0.0 0.0 +0 0 9 25 2 0 0 0.0 0.0 0.0 +0 0 9 26 2 0 0 0.0 0.0 0.0 +0 0 9 27 2 0 0 0.0 0.0 0.0 +0 0 9 28 2 0 0 0.0 0.0 0.0 +0 0 9 29 2 0 0 0.0 0.0 0.0 +0 0 9 30 2 0 0 0.0 0.0 0.0 +0 0 9 31 2 0 0 0.0 0.0 0.0 +0 0 10 0 2 0 0 0.0 0.0 0.0 +0 0 10 1 2 0 0 0.0 0.0 0.0 +0 0 10 2 2 0 0 0.0 0.0 0.0 +0 0 10 3 2 0 0 0.0 0.0 0.0 +0 0 10 4 2 0 0 0.0 0.0 0.0 +0 0 10 5 2 0 0 0.0 0.0 0.0 +0 0 10 6 2 0 0 0.0 0.0 0.0 +0 0 10 7 2 0 0 0.0 0.0 0.0 +0 0 10 8 2 0 0 0.0 0.0 0.0 +0 0 10 9 2 0 0 0.0 0.0 0.0 +0 0 10 10 2 0 0 0.0 0.0 0.0 +0 0 10 11 2 0 0 0.0 0.0 0.0 +0 0 10 12 2 0 0 0.0 0.0 0.0 +0 0 10 13 2 0 0 0.0 0.0 0.0 +0 0 10 14 2 0 0 0.0 0.0 0.0 +0 0 10 15 2 0 0 0.0 0.0 0.0 +0 0 10 16 2 0 0 0.0 0.0 0.0 +0 0 10 17 2 0 0 0.0 0.0 0.0 +0 0 10 18 2 0 0 0.0 0.0 0.0 +0 0 10 19 2 0 0 0.0 0.0 0.0 +0 0 10 20 2 0 0 0.0 0.0 0.0 +0 0 10 21 2 0 0 0.0 0.0 0.0 +0 0 10 22 2 0 0 0.0 0.0 0.0 +0 0 10 23 2 0 0 0.0 0.0 0.0 +0 0 10 24 2 0 0 0.0 0.0 0.0 +0 0 10 25 2 0 0 0.0 0.0 0.0 +0 0 10 26 2 0 0 0.0 0.0 0.0 +0 0 10 27 2 0 0 0.0 0.0 0.0 +0 0 10 28 2 0 0 0.0 0.0 0.0 +0 0 10 29 2 0 0 0.0 0.0 0.0 +0 0 10 30 2 0 0 0.0 0.0 0.0 +0 0 10 31 2 0 0 0.0 0.0 0.0 +0 0 11 0 2 0 0 0.0 0.0 0.0 +0 0 11 1 2 0 0 0.0 0.0 0.0 +0 0 11 2 2 0 0 0.0 0.0 0.0 +0 0 11 3 2 0 0 0.0 0.0 0.0 +0 0 11 4 2 0 0 0.0 0.0 0.0 +0 0 11 5 2 0 0 0.0 0.0 0.0 +0 0 11 6 2 0 0 0.0 0.0 0.0 +0 0 11 7 2 0 0 0.0 0.0 0.0 +0 0 11 8 2 0 0 0.0 0.0 0.0 +0 0 11 9 2 0 0 0.0 0.0 0.0 +0 0 11 10 2 0 0 0.0 0.0 0.0 +0 0 11 11 2 0 0 0.0 0.0 0.0 +0 0 11 12 2 0 0 0.0 0.0 0.0 +0 0 11 13 2 0 0 0.0 0.0 0.0 +0 0 11 14 2 0 0 0.0 0.0 0.0 +0 0 11 15 2 0 0 0.0 0.0 0.0 +0 0 11 16 2 0 0 0.0 0.0 0.0 +0 0 11 17 2 0 0 0.0 0.0 0.0 +0 0 11 18 2 0 0 0.0 0.0 0.0 +0 0 11 19 2 0 0 0.0 0.0 0.0 +0 0 11 20 2 0 0 0.0 0.0 0.0 +0 0 11 21 2 0 0 0.0 0.0 0.0 +0 0 11 22 2 0 0 0.0 0.0 0.0 +0 0 11 23 2 0 0 0.0 0.0 0.0 +0 0 11 24 2 0 0 0.0 0.0 0.0 +0 0 11 25 2 0 0 0.0 0.0 0.0 +0 0 11 26 2 0 0 0.0 0.0 0.0 +0 0 11 27 2 0 0 0.0 0.0 0.0 +0 0 11 28 2 0 0 0.0 0.0 0.0 +0 0 11 29 2 0 0 0.0 0.0 0.0 +0 0 11 30 2 0 0 0.0 0.0 0.0 +0 0 11 31 2 0 0 0.0 0.0 0.0 +0 0 12 0 3 0 0 0.0 0.0 0.0 +0 0 12 1 3 0 0 0.0 0.0 0.0 +0 0 12 2 3 0 0 0.0 0.0 0.0 +0 0 12 3 3 0 0 0.0 0.0 0.0 +0 0 12 4 3 0 0 0.0 0.0 0.0 +0 0 12 5 3 0 0 0.0 0.0 0.0 +0 0 12 6 3 0 0 0.0 0.0 0.0 +0 0 12 7 3 0 0 0.0 0.0 0.0 +0 0 12 8 3 0 0 0.0 0.0 0.0 +0 0 12 9 3 0 0 0.0 0.0 0.0 +0 0 12 10 3 0 0 0.0 0.0 0.0 +0 0 12 11 3 0 0 0.0 0.0 0.0 +0 0 12 12 3 0 0 0.0 0.0 0.0 +0 0 12 13 3 0 0 0.0 0.0 0.0 +0 0 12 14 3 0 0 0.0 0.0 0.0 +0 0 12 15 3 0 0 0.0 0.0 0.0 +0 0 12 16 3 0 0 0.0 0.0 0.0 +0 0 12 17 3 0 0 0.0 0.0 0.0 +0 0 12 18 3 0 0 0.0 0.0 0.0 +0 0 12 19 3 0 0 0.0 0.0 0.0 +0 0 12 20 3 0 0 0.0 0.0 0.0 +0 0 12 21 3 0 0 0.0 0.0 0.0 +0 0 12 22 3 0 0 0.0 0.0 0.0 +0 0 12 23 3 0 0 0.0 0.0 0.0 +0 0 12 24 3 0 0 0.0 0.0 0.0 +0 0 12 25 3 0 0 0.0 0.0 0.0 +0 0 12 26 3 0 0 0.0 0.0 0.0 +0 0 12 27 3 0 0 0.0 0.0 0.0 +0 0 12 28 3 0 0 0.0 0.0 0.0 +0 0 12 29 3 0 0 0.0 0.0 0.0 +0 0 12 30 3 0 0 0.0 0.0 0.0 +0 0 12 31 3 0 0 0.0 0.0 0.0 +0 0 13 0 3 0 0 0.0 0.0 0.0 +0 0 13 1 3 0 0 0.0 0.0 0.0 +0 0 13 2 3 0 0 0.0 0.0 0.0 +0 0 13 3 3 0 0 0.0 0.0 0.0 +0 0 13 4 3 0 0 0.0 0.0 0.0 +0 0 13 5 3 0 0 0.0 0.0 0.0 +0 0 13 6 3 0 0 0.0 0.0 0.0 +0 0 13 7 3 0 0 0.0 0.0 0.0 +0 0 13 8 3 0 0 0.0 0.0 0.0 +0 0 13 9 3 0 0 0.0 0.0 0.0 +0 0 13 10 3 0 0 0.0 0.0 0.0 +0 0 13 11 3 0 0 0.0 0.0 0.0 +0 0 13 12 3 0 0 0.0 0.0 0.0 +0 0 13 13 3 0 0 0.0 0.0 0.0 +0 0 13 14 3 0 0 0.0 0.0 0.0 +0 0 13 15 3 0 0 0.0 0.0 0.0 +0 0 13 16 3 0 0 0.0 0.0 0.0 +0 0 13 17 3 0 0 0.0 0.0 0.0 +0 0 13 18 3 0 0 0.0 0.0 0.0 +0 0 13 19 3 0 0 0.0 0.0 0.0 +0 0 13 20 3 0 0 0.0 0.0 0.0 +0 0 13 21 3 0 0 0.0 0.0 0.0 +0 0 13 22 3 0 0 0.0 0.0 0.0 +0 0 13 23 3 0 0 0.0 0.0 0.0 +0 0 13 24 3 0 0 0.0 0.0 0.0 +0 0 13 25 3 0 0 0.0 0.0 0.0 +0 0 13 26 3 0 0 0.0 0.0 0.0 +0 0 13 27 3 0 0 0.0 0.0 0.0 +0 0 13 28 3 0 0 0.0 0.0 0.0 +0 0 13 29 3 0 0 0.0 0.0 0.0 +0 0 13 30 3 0 0 0.0 0.0 0.0 +0 0 13 31 3 0 0 0.0 0.0 0.0 +0 0 14 0 3 0 0 0.0 0.0 0.0 +0 0 14 1 3 0 0 0.0 0.0 0.0 +0 0 14 2 3 0 0 0.0 0.0 0.0 +0 0 14 3 3 0 0 0.0 0.0 0.0 +0 0 14 4 3 0 0 0.0 0.0 0.0 +0 0 14 5 3 0 0 0.0 0.0 0.0 +0 0 14 6 3 0 0 0.0 0.0 0.0 +0 0 14 7 3 0 0 0.0 0.0 0.0 +0 0 14 8 3 0 0 0.0 0.0 0.0 +0 0 14 9 3 0 0 0.0 0.0 0.0 +0 0 14 10 3 0 0 0.0 0.0 0.0 +0 0 14 11 3 0 0 0.0 0.0 0.0 +0 0 14 12 3 0 0 0.0 0.0 0.0 +0 0 14 13 3 0 0 0.0 0.0 0.0 +0 0 14 14 3 0 0 0.0 0.0 0.0 +0 0 14 15 3 0 0 0.0 0.0 0.0 +0 0 14 16 3 0 0 0.0 0.0 0.0 +0 0 14 17 3 0 0 0.0 0.0 0.0 +0 0 14 18 3 0 0 0.0 0.0 0.0 +0 0 14 19 3 0 0 0.0 0.0 0.0 +0 0 14 20 3 0 0 0.0 0.0 0.0 +0 0 14 21 3 0 0 0.0 0.0 0.0 +0 0 14 22 3 0 0 0.0 0.0 0.0 +0 0 14 23 3 0 0 0.0 0.0 0.0 +0 0 14 24 3 0 0 0.0 0.0 0.0 +0 0 14 25 3 0 0 0.0 0.0 0.0 +0 0 14 26 3 0 0 0.0 0.0 0.0 +0 0 14 27 3 0 0 0.0 0.0 0.0 +0 0 14 28 3 0 0 0.0 0.0 0.0 +0 0 14 29 3 0 0 0.0 0.0 0.0 +0 0 14 30 3 0 0 0.0 0.0 0.0 +0 0 14 31 3 0 0 0.0 0.0 0.0 +0 0 15 0 3 0 0 0.0 0.0 0.0 +0 0 15 1 3 0 0 0.0 0.0 0.0 +0 0 15 2 3 0 0 0.0 0.0 0.0 +0 0 15 3 3 0 0 0.0 0.0 0.0 +0 0 15 4 3 0 0 0.0 0.0 0.0 +0 0 15 5 3 0 0 0.0 0.0 0.0 +0 0 15 6 3 0 0 0.0 0.0 0.0 +0 0 15 7 3 0 0 0.0 0.0 0.0 +0 0 15 8 3 0 0 0.0 0.0 0.0 +0 0 15 9 3 0 0 0.0 0.0 0.0 +0 0 15 10 3 0 0 0.0 0.0 0.0 +0 0 15 11 3 0 0 0.0 0.0 0.0 +0 0 15 12 3 0 0 0.0 0.0 0.0 +0 0 15 13 3 0 0 0.0 0.0 0.0 +0 0 15 14 3 0 0 0.0 0.0 0.0 +0 0 15 15 3 0 0 0.0 0.0 0.0 +0 0 15 16 3 0 0 0.0 0.0 0.0 +0 0 15 17 3 0 0 0.0 0.0 0.0 +0 0 15 18 3 0 0 0.0 0.0 0.0 +0 0 15 19 3 0 0 0.0 0.0 0.0 +0 0 15 20 3 0 0 0.0 0.0 0.0 +0 0 15 21 3 0 0 0.0 0.0 0.0 +0 0 15 22 3 0 0 0.0 0.0 0.0 +0 0 15 23 3 0 0 0.0 0.0 0.0 +0 0 15 24 3 0 0 0.0 0.0 0.0 +0 0 15 25 3 0 0 0.0 0.0 0.0 +0 0 15 26 3 0 0 0.0 0.0 0.0 +0 0 15 27 3 0 0 0.0 0.0 0.0 +0 0 15 28 3 0 0 0.0 0.0 0.0 +0 0 15 29 3 0 0 0.0 0.0 0.0 +0 0 15 30 3 0 0 0.0 0.0 0.0 +0 0 15 31 3 0 0 0.0 0.0 0.0 diff --git a/config/map_trigger.tsv b/config/map_trigger.tsv new file mode 100644 index 0000000..0a081bc --- /dev/null +++ b/config/map_trigger.tsv @@ -0,0 +1,10 @@ +0 0 M +1 1 M +2 2 M +3 3 M +0 1 C +0 2 C +0 3 C +1 2 C +1 3 C +2 3 C diff --git a/configuration.template.sh b/configuration.template.sh index 6a989f4..3a00f1a 100644 --- a/configuration.template.sh +++ b/configuration.template.sh @@ -4,6 +4,8 @@ CONFIG_FILE=${DATA_DIR}/config.ini set -e +mkdir -p ${DATA_DIR} + ./acquire_threshold_calibration --config ${CONFIG_FILE} -o ${DATA_DIR}/disc_calibration ./process_threshold_calibration --config ${CONFIG_FILE} -i ${DATA_DIR}/disc_calibration -o ${DATA_DIR}/disc_calibration.tsv --root-file ${DATA_DIR}/disc_calibration.root diff --git a/src/gui/start_gui b/src/gui/start_gui index 21fcfaa..a2ba12f 100755 --- a/src/gui/start_gui +++ b/src/gui/start_gui @@ -1,4 +1,5 @@ #!/usr/bin/env python +from __future__ import print_function import gi gi.require_version('Gtk', '3.0') @@ -20,10 +21,18 @@ from petsys import daqd from fcntl import fcntl, F_GETFL, F_SETFL from os import O_NONBLOCK, read +if 'SW_DAQ_TOFHIR' not in os.environ: + print("Error! Need to set SW_DAQ_TOFHIR environment variable!") + print("Try running: $ export SW_DAQ_TOFHIR=/path/to/sw_daq_tofhir") + sys.exit(1) + + class GUI: def __init__ (self): self.builder = Gtk.Builder() - self.builder.add_from_file('src/gui/gui_layout.glade') + + layout = os.path.join(os.environ['SW_DAQ_TOFHIR'],'src/gui/gui_layout.glade') + self.builder.add_from_file(layout) self.MainWindow = self.builder.get_object("MainWindow") diff --git a/src/petsys_py_lib/config.py b/src/petsys_py_lib/config.py index 957a782..afbdf52 100644 --- a/src/petsys_py_lib/config.py +++ b/src/petsys_py_lib/config.py @@ -295,25 +295,28 @@ def mapAsicChannelThresholdToDAC(self, key, vth_str, value): tmp = { "vth_t1" : vth_t1, "vth_t2" : vth_t2, "vth_e" : vth_e } return int( tmp[vth_str] + value) - def mapALDOVoltageToDAC(self, (portID, slaveID, chipID), bd, ov): - retA = -1 - retB = -1 - bestA = 9999. - bestB = 9999. - for key in self.__ALDOACalibrationTable[(portID, slaveID, chipID)]: - val = self.__ALDOACalibrationTable[(portID, slaveID, chipID)][key] - if abs( float(val) - (float(bd)+float(ov)) ) < bestA: - retA = key - bestA = abs( float(val) - (float(bd)+float(ov)) ) - for key in self.__ALDOBCalibrationTable[(portID, slaveID, chipID)]: - val = self.__ALDOBCalibrationTable[(portID, slaveID, chipID)][key] - if abs( float(val) - (float(bd)+float(ov)) ) < bestB: - retB = key - bestB = abs( float(val) - (float(bd)+float(ov)) ) - print("ALDO A(J2) on ASIC%d: DAC: %d V: %f") %(chipID,int(retA),float(self.__ALDOACalibrationTable[(portID, slaveID, chipID)][retA])) - print("ALDO B(J4) on ASIC%d: DAC: %d V: %f") %(chipID,int(retB),float(self.__ALDOBCalibrationTable[(portID, slaveID, chipID)][retB])) + def mapALDOVoltageToDAC(self, (portID, slaveID, chipID, aldoID), bd, ov): + ret = -1 + best = 9999. + table = {} + if aldoID is 'A': + table = self.__ALDOACalibrationTable[(portID, slaveID, chipID)] + if aldoID is 'B': + table = self.__ALDOBCalibrationTable[(portID, slaveID, chipID)] + + for key in table: + val = table[key] + if abs( float(val) - (float(bd)+float(ov)) ) < best: + ret = key + best = abs( float(val) - (float(bd)+float(ov)) ) + print("ALDO %s on ASIC%d: DAC: %d V: %f") %(aldoID,chipID,int(ret),float(table[ret])) + return ret + + def mapALDODACToVoltage(self, (portID, slaveID, chipID), dac): + retA = float(self.__ALDOACalibrationTable[(portID, slaveID, chipID)][dac]) + retB = float(self.__ALDOBCalibrationTable[(portID, slaveID, chipID)][dac]) return retA, retB - + def toInt(s): s = s.upper() if s[0:2] == "0X": @@ -405,8 +408,8 @@ def readSiPMBiasTableAldo(fn): for l in f: l = normalizeAndSplit(l) if l == ['']: continue - portID, slaveID, chipID = [ int(v) for v in l[0:3] ] - c[(portID, slaveID, chipID)] = [ float(v) for v in l[3:5] ] + portID, slaveID, chipID, aldoID = [ int(l[0]), int(l[1]), int(l[2]), l[3] ] + c[(portID, slaveID, chipID, aldoID)] = [ float(v) for v in l[4:6] ] f.close() return c diff --git a/src/petsys_util/acquire_sipm_IV_scan b/src/petsys_util/acquire_sipm_IV_scan new file mode 100755 index 0000000..79dfa67 --- /dev/null +++ b/src/petsys_util/acquire_sipm_IV_scan @@ -0,0 +1,267 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function +from petsys import daqd, config +from copy import deepcopy +from time import sleep +import argparse +import os +import subprocess +import ROOT +import sys +import math +from datetime import datetime +from os.path import expanduser, join + +# Try to guess where the Lab5015Utils directory is +sys.path.append(join(os.path.dirname(os.path.abspath(__file__)),"../..","Lab5015Utils")) +try: + from Lab5015_utils import Keithley2450, PiLas +except ImportError as e: + print("Error: unable to import from Lab5015_utils!") + print(e) + print("Maybe you need to add the directory to your PYTHONPATH environment variable?") + print("Example: $ export PYTHONPATH=/path/to/Lab5015_utils") + sys.exit(1) + +try: + from Lab5015_utils import Agilent3606A +except ImportError as e: + print("Unable to import Agilent3606A from Lab5015_utils. Skipping...") + +try: + from Lab5015_utils import KeithleyDMM6500 +except ImportError as e: + print("Unable to import KeithleyDMM6500 from Lab5015_utils. Skipping...") + +parser = argparse.ArgumentParser(description='Acquire SiPM IV scan') +parser.add_argument("--config", type=str, required=True, help="Configuration file") +parser.add_argument("--bvMin", type=str, dest="bvMin", required=True, help="starting bv") +parser.add_argument("--bvMax", type=str, dest="bvMax", required=True, help="ending bv") +parser.add_argument("--aldo", type=str, dest="aldo", required=True, help="which ALDO") +parser.add_argument("--nMeas", type=str, dest="nMeas", required=False, help="number of measurements to average") +parser.add_argument("--label", type=str, dest="label", required=False, help="folder name") +parser.add_argument("--verbose", default=False, action="store_true", help="set to true to display output and plots, otherwise just save to root file") +parser.add_argument("--keithley-model", type=int, choices=[2450,6500,3606], default=6500, help="Keithley model number (2450, 6500, or 3606 (3606 is actually Agilent))") +parser.add_argument("--keithley-ip-address", type=str, default=None, help="Keithley IP address") + +#------------------------ +# parsing input arguments +args = parser.parse_args() + +#----------------------------- +# load configuration from file +mask = config.LOAD_ALL +# if args.mode != "mixed": +# mask ^= config.LOAD_QDCMODE_MAP +mask ^= config.LOAD_QDCMODE_MAP +systemConfig = config.ConfigFromFile(args.config, loadMask=mask) + +daqd = daqd.Connection() +daqd.initializeSystem() +systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_OFF) + +asicsConfig = daqd.getAsicsConfig() +activeAsics = daqd.getActiveAsics() + +if len(activeAsics) == 0: + print("no active ASICs found. Exiting...") + exit() + + + +#-------------------------------------------------------------------- +# enable ALDO in case needed (it's only on even ASICs, e.g. 0,2,4...) +#if args.aldo: +# hvdac_config = daqd.get_hvdac_config() +# for portID, slaveID, railID in hvdac_config.keys(): +# # set 48 V as ALDO input bias (should not exceed this value) +# hvdac_config[(portID, slaveID, railID)] = systemConfig.mapBiasChannelVoltageToDAC((portID, slaveID, railID), 48) +# daqd.set_hvdac_config(hvdac_config) + + +if args.keithley_model in [2450, 6500]: + if args.keithley_ip_address is None: + ip_address_file = join(expanduser("~"),".keithley_ip_address.txt") + + if os.path.exists(ip_address_file): + with open(ip_address_file) as f: + args.keithley_ip_address = f.read().strip() + else: + print("Must supply Keithley IP address! You can find it by going to settings and then communication") + sys.exit(1) + else: + ip_address_file = join(expanduser("~"),".keithley_ip_address.txt") + with open(ip_address_file,"w") as f: + f.write(args.keithley_ip_address) + + portname = 'TCPIP0::%s::INSTR' % args.keithley_ip_address + print("Connecting to Keithley at ip address '%s'" % args.keithley_ip_address) + print("To change this IP address either edit ~/.keithley_ip_address.txt or remove that file and you will be prompted next time to enter it.") + +if args.keithley_model == 2450: + mykey = Keithley2450(portname) +elif args.keithley_model == 3606: + mykey = Agilent3606A() +else: + mykey = KeithleyDMM6500(portname) + mykey.set_read_V() + +asicsConfig0 = deepcopy(asicsConfig) +cfg = deepcopy(asicsConfig0) + + +for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + + ac = cfg[(portID, slaveID, chipID)] + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + gc.setValue("c_aldo_en", 0b00) + daqd.setAsicsConfig(cfg) + sleep(0.1) + + if args.keithley_model == 2450: + # FIXME: Would be much nicer to have a consistent interface between + # the two keithley models so we don't have to have this if + # statement here. + _, voltage = mykey.meas_V() + elif args.keithley_model == 3606: + voltage = mykey.meas_V() + else: + voltage = mykey.read() + print("ALDO off I: %f uA" % (float(voltage)*1E06/10.)) + + +#-------------- +# define graphs +g_I = ROOT.TGraph() +g_IV = ROOT.TGraph() +g_dlogIdV = ROOT.TGraph() + + +#-------- +# ov scan +for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + + ac = cfg[(portID, slaveID, chipID)] + for dac in range(0,256,1): + voltA, voltB = systemConfig.mapALDODACToVoltage((portID, slaveID, chipID),dac) + volt = 0. + + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + if args.aldo is "A": + gc.setValue("c_aldo_en", 0b10) + gc.setValue("Valdo_A_DAC", dac) + volt = float(voltA) + if args.aldo is "B": + gc.setValue("c_aldo_en", 0b01) + gc.setValue("Valdo_B_DAC", dac) + volt = float(voltB) + daqd.setAsicsConfig(cfg) + + if volt < float(args.bvMin): + continue + if volt > float(args.bvMax): + break + + sleep(0.25) + + curr = 0. + vMeas = 0. + nMeas = 1 + if args.nMeas: + nMeas = int(args.nMeas) + it = 0 + for _ in range(0, nMeas): + sleep(1) + if args.keithley_model == 2450: + _, thisVolt = mykey.meas_V() + elif args.keithley_model == 3606: + thisVolt = mykey.meas_V() + else: + thisVolt = mykey.read() + thisVolt = abs(thisVolt) + thisCurr = float(thisVolt)*1E06/10. + if args.verbose: + print("dac: %3d V_set: %6.3f V V_meas: %.3f mV --> I: %f uA" % (int(dac),volt,1000.*thisVolt,thisCurr)) + #print ("dac: %3d V_set: %6.3f V V_meas: %f V" % (int(dac),volt,thisVolt)) + g_I.SetPoint(g_I.GetN(),g_I.GetN(),thisCurr) + #g_IV.SetPoint(g_IV.GetN(),g_IV.GetN(),thisVolt) + + if it >= 0: + curr = curr + thisCurr + vMeas = vMeas + thisVolt + it += 1 + + curr = curr / nMeas + vMeas = vMeas / nMeas + g_IV.SetPoint(g_IV.GetN(),volt, curr) + print( "===> dac: %3.0d V_set: %6.3f V_meas: %6.3f mV --> I: %f uA" % (int(dac),volt,1000.*vMeas,curr)) + #g_IV.SetPoint(g_IV.GetN(),volt, vMeas) + #print( "%3.0d\t%f" % (int(dac),vMeas)) + + +#------------------------- +# switch off bias voltages +#systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_OFF) + +for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + gc.setValue("c_aldo_en", 0b00) +daqd.setAsicsConfig(cfg) + + +#--------- +# plotting +c1 = ROOT.TCanvas("c1","c1",1300,600) +c1.Divide(2,1) +c1.cd(1) +g_IV.Draw("APL") + +c1.cd(2) +for point in range(1, g_IV.GetN()): + x1 = g_IV.GetPointX(point-1) + y1 = g_IV.GetPointY(point-1) + x2 = g_IV.GetPointX(point) + y2 = g_IV.GetPointY(point) + g_dlogIdV.SetPoint(g_dlogIdV.GetN(),0.5*(x1+x2),(math.log(y2)-math.log(y1))/(x2-x1)) + +if args.verbose: + c1 = ROOT.TCanvas("c1","c1",500,500) + g_I.SetTitle("I vs i measurement;i measurement;current") + g_I.Draw("APL") + + c2 = ROOT.TCanvas("c2","c2",500,500) + g_IV.SetTitle("I vs volt;volt [V]; I [#muA]") + g_IV.Draw("APL") + + c3 = ROOT.TCanvas("c3","c3",500,500) + g_dlogIdV.SetTitle("dlogIdV vs volt;volt [V]; #DeltalogI/#deltaV [#muA/V]") + g_dlogIdV.Draw("APL") + + raw_input("ok?") + +now = datetime.now() +this_time = now.strftime('%Y-%m-%d_%H:%M:%S') +if not args.label: + args.label = '/' + +os.system("mkdir -p ../log_IV/%s"%args.label) +outfile_name = ("../log_IV/%s/IV_ALDO%s_time_%s.root"%(args.label,args.aldo,this_time)) +print('saving data to: %s' % outfile_name) + +outFile = ROOT.TFile(outfile_name,"RECREATE") +outFile.cd() +g_I.SetName("g_I") +g_I.Write() +g_IV.SetName("g_IV") +g_IV.Write() +g_dlogIdV.SetName("g_dlogIdV") +g_dlogIdV.Write() +outFile.Write() +outFile.Close() diff --git a/src/petsys_util/acquire_sipm_data_scan b/src/petsys_util/acquire_sipm_data_scan index ba9a042..496e391 100755 --- a/src/petsys_util/acquire_sipm_data_scan +++ b/src/petsys_util/acquire_sipm_data_scan @@ -1,12 +1,11 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- - +from __future__ import print_function from petsys import daqd, config from copy import deepcopy from time import sleep import argparse import os - +import pprint def get_list(input_list): vals = [] @@ -20,41 +19,53 @@ def get_list(input_list): vals.append(float(hyphen_list[0])) return vals - parser = argparse.ArgumentParser(description='Acquire SiPM data') parser.add_argument("--config", type=str, required=True, help="Configuration file") parser.add_argument("-o", type=str, dest="fileNamePrefix", required=False, help="Data filename (prefix)") parser.add_argument("--time", type=float, required=True, help="Acquisition time (in seconds)") parser.add_argument("--enable-hw-trigger", dest="hwTrigger", action="store_true", help="Enable the hardware coincidence filter") -parser.add_argument("--vth1", type=str, dest="vth1", required=True, help="comma separated values for vth1") -parser.add_argument("--vth2", type=str, dest="vth2", required=True, help="comma separated values for vth2") -parser.add_argument("--vthe", type=str, dest="vthe", required=True, help="comma separated values for vthe") -parser.add_argument("--taps", type=str, dest="taps", required=False, help="number of taps [0..6]") +parser.add_argument("--ith1", type=str, dest="ith1", required=True, help="comma separated values for ith1") +parser.add_argument("--ith2", type=str, dest="ith2", required=True, help="comma separated values for ith2") +parser.add_argument("--ithe", type=str, dest="ithe", required=True, help="comma separated values for ithe") +parser.add_argument("--ith2rel", dest="ith2rel", action="store_true", help="relative ith2 threshold") +parser.add_argument("--delayT", type=str, dest="delayT", required=False, help="delay for t branch [0..6]") +parser.add_argument("--delayE", type=str, dest="delayE", required=False, help="delay for e branch [0..6]") +parser.add_argument("--trimT", type=str, dest="trimT", required=False, help="trim for t branch [0..31]") +parser.add_argument("--trimE", type=str, dest="trimE", required=False, help="trim for e branch [0..31]") parser.add_argument("--attGain", type=int, dest="attGain", required=False, help="attenuator gain [0..7]") parser.add_argument("--ov", type=str, dest="ov", required=True, help="comma separated values for ov") +parser.add_argument("--ovDrop", type=float, dest="ovDrop", required=False, help="compensation for ov drop") parser.add_argument("--aldo", dest="aldo", action="store_true", help="switch for ALDO usage") parser.add_argument("--trigger", type=str, dest="trigger", required=False, help="trigger type (none, ext, int)") parser.add_argument("--freq", type=float, dest="freq", required=False, help="internal trigger frequency (in kHz)") parser.add_argument("--phase", type=float, dest="phase", required=False, help="trigger phase (in clk)") parser.add_argument("--prescale", type=int, dest="prescale", required=False, help="external trigger prescale [0..63]") parser.add_argument("--l1", dest="l1", action="store_true", help="Enable the L1 filtering") -parser.add_argument("--pedestals", dest="pedestals", action="store_true", help="Enable the acquisition of pedestals") parser.add_argument("--enable-channels", dest="enChannels", required=False, help="comma separated vector of enabled channels") -parser.add_argument("--fix-channels", dest="fixChannels", required=False, help="comma separated vector of channels for which vth1 is fixed at 30") - +parser.add_argument("--fix-channels", dest="fixChannels", required=False, help="comma separated vector of channels for which ith1 is fixed at 30") +parser.add_argument("--wait", dest="wait", action="store_true", help="wait 60 sec. before starting the run") +parser.add_argument("--data-dir", default="/storage/TOFHIR2", help="Directory to store raw and reco data") #------------------------ # parsing input arguments args = parser.parse_args() -vth1_list = get_list(args.vth1) -vth2_list = get_list(args.vth2) -vthe_list = get_list(args.vthe) +if not os.path.exists(args.data_dir): + print("Error: data directory '%s' does not exist!" % args.data_dir) + print("Please rerun with --data-dir specifying where output data is") + sys.exit(1) + +os.system('mkdir -p %s' % os.path.join(args.data_dir,"raw")) +os.system('mkdir -p %s' % os.path.join(args.data_dir,"reco")) + +ith1_list = get_list(args.ith1) +ith2_list = get_list(args.ith2) +ithe_list = get_list(args.ithe) ov_list = get_list(args.ov) -taps = 6 -if args.taps: - taps = args.taps +ovDrop = 0. +if args.ovDrop: + ovDrop = args.ovDrop if( args.enChannels ): args.enChannels = args.enChannels.split(',') @@ -62,19 +73,36 @@ if( args.enChannels ): if( args.fixChannels ): args.fixChannels = args.fixChannels.split(',') +run = -1 if not args.fileNamePrefix: - with open('/data/TOFHIR2/last_run') as f: - run = [int(x) for x in next(f).split()] - os.remove('/data/TOFHIR2/last_run') - with open('/data/TOFHIR2/last_run','w+') as f: - f.write(str(run[0]+1)) - args.fileNamePrefix = "/data/TOFHIR2/raw/run%04d" % (run[0]+1) + last_run_file = os.path.join(args.data_dir,"last_run") + if not os.path.exists(last_run_file): + print("Last run file '%s' does not exist. Should I create it [y/n]?" % last_run_file) + answer = raw_input() + if answer.lower() == 'y': + with open(last_run_file,"w") as f: + f.write("0\n") + else: + print("Quitting...") + sys.exit(0) + with open(last_run_file) as f: + runs = [int(x) for x in next(f).split()] + run = str(runs[0]+1) + os.remove(last_run_file) + with open(last_run_file,'w+') as f: + f.write(run) + args.fileNamePrefix = os.path.join(args.data_dir,"raw/run%04d" % (int(run))) +else: + run = args.fileNamePrefix -if args.pedestals: - print("INFO: acquiring pedestals") - command = "./acquire_qdc_calibration_fixed --config "+args.config+" -o "+args.fileNamePrefix+"_ped1" - os.system(command) +#--------------------- +# copy the config file +new_config_file = os.path.join(args.data_dir, "raw", "config_run%s.ini" % str(run)) +os.system('cp %s %s' % (args.config,new_config_file)) +with open(new_config_file, 'a') as configCopy: + configCopy.write(pprint.pformat(args)) + configCopy.write('\n') #----------------------------- # load configuration from file @@ -86,35 +114,42 @@ systemConfig = config.ConfigFromFile(args.config, loadMask=mask) daqd = daqd.Connection() daqd.initializeSystem() -systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_ON) +systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_OFF) asicsConfig = daqd.getAsicsConfig() activeAsics = daqd.getActiveAsics() +if len(activeAsics) == 0: + print("no active ASICs found. Exiting...") + exit() +else: + print("active ASICs found: ") + print(activeAsics) + #-------------- # trigger modes if args.trigger == "none": - print "### self-triggering mode ###" + print("### self-triggering mode ###") if args.trigger == "int": # Enable INTERNAL triggers from FEB/D to J15 daqd.write_config_register_tgr(8, 0x21A, 0x81) daqd.setTestPulsePLL(100, int(1./(args.freq*6.25e-06)), args.phase, False) if args.trigger == "ext": # Enable EXTERNAL L1 trigger source from J15 - ext_delay = 1917 # Delay added by FPGA in 6.25 ns increments - daqd.write_config_register_tgr(8, 0x21A, 0x11) - daqd.write_config_register_tgr(64, 0x02A0, (1<<63) | (0<<62) | (3 << 48) | ( args.prescale << 16) | (ext_delay) ) # prescale: 0..63 -- 0 is 0%, 63 is 63/64% + daqd.write_config_register_tgr(8, 0x21A, 0x01) + #ext_delay = 1917 # Delay added by FPGA in 6.25 ns increments + #daqd.write_config_register_tgr(64, 0x02A0, (1<<63) | (0<<62) | (3 << 48) | ( args.prescale << 16) | (ext_delay) ) # prescale: 0..63 -- 0 is 0%, 63 is 63/64% #-------------------------------------------------------------------- # enable ALDO in case needed (it's only on even ASICs, e.g. 0,2,4...) -if args.aldo: - hvdac_config = daqd.get_hvdac_config() - for portID, slaveID, railID in hvdac_config.keys(): - # set 48 V as ALDO input bias (should not exceed this value) - hvdac_config[(portID, slaveID, railID)] = systemConfig.mapBiasChannelVoltageToDAC((portID, slaveID, railID), 48) - daqd.set_hvdac_config(hvdac_config) +#if args.aldo: +# hvdac_config = daqd.get_hvdac_config() +# for portID, slaveID, railID in hvdac_config.keys(): +# # set 48 V as ALDO input bias (should not exceed this value) +# hvdac_config[(portID, slaveID, railID)] = systemConfig.mapBiasChannelVoltageToDAC((portID, slaveID, railID), 46) +# daqd.set_hvdac_config(hvdac_config) #------------------------------------------------ @@ -145,13 +180,13 @@ if args.trigger == "ext": continue gc = asicsConfig[(portID, slaveID, chipID)].globalConfig # Enable L1 trigger for even ASICs (with flex and ALDO) - if args.l1 : - gc.setValue("c_l1_enable", 0b01) - else: - gc.setValue("c_l1_enable", 0b00) - gc.setValue("c_l1_latency", 484) # Delay expected by ASIC in 25 ns increments + #if args.l1 : + # gc.setValue("c_l1_enable", 0b01) + #else: + # gc.setValue("c_l1_enable", 0b00) + #gc.setValue("c_l1_latency", 484) # Delay expected by ASIC in 25 ns increments # Use ASIC 1 channel 0 to timetag the trigger pulses - asicsConfig[(0, 0, 1)].globalConfig.setValue("c_ext_tp_en", 0b1) + asicsConfig[(0, 0, 1)].globalConfig.setValue("c_ext_tp_en", 1) asicsConfig[(0, 0, 1)].channelConfig[0].setValue("c_tgr_main", 0b01) @@ -162,9 +197,9 @@ cfg = deepcopy(asicsConfig0) #-------------------------------- # scan on thresholds and / or ov -for vth1 in vth1_list: - for vth2 in vth2_list: - for vthe in vthe_list: +for ith1 in ith1_list: + for ith2 in ith2_list: + for ithe in ithe_list: for ov in ov_list: for portID, slaveID, chipID in activeAsics: @@ -172,42 +207,75 @@ for vth1 in vth1_list: for channelID in range(32): cc = ac.channelConfig[int(channelID)] - #cc.setValue("cfg_a3_vth_t1", vth1) - #cc.setValue("cfg_a3_vth_t2", vth2) - #cc.setValue("cfg_a3_vth_e", vthe) - - dac_setting_vth1 = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t1", int(vth1)) - cc.setValue("cfg_a3_vth_t1", dac_setting_vth1) - dac_setting_vth2 = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t2", int(vth2)) - cc.setValue("cfg_a3_vth_t2", dac_setting_vth2) - dac_setting_vthe = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_e", int(vthe)) - cc.setValue("cfg_a3_vth_e", dac_setting_vthe) - #print("%d %d %d %d : %d,%d,%d") % (portID,slaveID,chipID,channelID,dac_setting_vth1,dac_setting_vth2,dac_setting_vthe) - - cc.setValue("cfg_a2_postamp_t_delay",int(taps)) + if args.delayT: + cc.setValue("cfg_a2_dcr_delay_t",int(args.delayT,2)) + if args.delayE: + cc.setValue("cfg_a2_dcr_delay_e",int(args.delayE,2)) if args.attGain: cc.setValue("cfg_a2_attenuator_gain",args.attGain) + if channelID == 0: + cc.setValue("cfg_a2_pulse_trim_t",int(15)) + if channelID == 31: + cc.setValue("cfg_a2_pulse_trim_t",int(12)) + + if args.trimT: + cc.setValue("cfg_a2_pulse_trim_t",int(args.trimT)) + if args.trimE: + cc.setValue("cfg_a2_pulse_trim_e",int(args.trimE)) + + # raw thresholds + #dac_setting_ith1 = int(ith1) + #dac_setting_ith2 = int(ith2) + #dac_setting_ithe = int(ithe) + # baseline-subtracted thresholds + dac_setting_ith1 = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t1", int(ith1)) ) + dac_setting_ith2 = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t2", int(ith2)) ) + dac_setting_ithe = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_e", int(ithe)) ) + # T1-relative T2 threshold + if args.ith2rel: + dac_setting_ith2 = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t2", int(ith1)+int(ith2)) ) + + cc.setValue("cfg_a3_ith_t1", dac_setting_ith1) + cc.setValue("cfg_a3_ith_t2", dac_setting_ith2) + cc.setValue("cfg_a3_ith_e", dac_setting_ithe) + + ############# FIXME + # if chipID == 2: + # dac_setting_ith1 = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t1", 10) ) + # dac_setting_ith2 = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t2", 10) ) + # dac_setting_ithe = min( 63, systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_e", 1) ) + # cc.setValue("cfg_a3_ith_t1", dac_setting_ith1) + # cc.setValue("cfg_a3_ith_t2", dac_setting_ith2) + # cc.setValue("cfg_a3_ith_e", dac_setting_ithe) + # cc.setValue("cfg_a2_attenuator_gain",0) + # cc.setValue("cfg_a2_dcr_delay_e",0b0000011) + ####################### + + + if channelID == 0: + print(("%d %d %d %d : %d,%d,%d") % (portID,slaveID,chipID,channelID,dac_setting_ith1,dac_setting_ith2,dac_setting_ithe)) + if( args.fixChannels ): for ac in cfg.values(): for ch in args.fixChannels: - print "fixing channel %d" % int(ch) + print("fixing channel %d" % int(ch)) - #cc.setValue("cfg_a3_vth_t1", 10) - #cc.setValue("cfg_a3_vth_t2", 10) + #cc.setValue("cfg_a3_ith_t1", 10) + #cc.setValue("cfg_a3_ith_t2", 10) cc = ac.channelConfig[int(ch)] - dac_setting_vth1 = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t1", int(10)) - cc.setValue("cfg_a3_vth_t1", dac_setting_vth1) - dac_setting_vth2 = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t2", int(10)) - cc.setValue("cfg_a3_vth_t2", dac_setting_vth2) + dac_setting_ith1 = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t1", int(10)) + cc.setValue("cfg_a3_ith_t1", dac_setting_ith1) + dac_setting_ith2 = systemConfig.mapAsicChannelThresholdToDAC((portID, slaveID, chipID, channelID), "vth_t2", int(10)) + cc.setValue("cfg_a3_ith_t2", dac_setting_ith2) if not args.aldo: biasVoltageConfig = daqd.get_hvdac_config() for key in daqd.getActiveBiasChannels(): offset, prebd, bd, over__ = systemConfig.getBiasChannelDefaultSettings(key) - vset = offset + bd + float(ov) + vset = offset + bd + float(ov) + ovDrop dac_setting = systemConfig.mapBiasChannelVoltageToDAC(key, vset) biasVoltageConfig[key] = dac_setting daqd.set_hvdac_config(biasVoltageConfig) @@ -216,23 +284,41 @@ for vth1 in vth1_list: for portID, slaveID, chipID in activeAsics: if chipID%2 is not 0: continue - bd, over__ = systemConfig.getBiasChannelDefaultSettingsAldo((portID, slaveID, chipID)) gc = (cfg[(portID, slaveID, chipID)]).globalConfig - dac_A, dac_B = systemConfig.mapALDOVoltageToDAC((portID, slaveID, chipID),bd,float(ov)) gc.setValue("c_aldo_en", 0b11) - gc.setValue("Valdo_A_DAC", dac_A) - gc.setValue("Valdo_B_DAC", dac_B) - + for aldoID in ['A', 'B']: + bd, over__ = systemConfig.getBiasChannelDefaultSettingsAldo((portID, slaveID, chipID, aldoID)) + dac = systemConfig.mapALDOVoltageToDAC((portID, slaveID, chipID, aldoID),bd,float(ov)+ovDrop) + + ### FIXME#################### + # if chipID == 2: + # dac = systemConfig.mapALDOVoltageToDAC((portID, slaveID, chipID, aldoID),bd,3.5) + ########################## + gc.setValue("Valdo_%s_DAC"%aldoID, dac) + + daqd.setAsicsConfig(cfg) sleep(0.1) - print "ov: %3.1f, vth1: %2d, vth2: %2d, vthe: %2d" % (float(ov), int(vth1), int(vth2), int(vthe)) - daqd.acquire(args.time, float(ov), 10000*(int(vth1)+1)+100*(int(vth2)+1)+int(vthe)+1) + if args.wait: + sleep(60.) + args.wait = False + print("ov: %3.1f, ith1: %2d, ith2: %2d, ithe: %2d" % (float(ov), int(ith1), int(ith2), int(ithe))) + print(">>> t1: " + str(((cfg[(0,0,0)]).channelConfig[0]).getValue("cfg_a3_ith_t1"))) + print(">>> t2: " + str(((cfg[(0,0,0)]).channelConfig[0]).getValue("cfg_a3_ith_t2"))) + print(">>> e: " + str(((cfg[(0,0,0)]).channelConfig[0]).getValue("cfg_a3_ith_e"))) + daqd.acquire(args.time, float(ov), 10000*(int(ith1)+1)+100*(int(ith2)+1)+int(ithe)+1) -systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_OFF) -daqd.setTestPulseNone() +#------------------------- +# switch off bias voltages +systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_OFF) -if args.pedestals: - print("INFO: acquiring pedestals") - command = "./acquire_qdc_calibration_fixed --config "+args.config+" -o "+args.fileNamePrefix+"_ped2" - os.system(command) +if args.aldo: + for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + gc.setValue("c_aldo_en", 0b00) + daqd.setAsicsConfig(cfg) + +daqd.setTestPulseNone() diff --git a/src/petsys_util/acquire_sipm_stressTest b/src/petsys_util/acquire_sipm_stressTest new file mode 100755 index 0000000..1952abd --- /dev/null +++ b/src/petsys_util/acquire_sipm_stressTest @@ -0,0 +1,254 @@ +#!/usr/bin/env python +from __future__ import print_function +import sys +import os +from petsys import daqd, config +from copy import deepcopy +from time import sleep +import argparse +import ROOT +import math +from datetime import datetime +from ROOT import TFile +from os.path import expanduser, join + +# Try to guess where the Lab5015Utils directory is +sys.path.append(join(os.path.dirname(os.path.abspath(__file__)),"../..","Lab5015Utils")) +try: + from Lab5015_utils import Keithley2450, PiLas +except ImportError as e: + print("Error: unable to import from Lab5015_utils!") + print(e) + print("Maybe you need to add the directory to your PYTHONPATH environment variable?") + print("Example: $ export PYTHONPATH=/path/to/Lab5015_utils") + sys.exit(1) + +try: + from Lab5015_utils import Agilent3606A +except ImportError as e: + print("Unable to import Agilent3606A from Lab5015_utils. Skipping...") + +try: + from Lab5015_utils import KeithleyDMM6500 +except ImportError as e: + print("Unable to import KeithleyDMM6500 from Lab5015_utils. Skipping...") + +parser = argparse.ArgumentParser(description='Acquire SiPM IV scan') +parser.add_argument("--config", type=str, required=True, help="Configuration file") +parser.add_argument("--bv", type=float, required=True, help="initial bias voltage") +parser.add_argument("--aldoA", dest="aldoA", action="store_true", help="do aldo A") +parser.add_argument("--aldoB", dest="aldoB", action="store_true", help="do aldo B") +parser.add_argument("--ch", dest="keyChannel", required=True, help="which multimeter channel to read") +parser.add_argument("--time", type=float, dest="time", required=True, help="number of measurements to average") +parser.add_argument("--label", type=str, dest="label", required=True, help="folder name") +parser.add_argument("--verbose", default=False, action="store_true", help="set to true to display output and plots, otherwise just save to root file") +parser.add_argument("--laser", dest="laser", action="store_true", help="pilot laser") +parser.add_argument("--asic", type=int, dest="asic", required=True, help="asic id") +parser.add_argument("--keithley-model", type=int, choices=[2450,6500,3606], default=6500, help="Keithley model number (2450, 6500, or 3606 (3606 is actually Agilent))") +parser.add_argument("--keithley-ip-address", type=str, default=None, help="Keithley IP address") + +#------------------------ +# parsing input arguments +args = parser.parse_args() + +#--------------------------------- +# connect and configure multimeter + +if args.keithley_model in [2450, 6500]: + if args.keithley_ip_address is None: + ip_address_file = join(expanduser("~"),".keithley_ip_address.txt") + + if os.path.exists(ip_address_file): + with open(ip_address_file) as f: + args.keithley_ip_address = f.read().strip() + else: + print("Must supply Keithley IP address! You can find it by going to settings and then communication") + sys.exit(1) + else: + ip_address_file = join(expanduser("~"),".keithley_ip_address.txt") + with open(ip_address_file,"w") as f: + f.write(args.keithley_ip_address) + + portname = 'TCPIP0::%s::INSTR' % args.keithley_ip_address + print("Connecting to Keithley at ip address '%s'" % args.keithley_ip_address) + print("To change this IP address either edit ~/.keithley_ip_address.txt or remove that file and you will be prompted next time to enter it.") + +if args.keithley_model == 2450: + mykey = Keithley2450(portname) +elif args.keithley_model == 3606: + mykey = Agilent3606A() +else: + mykey = KeithleyDMM6500(portname) + mykey.closeChannel(int(args.keyChannel)) + mykey.read() + +las = None +if args.laser: + las = PiLas() + lasState = 0 + if args.laser: + las.set_state(lasState) + + +#----------------------------- +# load configuration from file +mask = config.LOAD_ALL +# if args.mode != "mixed": +# mask ^= config.LOAD_QDCMODE_MAP +mask ^= config.LOAD_QDCMODE_MAP +systemConfig = config.ConfigFromFile(args.config, loadMask=mask) + +daqd = daqd.Connection() +daqd.initializeSystem() +systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_ON) + +hvdac_config = daqd.get_hvdac_config() +for portID, slaveID, railID in hvdac_config.keys(): + # set 48 V as ALDO input bias (should not exceed this value) + hvdac_config[(portID, slaveID, railID)] = systemConfig.mapBiasChannelVoltageToDAC((portID, slaveID, railID), 46) +daqd.set_hvdac_config(hvdac_config) + +asicsConfig = daqd.getAsicsConfig() +activeAsics = daqd.getActiveAsics() + +if len(activeAsics) == 0: + print ("no active ASICs found. Exiting...") + exit() + +asicsConfig0 = deepcopy(asicsConfig) +cfg = deepcopy(asicsConfig0) + +for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + if chipID != args.asic: continue + ac = cfg[(portID, slaveID, chipID)] + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + gc.setValue("c_aldo_en", 0b00) + daqd.setAsicsConfig(cfg) + sleep(0.1) + this_volt = 0. + + for it in range(0,5): + if args.keithley_model == 2450: + _, this_volt = mykey.meas_V() + elif args.keithley_model == 3606: + this_volt = mykey.meas_V() + else: + this_volt = mykey.read() + this_curr = this_volt*1e06/10. + sleep(0.5) + print( "ALDO off V_meas: %.3f mV --> I: %f uA" % (1000.*this_volt,this_curr)) + + +#-------------- +# define graphs +g_I = ROOT.TGraph() + + +#-------- +# ov scan +for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + + if chipID != args.asic: continue + + ac = cfg[(portID, slaveID, chipID)] + volt = args.bv + dac = 0 + + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + if args.aldoA and not args.aldoB: + dac = systemConfig.mapALDOVoltageToDAC((portID, slaveID, chipID, 'A'),30.,args.bv-30.) + gc.setValue("c_aldo_en", 0b10) + gc.setValue("Valdo_A_DAC", dac) + if args.aldoB and not args.aldoA: + dac = systemConfig.mapALDOVoltageToDAC((portID, slaveID, chipID, 'B'),30.,args.bv-30.) + gc.setValue("c_aldo_en", 0b01) + gc.setValue("Valdo_B_DAC", dac) + daqd.setAsicsConfig(cfg) + + sleep(1.) + + curr = 0. + vMeas = 0. + nMeas = 1 + + timestamp_init = datetime.now() + + while True: + this_volt = 0. + if args.keithley_model == 2450: + _, this_volt = mykey.meas_V() + elif args.keithley_model == 3606: + this_volt = mykey.meas_V() + else: + this_volt = mykey.read() + this_volt = abs(this_volt) + this_curr = this_volt*1E06/10. + if args.verbose: + print ("dac: %3d V_set: %6.3f V V_meas: %.3f mV --> I: %f uA" % (int(dac),volt,1000.*this_volt,this_curr)) + g_I.SetPoint(g_I.GetN(),g_I.GetN(),this_curr) + + timestamp_curr = datetime.now() + sleep(0.2) + if args.laser: + if float((timestamp_curr - timestamp_init).total_seconds()) > args.time/4. and lasState is 0: + las.set_trigger(0) + las.set_freq(50000) + #las.set_freq(467000) + #las.set_freq(10000) + lasState = 1 + las.set_state(lasState) + if float((timestamp_curr - timestamp_init).total_seconds()) > args.time: + break + + +#------------------------- +# switch off bias voltages + +systemConfig.loadToHardware(daqd, bias_enable=config.APPLY_BIAS_OFF) + +for portID, slaveID, chipID in activeAsics: + if chipID%2 is not 0: + continue + gc = (cfg[(portID, slaveID, chipID)]).globalConfig + gc.setValue("c_aldo_en", 0b00) +daqd.setAsicsConfig(cfg) + +if args.laser: + lasState = 0 + las.set_state(lasState) + + +#--------- +# plotting +now = datetime.now() +this_time = now.strftime('%Y-%m-%d_%H:%M:%S') +os.system("mkdir -p ../log_stressTest/%s/"%args.label) +outfile_name = ("../log_stressTest/%s/IV_bv%.2f_time_%s.root"%(args.label,args.bv,this_time)) +print('saving data to: %s' % outfile_name) + +outFile = TFile(outfile_name,"RECREATE") +outFile.cd() +g_I.SetName("g_I") +g_I.Write() +outFile.Write() +outFile.Close() + +if args.verbose: + c1 = ROOT.TCanvas("c1","c1",500,500) + g_I.SetTitle("I vs i measurement;i measurement;current") + g_I.Draw("APL") + min_time = g_I.GetPointX(0) + max_time = g_I.GetPointX(g_I.GetN()-1) + fitFunc_dark = ROOT.TF1('fitFunc_dark','pol0',min_time,min_time+(max_time-min_time)/5.) + g_I.Fit(fitFunc_dark,'RNS') + fitFunc_dark.SetLineColor(ROOT.kRed) + fitFunc_dark.Draw('same') + fitFunc_phot = ROOT.TF1('fitFunc_phot','pol0',min_time+(max_time-min_time)/3.,max_time) + g_I.Fit(fitFunc_phot,'RNS') + fitFunc_phot.SetLineColor(ROOT.kGreen) + fitFunc_phot.Draw('same') + raw_input("ok?") diff --git a/src/petsys_util/acquire_tdc_calibration b/src/petsys_util/acquire_tdc_calibration index 607cb35..3b9552e 100755 --- a/src/petsys_util/acquire_tdc_calibration +++ b/src/petsys_util/acquire_tdc_calibration @@ -66,7 +66,11 @@ for firstChannel in range(0, channelStep): t_start = time.time() binSize = (phaseMax - phaseMin) / nBins finePhase = phaseMin + (i+0.5) * binSize - daqd.set_test_pulse_febds(100, 1024, finePhase, False) + # Note: We increase the interval between pulses by a factor of + # 2 from Riccardo's repository. This was found to be necessary + # to not have the TDC calibration fail at Caltech and later + # with the TOFHIR2X at the University of Virginia. + daqd.set_test_pulse_febds(100, 1024*2, finePhase, False) daqd.acquire(0.02, finePhase, 0) t_finish = time.time() print "Channel(s): %s Phase: %4.3f clk in %3.2f seconds " % (activeChannels_string, finePhase, t_finish - t_start) diff --git a/src/petsys_util/convert.py b/src/petsys_util/convert.py index 83f317b..0313ba5 100755 --- a/src/petsys_util/convert.py +++ b/src/petsys_util/convert.py @@ -1,51 +1,58 @@ #!/usr/bin/env python - +from __future__ import print_function import os import argparse parser = argparse.ArgumentParser(description='convert raw data') parser.add_argument("--config", type=str, required=True, help="Configuration file") -parser.add_argument("-r", type=str, dest="run", required=True, help = "Run number") +parser.add_argument("-r", "--run", type=str, required=True, help="Run number") parser.add_argument("--mode", type=str, required=True, choices=["r", "s", "c", "e"], help = "reconstruction mode (singles, coincicences or event)") parser.add_argument("--refChannel", type=str, required=False, help = "reference channel") parser.add_argument("--pedestals", dest="pedestals", action="store_true", help="Enable the acquisition of pedestals") - +parser.add_argument("--data-dir", default="/storage/TOFHIR2", help="Directory to store raw and reco data") args = parser.parse_args() +if not os.path.exists(args.data_dir): + print("Error: data directory '%s' does not exist!" % args.data_dir) + print("Please rerun with --data-dir specifying where output data is") + +raw_prefix = os.path.join(args.data_dir,"raw",args.run) +reco_prefix = os.path.join(args.data_dir,"reco","%s" % args.run) + if args.mode == 'r': - command = "./convert_raw_to_raw --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+" -o /data/TOFHIR2/reco/run"+args.run+"_r.root" + command = "./convert_raw_to_raw --config %s -i %s -o %s_r.root" % (args.config, raw_prefix, reco_prefix) os.system(command) if args.mode == 's': - mainCommand = "./convert_raw_to_singles --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+" --writeRoot" + mainCommand = "./convert_raw_to_singles --config %s -i %s --writeRoot" % (args.config, raw_prefix) if args.pedestals: - command = "./convert_raw_to_singles --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+"_ped1 -o /data/TOFHIR2/reco/run"+args.run+"_ped1_s.root --writeRoot" + command = "./convert_raw_to_singles --config %s -i %s_ped1 -o %s_ped1_s.root --writeRoot" % (args.config, raw_prefix, reco_prefix) os.system(command) - command = "./convert_raw_to_singles --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+"_ped2 -o /data/TOFHIR2/reco/run"+args.run+"_ped2_s.root --writeRoot" + command = "./convert_raw_to_singles --config %s -i %s_ped2 -o %s_ped2_s.root --writeRoot" % (args.config, raw_prefix, reco_prefix) os.system(command) - command = "./analyze_pedestals.exe /data/TOFHIR2/reco/run"+args.run+"_ped1_s.root /data/TOFHIR2/reco/run"+args.run+"_ped2_s.root /data/TOFHIR2/reco/run"+args.run+"_pedestals.root" + command = "./analyze_pedestals.exe %s_ped1_s.root %s_ped2_s.root %s_pedestals.root" % (raw_prefix, raw_prefix, reco_prefix) os.system(command) - mainCommand += " --pedestals -o /data/TOFHIR2/reco/run"+args.run+"_ped_s.root" + mainCommand += " --pedestals -o %s_ped_s.root" % reco_prefix else: - mainCommand += " -o /data/TOFHIR2/reco/run"+args.run+"_s.root" + mainCommand += " -o %s_s.root" % reco_prefix os.system(mainCommand) if args.mode == 'c': - command = "./convert_raw_to_coincidence --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+" -o /data/TOFHIR2/reco/run"+args.run+"_c.root --writeRoot" + command = "./convert_raw_to_coincidence --config %s -i %s -o %s_c.root --writeRoot" % (args.config, raw_prefix, reco_prefix) os.system(command) if args.mode == 'e': - mainCommand = "./convert_raw_to_event --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+" --writeRoot" + mainCommand = "./convert_raw_to_event --config %s -i %s --writeRoot" % (args.config, raw_prefix) if args.pedestals: - command = "./convert_raw_to_singles --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+"_ped1 -o /data/TOFHIR2/reco/run"+args.run+"_ped1_s.root --writeRoot" + command = "./convert_raw_to_singles --config %s -i %s_ped1 -o %s_ped1_s.root --writeRoot" % (args.config, raw_prefix, reco_prefix) os.system(command) - command = "./convert_raw_to_singles --config "+args.config+" -i /data/TOFHIR2/raw/run"+args.run+"_ped2 -o /data/TOFHIR2/reco/run"+args.run+"_ped2_s.root --writeRoot" + command = "./convert_raw_to_singles --config %s -i %s_ped2 -o %s_ped2_s.root --writeRoot" % (args.config, raw_prefix, reco_prefix) os.system(command) - command = "./analyze_pedestals.exe /data/TOFHIR2/reco/run"+args.run+"_ped1_s.root /data/TOFHIR2/reco/run"+args.run+"_ped2_s.root /data/TOFHIR2/reco/run"+args.run+"_pedestals.root" + command = "./analyze_pedestals.exe %s_ped1_s.root %s_ped2_s.root %s_pedestals.root" % (raw_prefix, raw_prefix, reco_prefix) os.system(command) - mainCommand += " --pedestals -o /data/TOFHIR2/reco/run"+args.run+"_ped_e.root" + mainCommand += " --pedestals -o %s_ped_e.root" % reco_prefix else: - mainCommand += " -o /data/TOFHIR2/reco/run"+args.run+"_e.root" + mainCommand += " -o %s_e.root" % reco_prefix if args.refChannel : - mainCommand += " --refChannel "+args.refChannel + mainCommand += " --refChannel %s" % args.refChannel os.system(mainCommand) diff --git a/src/petsys_util/convert_raw_to_event.cpp b/src/petsys_util/convert_raw_to_event.cpp index 0d2a49f..d1cfae5 100644 --- a/src/petsys_util/convert_raw_to_event.cpp +++ b/src/petsys_util/convert_raw_to_event.cpp @@ -50,7 +50,7 @@ class DataFileWriter { long long brStepEnd; unsigned short brN; - int brChannelIdx[128]; + int brChannelIdx[256]; std::vector brTime; std::vector brChannelID; std::vector brToT; @@ -89,7 +89,7 @@ class DataFileWriter { if( pedestalFile != NULL ) { std::cout << "pedestals!" << std::endl; - for(int ch = 0; ch < 128; ++ch) + for(int ch = 0; ch < 256; ++ch) { TProfile* prof = (TProfile*)( pedestalFile->Get(Form("p_qfine_ch%d_2",ch)) ); if( !prof ) continue; @@ -113,7 +113,7 @@ class DataFileWriter { hData->Branch("prevEventTime", &brPrevEventTime, bs); hData->Branch("timeLast", &brTimeLast, bs); hData->Branch("mh_n", &brN, bs); - hData->Branch("channelIdx", brChannelIdx, "channelIdx[128]/I"); + hData->Branch("channelIdx", brChannelIdx, "channelIdx[256]/I"); hData->Branch("tot", &brToT); hData->Branch("t1coarse", &brT1Coarse); hData->Branch("t1fine", &brT1Fine); @@ -214,7 +214,7 @@ class DataFileWriter { brQT1.clear(); brQT2.clear(); brTacID.clear(); - for(unsigned int jj = 0; jj < 128; ++jj) brChannelIdx[jj] = -1; + for(unsigned int jj = 0; jj < 256; ++jj) brChannelIdx[jj] = -1; channelCount.clear(); brTimeLast = brTimeLastTmp; @@ -347,7 +347,7 @@ int main(int argc, char *argv[]) char *inputFilePrefix = NULL; char *outputFileName = NULL; FILE_TYPE fileType = FILE_TEXT; - int hitLimitToWrite = 128; + int hitLimitToWrite = 256; long long eventFractionToWrite = 1024; bool coincidence = false; int refChannel = -1; diff --git a/src/petsys_util/create_ALDO_calibration_combined.py b/src/petsys_util/create_ALDO_calibration_combined.py new file mode 100755 index 0000000..4c9bfeb --- /dev/null +++ b/src/petsys_util/create_ALDO_calibration_combined.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +import argparse +import os + +if __name__ == '__main__': + parser = argparse.ArgumentParser("script to combine aldo config files") + parser.add_argument("input_filenames", nargs="+", help="input filenames") + parser.add_argument("--dest-dir", default='.', help="destination directory") + args = parser.parse_args() + + output_filenames = set() + + map_input = {} + for filename in args.input_filenames: + head, tail = os.path.split(filename) + root, ext = os.path.splitext(tail) + print(root) + asic = int(root.split('_')[2][-1]) + aldo = root.split('_')[-2] + rang = root.split('_')[-1] + + output = os.path.join(args.dest_dir,'aldo_scan_ALDO_%s_%s.tsv' % (aldo,rang)) + + if output in output_filenames: + print("appending to %s" % output) + else: + print("writing to %s" % output) + + with open(output,"a" if output in output_filenames else "w") as out: + with open(filename, 'r') as f: + for line in f: + readings = line.split() + line_out = '0\t0\t%d\t%3d\t%f\n' %(asic,int(readings[0]),float(readings[1])) + out.write(line_out) + + output_filenames.update((output,)) diff --git a/src/petsys_util/scan_aldo_hv b/src/petsys_util/scan_aldo_hv new file mode 100755 index 0000000..50aee88 --- /dev/null +++ b/src/petsys_util/scan_aldo_hv @@ -0,0 +1,173 @@ +#!/usr/bin/env python +from __future__ import print_function +import sys +from petsys import daqd, config +from copy import deepcopy +import argparse +#import serial +from time import sleep +from os.path import expanduser, join +import os + +# Try to guess where the Lab5015Utils directory is +sys.path.append(join(os.path.dirname(os.path.abspath(__file__)),"../..","Lab5015Utils")) +try: + from Lab5015_utils import Keithley2450 +except ImportError as e: + print("Error: unable to import from Lab5015_utils!") + print(e) + print("Maybe you need to add the directory to your PYTHONPATH environment variable?") + print("Example: $ export PYTHONPATH=/path/to/Lab5015_utils") + sys.exit(1) + +try: + from Lab5015_utils import Agilent3606A +except ImportError as e: + print("Unable to import Agilent3606A from Lab5015_utils. Skipping...") + +try: + from Lab5015_utils import KeithleyDMM6500 +except ImportError as e: + print("Unable to import KeithleyDMM6500 from Lab5015_utils. Skipping...") + + +keyChannels = { + (0,"A") : 3, + (0,"B") : 4, + #(2,"A") : 7, + #(2,"B") : 8 +} + +asics = [i[0] for i in keyChannels.keys()] +asics = list(set(asics)) + +def main(argv): + + parser = argparse.ArgumentParser(description='Acquire data for ALDO calibration') + parser.add_argument("--config", type=str, required=True, help="Configuration file") + parser.add_argument("-o", type=str, dest="fileNamePrefix", required=True, help="Data filename (prefix)") + parser.add_argument("--keithley-model", type=int, choices=[2450,6500,3606], default=6500, help="Keithley model number (2450, 6500, or 3606 (3606 is actually Agilent))") + parser.add_argument("--keithley-ip-address", type=str, default=None, help="Keithley IP address") + args = parser.parse_args() + + mask = config.LOAD_ALL + mask ^= config.LOAD_QDCMODE_MAP + mask ^= config.LOAD_BIAS_SETTINGS_ALDO + mask ^= config.LOAD_ALDO_CALIBRATION + mask ^= config.LOAD_MAP + systemConfig = config.ConfigFromFile(args.config, loadMask=mask) + + if args.keithley_model in [2450, 6500]: + if args.keithley_ip_address is None: + ip_address_file = join(expanduser("~"),".keithley_ip_address.txt") + + if os.path.exists(ip_address_file): + with open(ip_address_file) as f: + args.keithley_ip_address = f.read().strip() + else: + print("Must supply Keithley IP address! You can find it by going to settings and then communication") + sys.exit(1) + else: + ip_address_file = join(expanduser("~"),".keithley_ip_address.txt") + with open(ip_address_file,"w") as f: + f.write(args.keithley_ip_address) + + portname = 'TCPIP0::%s::INSTR' % args.keithley_ip_address + print("Connecting to Keithley at ip address '%s'" % args.keithley_ip_address) + print("To change this IP address either edit ~/.keithley_ip_address.txt or remove that file and you will be prompted next time to enter it.") + + if args.keithley_model == 2450: + mykey = Keithley2450(portname) + elif args.keithley_model == 3606: + mykey = Agilent3606A() + else: + mykey = KeithleyDMM6500(portname) + + conn = daqd.Connection() + conn.initializeSystem() + systemConfig.loadToHardware(conn, bias_enable=config.APPLY_BIAS_ON, hw_trigger_enable=False, qdc_mode = "tot") + activeAsics = conn.getActiveAsics() + + # hvdac_config = conn.get_hvdac_config() + # + # for portID, slaveID, railID in hvdac_config.keys(): + # hvdac_config[(portID, slaveID, railID)] = systemConfig.mapBiasChannelVoltageToDAC((portID, slaveID, railID), 46) + # + # conn.set_hvdac_config(hvdac_config) + + + asicsConfig = conn.getAsicsConfig() + for ac in asicsConfig.values(): + gc = ac.globalConfig + gc.setValue("c_aldo_en", 0b00) + gc.setValue("c_aldo_range", 0b00) + + #aldo_dac_gain = 0 + #gc.setValue("Valdo_A_Gain", aldo_dac_gain) + #gc.setValue("Valdo_A_DAC", 255) + #gc.setValue("Valdo_B_Gain", aldo_dac_gain) + #gc.setValue("Valdo_B_DAC", 255) + + conn.setAsicsConfig(asicsConfig) + + asicsConfig0 = deepcopy(asicsConfig) + for portID, slaveID, chipID in activeAsics: + + if (chipID%2) != 0: + continue + + ac = asicsConfig0[(portID, slaveID, chipID)] + + for which_aldo in ['A', 'B']: + #for which_aldo in ['A']: + print("Connect to ALDO %s" % which_aldo) + raw_input("Press ENTER to continue") + + if args.keithley_model == 6500: + mykey.closeChannel(keyChannels[(chipID,which_aldo)]) + + for aldo_range in [ "low", "high" ]: + + f = open("%s_ASIC%d_ALDO_%s_%s.tsv" % (args.fileNamePrefix, chipID, which_aldo, aldo_range), "w") + print("%s_ASIC%d_ALDO_%s_%s.tsv" % (args.fileNamePrefix, chipID, which_aldo, aldo_range)) + asicsConfig = deepcopy(asicsConfig0) + gc = (asicsConfig[(portID, slaveID, chipID)]).globalConfig + for dac in range(0, 256, 1): + gc.setValue("Valdo_%s_DAC" % which_aldo, dac) + if aldo_range == "low": + gc.setValue("Valdo_%s_Gain" % which_aldo, 0) + elif aldo_range == "high": + gc.setValue("Valdo_%s_Gain" % which_aldo, 1) + else: + raise "aldo range has bad value %s" % aldo_range + if which_aldo == 'A': + gc.setValue("c_aldo_en", 0b10) + elif which_aldo == 'B': + gc.setValue("c_aldo_en", 0b01) + conn.setAsicsConfig(asicsConfig) + if dac is 0: + sleep(2.) + else: + sleep(0.2) + + if args.keithley_model == 2450: + _, voltage = mykey.meas_V() + elif args.keithley_model == 3606: + voltage = mykey.meas_V() + else: + voltage = mykey.read() + print(which_aldo, dac, float(voltage)) + f.write("%d\t%f\n" % (dac, float(voltage))) + f.close() + + + asicsConfig = conn.getAsicsConfig() + for ac in asicsConfig.values(): + gc = ac.globalConfig + gc.setValue("c_aldo_en", 0b00) + gc.setValue("c_aldo_range", 0b00) + conn.setAsicsConfig(asicsConfig) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/src/raw_data/RawReader.cpp b/src/raw_data/RawReader.cpp index 8d59fd2..36423c9 100644 --- a/src/raw_data/RawReader.cpp +++ b/src/raw_data/RawReader.cpp @@ -288,8 +288,8 @@ void RawReader::processStep(int n, bool verbose, EventSink *sink) long long tq = (t1 & 0x7FFFFFFFFFFFFC00LL) | eventWord.getQCoarse(); long long tp = (t1 & 0x7FFFFFFFFFFFF000LL) | (eventWord.getPrevEventTime() << 2); - if(t2 < t1) t2 += 1024; - if(tq < t1) tq += 1024; + if((t2+2) < t1) t2 += 1024; + if((tq+2) < t1) tq += 1024; if(tp >= t1) tp -= 4096; e.time = t1 - (currentBufferFirstFrame * 1024);