#!/bin/env python3 # written 2019-01-28 by mza # last updated 2023-09-26 by mza import threading # Thread() from math import * from B2L_common import * from B2L_defs import * from get_status import get_status import ethudp from DebugInfoWarningError import debug, info, warning, error, debug2, debug3, set_verbosity import time # sleep() import struct # unpack_from import pytz # pytz - sudo apt install -y python-pip; sudo pip2 install pytz #import datetime import matplotlib.dates as mdates # sudo pip2 install matplotlib from mpl_toolkits.axes_grid1.inset_locator import inset_axes from math import ceil # sudo apt install -y python-pip python3-pip python-tk # python -m pip install --user -U pip # python -m pip install --user -U matplotlib # python -m pip install --user -U scipy import matplotlib.pyplot as plt # sudo apt install -y python-cairocffi import matplotlib.gridspec as gridspec #import matplotlib.image as mpl_img from matplotlib.ticker import (MultipleLocator, FormatStrFormatter, AutoMinorLocator) import numpy import tkinter # sudo apt install -y python3-tk from PIL import Image, ImageTk # sudo apt-get install -y python3-pil.imagetk def print_ROOT_usage(): print("ROOT environment not setup yet") HOME = os.environ['HOME'] potential_locations = [ "/usr/local/bin", HOME + "/build/root/bin" ] filename = "thisroot.sh" for location in potential_locations: potential_filename = location + "/" + filename if os.path.isfile(potential_filename): #print(". " + HOME + "/build/root/bin/thisroot.sh; " + str(sys.argv)) print(". " + potential_filename) #info(sys.argv[0] + sys.argv[1:]) #info(" ".join(sys.argv[0:])) sys.exit(1) try: import ROOT # TH1F info("using ROOT") should_use_ROOT = True except: should_use_ROOT = False info("not using ROOT") #print_ROOT_usage() #ROOT.gROOT.SetBatch(True) BS = 0 frame_mask_shift = 16 frame_mask_all = 0b111111111 << frame_mask_shift bunch_marker_first_valid = 4 initial_bunch_marker_of_interest = 1701 desired_RF_bucket = initial_bunch_marker_of_interest RF_buckets = 5120 bunch_marker_last_valid = RF_buckets - 1 #number_of_64_sample_windows_per_beam_orbit = 427 pedestal_subtraction_amount = 1000 stagger_amount = 50 ch_adc_min = 0 - 300 ch_adc_max = 128 * stagger_amount + 300 maximum_absolute_value_before_issuing_warning = 1000 slice_lower_limit = -250 slice_upper_limit = 300 should_plot_slice = 0 #should_plot_sweep = 1 #should_plot_zoomed_waveforms = 1 #number_of_zoomed_waveforms_to_plot = 4 should_generate_png = 1 should_generate_pdf = 0 gui_update_period_ms = 200 linewidth = 0.3 dpi = 100.0 duration_in_ns_of_64_sample_waveform = 23.58 desired_x_axis = "time" desired_physical_window_numbers = [ w for w in range(425) ] starting_physical_window_number = 0 ending_physical_window_number = starting_physical_window_number + 425 revolution_marker_offset_in_RF_buckets = 4370.5 bunch_current_offset = -260.0 bunch_current_scale = 350.0 current_gridstep = 200.0 # in mA nbunches_gridstep = 400 def set_trigger_mask(s, c0, c1, c2, c3): write_register(SCROD_AxiCommon_trigMask, s, BS) write_register(CARRIER_AxiCommon_trigMask, c0, BS, 0) write_register(CARRIER_AxiCommon_trigMask, c1, BS, 1) write_register(CARRIER_AxiCommon_trigMask, c2, BS, 2) write_register(CARRIER_AxiCommon_trigMask, c3, BS, 3) def mask_triggers(s=0xf, c0=0xf, c1=0xf, c2=0xf, c3=0xf): set_trigger_mask(s, c0, c1, c2, c3) def unmask_triggers(s=0, c0=0, c1=0, c2=0, c3=0): set_trigger_mask(s, c0, c1, c2, c3) def set_trig_prescale_N_log2(N_log2): write_register(SCROD_AxiCommon_trig_prescale_N_log2, N_log2, BS) def get_xrm_trigger_enable_status(): return read_register(SCROD_AxiCommon_xrm_trigger_enabled, BS) def enable_xrm_triggers(): write_register(SCROD_AxiCommon_xrm_trigger_enabled, 1, BS) def disable_xrm_triggers(): write_register(SCROD_AxiCommon_xrm_trigger_enabled, 0, BS) def allow_xrm_triggers_for_a_while(duration=1.0): if be_verbose_when_collecting_data: info("allowing xrm triggers for " + str(int(1000.0*duration)/1000.0) + " seconds...") a = get_SCROD_eventCnt() enable_xrm_triggers() time.sleep(duration) disable_xrm_triggers() b = get_SCROD_eventCnt() diff = b - a info("eventCnt difference: " + str(diff)) return diff def trigger_and_wait_for_xrm_triggers(duration=1.0): # if be_verbose_when_collecting_data: # info("allowing xrm triggers for " + str(int(1000.0*duration)/1000.0) + " seconds...") a = get_SCROD_eventCnt() if should_software_trigger: software_trigger(BS) else: write_register_without_readback_verification(SCROD_AxiCommon_clear_count_of_triggers_for_bunch_markers, 0xf, BS) wait_at_least_until_next_frame9() time.sleep(duration) b = get_SCROD_eventCnt() diff = b - a info("eventCnt difference: " + str(diff)) return diff expected_trigger_rate = { 0:11150.0, 1:5560.0, 2:2780.0, 3:1390.0, 4:690.0, 5:350.0, 6:170.0, 7:90.0, 8:40.0, 9:20.0, 10:10.0, 11:5.0, 12:2.0, 13:1.0, 14:1.0, 15:1.0, 16:1.0, 17:1.0, 18:1.0 } def generate_histogram_of_trigger_rate_versus_prescale_N_log2(start, end): global expected_trigger_rate old_desired_trigger_quantities = set_desired_trigger_quantities(0, 0, 0, 0) mask_triggers() #max_rate = 151000.0 for i in range(start, end+1): set_trig_prescale_N_log2(i) #duration = 40.0 * (2.0**i) / max_rate duration = 0.1 #info(duration) if i > 10: duration = 1.0 diff = allow_xrm_triggers_for_a_while(duration) #info(str(diff)) rate = diff / duration expected_trigger_rate[i] = rate info("[" + str(i) + "]: " + str(rate)) set_desired_trigger_quantities(old_desired_trigger_quantities[0], old_desired_trigger_quantities[1], old_desired_trigger_quantities[2], old_desired_trigger_quantities[3]) def get_SCROD_eventCnt(should_show_it=0): SCROD_eventCnt = read_register(SCROD_AxiCommon_eventCnt, BS) if should_show_it: info("SCROD_eventCnt: " + str(SCROD_eventCnt)) return SCROD_eventCnt def get_carrier_eventCnts(should_show_them=0): if 5==number_of_carriers[BS] or 0==number_of_carriers[BS]: return eventCnt = [] if 1 <= number_of_carriers[BS]: carrier0_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 0) eventCnt.append(carrier0_eventCnt) if should_show_them: info("carrier0_eventCnt: " + str(carrier0_eventCnt)) if 2 <= number_of_carriers[BS]: carrier1_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 1) eventCnt.append(carrier1_eventCnt) if should_show_them: info("carrier1_eventCnt: " + str(carrier1_eventCnt)) if 3 <= number_of_carriers[BS]: carrier2_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 2) eventCnt.append(carrier2_eventCnt) if should_show_them: info("carrier2_eventCnt: " + str(carrier2_eventCnt)) if 4 <= number_of_carriers[BS]: carrier3_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 3) eventCnt.append(carrier3_eventCnt) if should_show_them: info("carrier3_eventCnt: " + str(carrier3_eventCnt)) return eventCnt def set_desired_trigger_quantities(a, b, c, d): old_a = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_a, BS) old_b = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_b, BS) old_c = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_c, BS) old_d = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_d, BS) write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_a, a, BS) write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_b, b, BS) write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_c, c, BS) write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_d, d, BS) return old_a, old_b, old_c, old_d def calculate_parameters(SST_clock_divide_ratio=6, should_print_info=0): # 5120 / 4 = 1280 FTSW clocks per frame # 5120 buckets / 508.8875 MHz = 10.0611628307 us per frame # # 127.221875 MHz / 6 = 21.203645833 MHz # 128 samples per write window * 21.203645833 MHz SST = 2714.066666 MHz sampling rate # 1/21.203645833 MHz = 47.1617007689 ns per write window # 10.0611628307 us / 47.1617007689 ns = 213.333333 write windows per revolution # 5120 / 213.333333 = 24.0 bunches per window # 6.0 FTSW bunches per window # # 127.221875 MHz / 8 = 15.902734375 MHz # 128 samples per write window * 15.902734375 MHz SST = 2035.55 MHz sampling rate # 1/15.902734375 MHz = 62.882268 ns per write window # 10.0611628307 us / 62.882268 ns = 160 write windows per revolution # 5120 / 160 = 32.0 bunches per window # 8.0 FTSW bunches per window global RF_clock_Hz RF_clock_Hz = 508.8875e6 global period_of_RF_clock_ns period_of_RF_clock_ns = 1.0e9 / RF_clock_Hz global asic_samples_per_write_window asic_samples_per_write_window = 128 global asic_samples_per_read_window asic_samples_per_read_window = asic_samples_per_write_window // 2 global FTSW_clock_divide_ratio FTSW_clock_divide_ratio = 4 global revolution_duration_s revolution_duration_s = RF_buckets / RF_clock_Hz global SST_clock_Hz SST_clock_Hz = RF_clock_Hz / FTSW_clock_divide_ratio / SST_clock_divide_ratio global sampling_rate_Hz sampling_rate_Hz = SST_clock_Hz * asic_samples_per_write_window global write_window_duration_s write_window_duration_s = 1.0 / SST_clock_Hz global read_window_duration_s read_window_duration_s = write_window_duration_s / 2.0 global write_windows_per_revolution write_windows_per_revolution = revolution_duration_s / write_window_duration_s global read_windows_per_revolution read_windows_per_revolution = revolution_duration_s / read_window_duration_s global RF_buckets_per_write_window RF_buckets_per_write_window = RF_buckets // write_windows_per_revolution global RF_buckets_per_read_window RF_buckets_per_read_window = RF_buckets // read_windows_per_revolution global FTSW_clocks_per_write_window FTSW_clocks_per_write_window = RF_buckets_per_write_window // FTSW_clock_divide_ratio global FTSW_clocks_per_read_window FTSW_clocks_per_read_window = RF_buckets_per_read_window // FTSW_clock_divide_ratio global asic_samples_per_RF_bucket asic_samples_per_RF_bucket = asic_samples_per_read_window // RF_buckets_per_read_window global total_number_of_physical_windows total_number_of_physical_windows = 512 if should_print_info: info("revolution_duration_us: " + str(revolution_duration_s*1.0e6)) info("SST_clock_MHz: " + str(SST_clock_Hz/1.0e6)) info("sampling_rate_GHz: " + str(sampling_rate_Hz/1.0e9)) info("write_window_duration_ns : " + str(write_window_duration_s*1.0e9)) info("read_window_duration_ns : " + str(read_window_duration_s*1.0e9)) info("write_windows_per_revolution: " + str(write_windows_per_revolution)) info("read_windows_per_revolution: " + str(read_windows_per_revolution)) info("RF_buckets_per_write_window: " + str(RF_buckets_per_write_window)) info("RF_buckets_per_read_window: " + str(RF_buckets_per_read_window)) info("FTSW_clocks_per_write_window: " + str(FTSW_clocks_per_write_window)) info("FTSW_clocks_per_read_window: " + str(FTSW_clocks_per_read_window)) def show_xrm_trigger_enable_status(): en = read_register(SCROD_AxiCommon_xrm_trigger_enabled, BS) info("xrm trigger enabled: " + str(en)) def show_relevant_registers(): #get_SCROD_eventCnt(1) #get_carrier_eventCnts(1) show_frame_masks() nlog2 = read_register(SCROD_AxiCommon_trig_prescale_N_log2, BS) info("N_log2 prescale: " + str(nlog2)) show_xrm_trigger_enable_status() show_asic_timeouts(BS) show_SEM_status(BS) def show_some_info(): info("") show_current_time() show_asic_timeouts(BS) get_SCROD_eventCnt(1) get_carrier_eventCnts(1) show_relevant_registers() #show_scalers(BS) #get_status(BS) # https://stackoverflow.com/a/1158096/5728815 def touch(filename): if os.path.exists(filename): os.utime(filename, None) else: open(filename, 'a').close() def get_mtime(filename): return os.stat(filename).st_mtime def set_mtime(destination, source): reftime = get_mtime(source) os.utime(destination, (reftime, reftime)) newtime = get_mtime(destination) #info(hex(reftime)) #info(hex(newtime)) # from https://matplotlib.org/3.1.1/gallery/text_labels_and_annotations/date.html def plot_beam_conditions(x, current, nbunches, xcenter=0, xwidth=10800): #global fig3 global axes3 global axes4 # try: # axes3 # except: #fig3 = plt.figure(figsize=(3.0, 1.0)) #fig3.tight_layout(pad=2) # if not already_plotted: # axes3 = fig.add_subplot(1, 1, 1) # else: if already_plotted: axes3.clear() #axes4.clear() axes4 = axes3.twinx() axes3.set_autoscaley_on(False) axes4.set_autoscaley_on(False) #axes3.set_ylim([129, -2]) if 0==xcenter: xcenter = datetime.datetime.strptime(timestring, "%Y-%m-%d.%H%M%S") #xcenter = datetime.datetime(2019, 11, 15, 8, 45) #info(str(xcenter)) xcenter = mdates.date2num(xcenter) #info(str(xcenter)) xcenter = mdates.num2epoch(xcenter) #info(str(xcenter)) x0 = xcenter - xwidth / 2.0 x1 = xcenter + xwidth / 2.0 #info("x:[" + str(x0) + "," + str(xcenter) + "," + str(x1) + "]") i0 = 0 i1 = 0 for i in range(len(x)): # find start and end indices if 0==i0: if x0 [ [5, 1], [0, 11], [4, 1], [0, 11], [4, 1], [0, 13] ] rle = [] current_value = -1 old_value = -1 current_count = 0 if len(numbers): for i in range(len(numbers)): current_value = numbers[i] if 0==i: old_value = current_value if old_value==current_value: current_count += 1 else: rle.append([old_value, current_count]) old_value = current_value current_count = 1 rle.append([old_value, current_count]) string = dec(0, 5) + ": " count = 0 i = 0 for kv in rle: k, v = kv count += v i += v string += "[" + str(k) + "," + str(v) + "]," if 11>2): try: w = struct.unpack_from("I", chunk, offset) offset += 4 yield w[0] except: break else: break def open_datafile_for_reading(): global datafile global datafile_event_number if datafile is None: datafile = open(datafilename, "rb") datafile_event_number = 0 # else: # error("datafile already open") # info(str(datafile.tell())) # sys.exit(2) def open_waveformfile_for_reading(): global waveformfile global waveformfile_event_number global waveformfile_waveform_number if waveformfile is None: waveformfile = open(waveformfilename, "rb") waveformfile_event_number = 0 waveformfile_waveform_number = 0 # else: # error("waveform file already open") # info(str(waveformfile.tell())) # sys.exit(3) #waveformfile.seek(0) def open_roottreefile_for_writing(): if not should_use_ROOT: return global roottree_events global roottree_waveforms global roottreefile #global roottreefile_event_number #global roottreefile_waveform_number try: if roottreefile is None: info("writing root tree file " + roottreefilename + " ...") roottreefile = ROOT.TFile(roottreefilename, "recreate") roottree_events = ROOT.TTree("events", "events") roottree_waveforms = ROOT.TTree("waveforms", "waveforms") #info("root tree file " + roottreefilename + " opened for writing ...") except: error("can't open roottreefile for writing") sys.exit(4) #roottreefile_event_number = 0 #roottreefile_waveform_number = 0 # else: # info(str(waveformfile.tell())) #waveformfile.seek(0) roottreefilename = "" def open_roottreefile_for_reading(): if not should_use_ROOT: return if ""==roottreefilename: return #info("opening root file") #info("attempting to parse root file...") roottreefile = ROOT.TFile(roottreefilename) roottree_events = roottreefile.Get("events") #roottree_waveforms.Show() #roottree_events.Print() #roottree_waveforms.Print() #roottree_waveforms.Scan("waveform") event_index = 0 #wfb = roottree_waveforms.GetBranch("waveform") # wfn = roottree_waveforms.GetBranch("waveform_number") if False: for event in roottree_events: event_index += 1 event_number = event.event_number scrod_id = event.scrod_id phase = event.phase ctime = event.ctime count_since_revo9 = event.count_since_revo9 eventQueueDepth = event.eventQueueDepth eventNumberByte = event.eventNumberByte masks = event.masks info("event_index: " + str(event_index)) info("event_number: " + str(event_number)) info("scrod_id: " + str(scrod_id)) info("phase: " + str(phase)) info("ctime: " + str(ctime)) info("count_since_revo9: " + str(count_since_revo9)) info("eventQueueDepth: " + str(eventQueueDepth)) info("eventNumberByte: " + str(eventNumberByte)) info("masks: " + hex(masks, 4)) roottree_waveforms = roottreefile.Get("waveforms") waveform_index = 0 num_errors_total = 0 for waveform in roottree_waveforms: waveform_index += 1 num_errors_for_this_index = 0 event_number = waveform.event_number waveform_number = waveform.waveform_number starting_sample = waveform.starting_sample if not 32==starting_sample and not 0==starting_sample: #error("found starting_sample " + str(starting_sample)) num_errors_for_this_index += 1 logical_window = waveform.logical_window if 511Draw("waveform:lin_ch:physical_window", "344<=physical_window && physical_window<=375"); # events->Draw("event_number:count_since_revo9"); #info("done parsing root file") def close_datafile_for_reading(): global datafile if datafile is not None: datafile.close() datafile = None def close_waveformfile_for_reading(): global waveformfile if waveformfile is not None: waveformfile.close() waveformfile = None roottreefile = None def close_roottreefile_for_writing(): if not should_use_ROOT: return global roottreefile if roottreefile is not None: #info("closing root file") roottreefile.Write() roottreefile.Close() roottreefile = None def words_from_file(f, chunksize=16384): total_yield = 0 # seek = 0 while True: try: chunk = f.read(chunksize) except: error("can't read from file") break offset = 0 if chunk: #for w in struct.iter_unpack("I", chunk): for i in range(chunksize>>2): try: (w,) = struct.unpack_from("I", chunk, offset) offset += 4 total_yield += 1 yield w except GeneratorExit: #info("breaking at line 463") close_waveformfile_for_reading() return except: break else: # time.sleep(1) # info("waiting...") break # seek += offset #info("reached end of file at " + str(f.tell())) # total_yield -= 4 #info("yielded " + str(total_yield) + " words") #info("yielded " + str(4*total_yield) + " bytes") #yield 0x12345678 def parse_datafile_and_dump_waveforms_to(outfilename): #string = 'hexdump datafile -e \'5/4 \"%08X \"\' -e \'\"\\n\"\'' #info(string) #response = commands.getstatusoutput(string) #info(response[1]) #info("") if be_verbose_when_collecting_data: string = "# t v scr x bonu p cor s cti rev9 mask qu ## " debug(string) # i is word number from Belle 2 TOP data format (production data format 4.1) # j is the number of core words remaining # k is the number of bonus words remaining # n is count of the events in the file so far j = 0 k = 0 i = 999999 global datafile_event_number open_datafile_for_reading() outfile = open(outfilename, "ab") debug_string = "" debug2_string = "" # old_verbosity = set_verbosity(4) just_finished_hits = 0 if should_write_root_tree: # array.array types: B=u8 h=s16 H=u16 L=u32 root_datafile_event_number = array.array('L', [0]) root_scrod_id = array.array('H', [0]) root_phase = array.array('H', [0]) root_ctime = array.array('H', [0]) root_count_since_revo9 = array.array('H', [0]) root_eventQueueDepth = array.array('H', [0]) root_eventNumberByte = array.array('H', [0]) root_masks = array.array('H', [0]) # root types: b=u8 S=s16 s=u16 i=u32 roottree_events.Branch("event_number", root_datafile_event_number, "event_number/I") roottree_events.Branch("scrod_id", root_scrod_id, "scrod_id/s") roottree_events.Branch("phase", root_phase, "phase/s") roottree_events.Branch("ctime", root_ctime, "ctime/s") roottree_events.Branch("count_since_revo9", root_count_since_revo9, "count_since_revo9/s") roottree_events.Branch("eventQueueDepth", root_eventQueueDepth, "eventQueueDepth/s") roottree_events.Branch("eventNumberByte", root_eventNumberByte, "eventNumberByte/s") roottree_events.Branch("masks", root_masks, "masks/s") waveform = [] for w in words_from_file(datafile): i += 1 if 0==j and 0==k and 4==(w>>24) and 1==((w>>16)&0xff): i = 0 #outfile.flush() if 0!=datafile_event_number: if be_verbose_when_collecting_data: debug(debug_string, 0) debug2(debug2_string, 0) datafile_event_number += 1 debug_string = str(datafile_event_number) + " " debug2_string = "" if 0==i: packet_type = w>>24 packet_version = (w>>16)&0xff should_be_a = (w>>12)&0xf scrod_id = w&0xfff debug_string += hex(packet_type, 1) + " " + hex(packet_version, 1) + " " + hex(scrod_id, 3) + " " elif 1==i: extra = w>>29 bonus = (w>>16) & 0x1fff k = bonus phase = (w>>12) & 0xf core = w & 0xfff j = core - 5 # core words includes the overall event header debug_string += hex(extra, 1) + " " + hex(bonus, 4) + " " + hex(phase, 1) + " " + hex(core, 3) + " " elif 2==i: skipped = w>>31 should_be_zeroes = (w>>27) & 0xf ctime = (w>>16) & 0x7ff count_since_revo9 = w & 0xffff debug_string += hex(skipped, 1) + " " + hex(ctime, 3) + " " + hex(count_since_revo9, 4) + " " elif 3==i: masks = w>>16 eventQueueDepth = (w>>8) & 0xff eventNumberByte = w & 0xff debug_string += hex(masks, 4) + " " + hex(eventQueueDepth, 2) + " " + hex(eventNumberByte, 2) + " " else: # done with header, go on to hits (interleaved with waveforms if present) should_be_b = (w>>12) & 0xf #if 0xb==should_be_b: # debug2_string += "\n [" + str(j) + "," + str(k) + "] " + hex(w, 8) + " " if 0>30) & 0x3 asic = (w>>28) & 0x3 channel = (w>>25) & 0x7 window = (w>>16) & 0x1ff waveform_present = (w>>7) & 1 if waveform_present: waveform_present_string = "w" else: waveform_present_string = "-" if 0xb==should_be_b: debug2_string += "\n [" + str(j) + "," + str(k) + "] " #debug2_string += hex(w, 8) + " " debug2_string += hex(carrier, 1) + " " + hex(asic, 1) + " " + hex(channel, 1) + " " + hex(window, 3) + " " + waveform_present_string + " " #else: # debug2_string += "\n error parsing hit " j -= 1 elif 4==(j%5): j -= 1 elif 3==(j%5): j -= 1 elif 2==(j%5): j -= 1 elif 1==(j%5): j -= 1 just_finished_hits = 1 else: if just_finished_hits: just_finished_hits = 0 should_be_5 = (w>>9) & 0x7 if 0x5!=should_be_5: debug2_string += "error " else: # now checkout the waveforms if present if 0>16 if (1<<15) & one: one -= 1<<16 zero = w & 0xffff if (1<<15) & zero: zero -= 1<<16 #debug2_string += str(zero) + "," + str(one) + " " #debug2_string += hex(zero) + "," + hex(one) + " " #yield zero #yield one waveform[2*k] = zero waveform[2*k+1] = one k += 1 #if 15==k: # info("k=15") #if 16==k: # info("k=16") elif "parsing_header"==mode and found_valid_first_word: #second += 1 should_be_1_zero_another_one_though = w>>31 starting_sample = (w>>25) & 0x3f logical_window = (w>>16) & 0x1ff carrier_event_number_lsbs = (w>>9) & 0x7f physical_window = w & 0x1ff if 0==should_be_1_zero_another_one_though and logical_window==physical_window and (0==starting_sample or 0x20==starting_sample): found_valid_second_word = 1 debug_string += hex(carrier_event_number_lsbs, 2) + " " debug_string += hex(logical_window, 3) + " " debug_string += hex(physical_window, 3) + " " debug_string += hex(starting_sample, 2) + " " if be_verbose_when_collecting_data: debug(debug_string) debug_string = "" waveform = zero_waveform(waveform) k = 0 mode = "yielding_data" else: debug_string += "\nerror finding second word " + hex(w, 8) mode = "looking_for_start_of_header" elif "looking_for_start_of_header"==mode: #first += 1 k = 0 found_valid_first_word = 0 found_valid_second_word = 0 n_samples = w>>16 should_be_5_zeroes = (w>>11) & 0x1f n_windows = (w>>8) & 0x7 should_be_1_zero = (w>>7) & 1 carrier = (w>>5) & 0x3 asic = (w>>3) & 0x3 channel = w & 0x7 if 0==should_be_5_zeroes and 0==should_be_1_zero and 0x20==n_samples: found_valid_first_word = 1 waveformfile_waveform_number += 1 #info("working on the " + str(waveformfile_waveform_number) + "th waveform in the file") debug_string = str(waveformfile_waveform_number) + ": " debug_string += hex(carrier, 1) + " " debug_string += hex(asic, 1) + " " debug_string += hex(channel, 1) + " " debug_string += hex(n_samples, 2) + " " debug_string += hex(n_windows, 1) + " " mode = "parsing_header" else: debug_string += "\nerror finding first word " + hex(w, 8) mode = "looking_for_start_of_header" if number_of_waveform_words_in_a_waveform_packet==k: mode = "looking_for_start_of_header" #info("on the " + str(waveformfile_waveform_number) + "th waveform in the file") yield (carrier_event_number_lsbs, carrier, asic, channel, physical_window, logical_window, n_windows, starting_sample, n_samples, waveform.tolist()) if should_write_root_tree: root_waveformfile_event_number[0] = waveformfile_event_number root_waveformfile_waveform_number[0] = waveformfile_waveform_number root_carrier_event_number_lsbs[0] = carrier_event_number_lsbs root_carrier[0] = carrier root_asic[0] = asic root_channel[0] = channel root_lin_ch[0] = xrm_map_cac_to_linear(carrier, asic, channel) root_n_samples[0] = n_samples root_n_windows[0] = n_windows root_starting_sample[0] = starting_sample root_logical_window[0] = logical_window root_physical_window[0] = physical_window #if 0==carrier and 2==asic and 7==channel and 234==physical_window and 32==starting_sample: if False and 10000==waveformfile_waveform_number: string = "" for i in range(len(waveform)): string += "," + dec(waveform[i], 3) #info(dec(i, 2) + " " + dec(waveform[i])) info(string) # #a1 = numpy.reshape(waveform, (4,8)) # #info(str(a1)) roottree_waveforms.Fill() debug("filling roottree_waveforms #" + str(waveformfile_event_number) + " with #" + str(waveformfile_waveform_number)) k = 0 waveform = zero_waveform(waveform) #info("k=" + str(k)) #info("first=" + str(first)) #info("second=" + str(second)) #info("yielding=" + str(yielding)) #info("did_this=" + str(did_this)) if be_verbose_when_collecting_data: if len(debug_string): debug(debug_string) # if len(array): # #info("len(array)=" + str(len(array))) # info("on the " + str(waveformfile_waveform_number) + "th waveform in the file") #yield (carrier_event_number_lsbs, carrier, asic, channel, physical_window, logical_window, n_windows, starting_sample, n_samples, array) #debug2(debug2_string) #info("words=" + str(words)) #set_verbosity(old_verbosity) def events_from_waveformfile(): event = [] array = [] previous_carrier_event_number_lsbs = 123456789 # dummy much bigger than a real carrier event number if be_verbose_when_collecting_data: debug(" ce c a c phy log w st sa") #old_verbosity = set_verbosity(5) global waveformfile_event_number for waveform in waveforms_from_waveformfile(): carrier_event_number_lsbs, carrier, asic, channel, physical_window, logical_window, n_windows, starting_sample, n_samples, array = waveform if 0==carrier and 0==asic and (0==channel or 1==channel): debug2(" " + hex(carrier_event_number_lsbs, 2) + " " + hex(carrier, 1) + " " + hex(asic, 1) + " " + hex(channel, 1) + " " + hex(physical_window, 3) + " " + hex(logical_window, 3) + " " + hex(n_windows, 1) + " " + hex(starting_sample, 2) + " " + hex(n_samples, 2)) if previous_carrier_event_number_lsbs!=carrier_event_number_lsbs: debug("previous_carrier_event_number_lsbs!=carrier_event_number_lsbs") previous_carrier_event_number_lsbs = carrier_event_number_lsbs if len(event): #info("on the " + str(waveformfile_event_number) + "th event in the file") if be_verbose_when_collecting_data: debug("wfw: " + hex(carrier_event_number_lsbs, 2) + " " + hex(carrier, 1) + " " + hex(asic, 1) + " " + hex(channel, 1) + " " + hex(physical_window, 3) + " " + hex(logical_window, 3) + " " + hex(n_windows, 1) + " " + hex(starting_sample, 2) + " " + hex(n_samples, 2)) debug("yielding event " + hex(waveformfile_event_number,4)) yield event event = [] debug("waveformfile_event_number+=1") waveformfile_event_number += 1 # if be_verbose_when_collecting_data: # debug(hex(waveformfile_event_number,4) + " " + hex(carrier_event_number_lsbs, 2) + " " + hex(carrier, 1) + " " + hex(asic, 1) + " " + hex(channel, 1) + " " + hex(physical_window, 3) + " " + hex(logical_window, 3) + " " + hex(n_windows, 1) + " " + hex(starting_sample, 2) + " " + hex(n_samples, 2)) event.append(waveform) if len(event): #info("on the " + str(waveformfile_event_number) + "th event in the file") if be_verbose_when_collecting_data: debug("wfw: " + hex(carrier_event_number_lsbs, 2) + " " + hex(carrier, 1) + " " + hex(asic, 1) + " " + hex(channel, 1) + " " + hex(physical_window, 3) + " " + hex(logical_window, 3) + " " + hex(n_windows, 1) + " " + hex(starting_sample, 2) + " " + hex(n_samples, 2)) debug("yielding event " + hex(waveformfile_event_number,4)) yield event #set_verbosity(old_verbosity) def count_events_in_waveformfile(): k = 0 open_waveformfile_for_reading() for event in events_from_waveformfile(): k += 1 close_waveformfile_for_reading() return k def update_gui(): if not gui_initialized: error("gui not initialized") sys.exit(1) #info("updating") show_latest_png_if_necessary() gui_window.after(gui_update_period_ms, update_gui) gui_initialized = 0 def initialize_gui(): read_config_file_for_xrm_stuff() global gui_window global image_frame global gui_initialized if not gui_initialized: gui_initialized = 1 gui_window = tkinter.Tk() gui_window.title("XRM " + station) #infotext = tkinter.Label(gui_window, text="xrm!") #infotext.pack() #quitbutton = tkinter.Button(gui_window, text="quit", command=gui_window.quit) #quitbutton.pack() image_frame = tkinter.Frame(gui_window, width=plot_width, height=plot_height) image_frame.pack() gui_window.after(gui_update_period_ms, update_gui) gui_window.mainloop() def show_png(filename): #gui_window.geometry('+%d+%d' % (100,100)) #gui_window.geometry('%dx%d' % (image1.size[0],image1.size[1])) #label_image.place(x=0,y=0,width=image1.size[0],height=image1.size[1]) try: photo = ImageTk.PhotoImage(Image.open(filename)) except: return global first_time_through global label try: if first_time_through: first_time_through = 0 except: first_time_through = 0 label = tkinter.Label(image_frame, image=photo) label.pack() label.configure(image=photo) label.image = photo gui_window.update() def get_latest_png(): command = "find -L data/" + station + " -type f -name '*.png' -printf '%TY-%Tm-%Td+%TH:%TM:%TS %p\n' | sort -n -k 1 | tail -n1 | awk '{ print $2 }'" response = commands.getstatusoutput(command) return response[1] def show_latest_png(): filename = get_latest_png() show_png(filename) old_png_filename = "" def show_latest_png_if_necessary(): global old_png_filename filename = get_latest_png() if old_png_filename!=filename: old_png_filename = filename time.sleep(1) info(filename) show_png(filename) def continuously_show_latest_png(): initialize_gui() def xrm_lin_ch_range(): #info("xrm_lin_ch_range") #return [ n for n in range(128) ] list = [] for carrier in range(4): for asic in range(4): for channel in range(8): if carrier not in carriers_to_dejuice: list.append(xrm_map_cac_to_linear(carrier, asic, channel)) # for item in list: # info(str(item)) return list #return [ lin_ch for lin_ch in range(0, 128, 2) ] def xrm_map_linear_to_cac(element): #if element not in range(1, 1+128): if element not in range(128): error("called xrm_map_linear_to_cac(" + str(element) + ") which is not allowed") sys.exit(1) # string = "element" + dec(element, 3) # element -= 1 carrier = element%4 element -= carrier asic_l = element%8 element -= asic_l asic_l //= 4 asic_l = not asic_l channel = element%64 element -= channel channel //= 8 if not asic_l: channel = 7 - channel asic_h = element asic_h //= 64 asic_h <<= 1 asic = asic_h | asic_l # string += " carrier" + str(carrier) # string += " asic" + str(asic) # string += " channel" + str(channel) # if not carrier in range(4): # error("bad mapping: carrier cannot be " + str(carrier)) # info(string) # sys.exit(0) # if not asic in range(4): # error("bad mapping: asic cannot be " + str(asic)) # info(string) # sys.exit(0) # if not channel in range(8): # error("bad mapping: channel cannot be " + str(channel)) # info(string) # sys.exit(0) return carrier, asic, channel def xrm_map_cac_to_linear(carrier, asic, channel): if carrier not in range(4): error("called xrm_map_cac_to_linear(" + str(carrier) + ") which is not allowed") sys.exit(1) if asic not in range(4): error("called xrm_map_cac_to_linear(" + str(asic) + ") which is not allowed") sys.exit(1) if channel not in range(8): error("called xrm_map_cac_to_linear(" + str(channel) + ") which is not allowed") sys.exit(1) #return 32*carrier + 8*asic + channel # straight cac mapping #return 16*carrier + 8*asic + channel # straight cac mapping; only carrier0 and carrier2 populated if 0==asic%2: asic_even = True asic_odd = False else: asic_even = False asic_odd = True # xrm slac detector wirebond board mapping: lin_ch = \ + ((asic//2)<<6) \ + (((7-channel)*(asic_even) + (channel)*(asic_odd))<<3) \ + (((asic+1)%2)<<2) \ + carrier return lin_ch def show_xrm_mapping(): cac_string = "" for element in range(128): carrier, asic, channel = xrm_map_linear_to_cac(element) #if 0==element%2: # if len(cac_string): # info(cac_string + colorarray_xrm(element)) if element in xrm_lin_ch_range(): cac_string += str(carrier) + "." + str(asic) + "." + str(channel) + "(" + colorarray_xrm(element) + ") " if 3==element%4: info(cac_string) cac_string = "" for carrier in range(4): for asic in range(4): element_string = "" for channel in range(8): element = xrm_map_cac_to_linear(carrier, asic, channel) element_string += dec(element, 3) + " " info(element_string) for element_in in range(128): carrier, asic, channel = xrm_map_linear_to_cac(element_in) element = xrm_map_cac_to_linear(carrier, asic, channel) if element != element_in: error("bad mapping: cac=" + str(carrier) + " " + str(asic) + " " + str(channel) + " lin=" + str(element)) # for element in range(128): # info(colorarray_xrm(element)) def plotquit(event): #info("quitting plots") global should_keep_going should_keep_going = 0 global sweep_should_keep_going sweep_should_keep_going = 0 #sys.exit(0) #def cac_phy_sub_sample_array(value): # return [[[[[[value for sample in range(32)] for subwindow in range(2)] for physical_window in range(512)] for channel in range(8)] for asic in range(4)] for carrier in range(4)] #def lin_phy_sub_sample_array(value): # return [[[[value for sample in range(32)] for subwindow in range(2)] for physical_window in range(512)] for channel in xrm_lin_ch_range()] def lin_array(value): #return [[value for sample in range(64*512)] for channel in xrm_lin_ch_range()] #return [[value for sample in range(asic_samples_per_read_window*number_of_physical_windows_to_plot)] for channel in xrm_lin_ch_range()] return [[value for sample in range(asic_samples_per_read_window*total_number_of_physical_windows)] for channel in range(128)] #independent_axis_units = duration_in_ns_of_64_sample_waveform independent_axis_units = 12 # RF_buckets_per_read_window but only after we've run calculate_parameters() def lin_ch_domain(first_physical_window_to_plot, last_physical_window_to_plot, number_of_physical_windows): #return numpy.linspace(first_physical_window_to_plot*duration_in_ns_of_64_sample_waveform, (last_physical_window_to_plot-first_physical_window_to_plot+1)*duration_in_ns_of_64_sample_waveform, (last_physical_window_to_plot-first_physical_window_to_plot+1)*64) # in ns return numpy.linspace(first_physical_window_to_plot*independent_axis_units, (last_physical_window_to_plot+1)*independent_axis_units-1.0/asic_samples_per_RF_bucket, number_of_physical_windows*asic_samples_per_read_window) #def domain(number_of_physical_windows_to_plot=1): # return numpy.linspace(0+duration_in_ns_of_64_sample_waveform*(number_of_physical_windows_to_plot-1), number_of_physical_windows_to_plot*duration_in_ns_of_64_sample_waveform, 64) # in ns datafile = None waveformfile = None def plot_slice_centered_on_RF_bucket(array): if already_plotted: axes2.clear() axes2.set_autoscaley_on(False) axes2.plot(array[0::2], [n for n in range(64)], color="blue") #info(str(desired_RF_bucket)) #axes2.set_ylim([129, -2]) #axes2.set_ylim([66, -2]) axes2.set_ylim([-4, 67]) axes2.set_yticklabels([]) axes2.set_yticks([]) axes2.set_xlim([slice_lower_limit, slice_upper_limit]) #axes2.set_xticklabels([]) #axes2.set_xticks([]) axes2.set_ylabel("channel") axes2.set_xlabel("amplitude (ADC counts)") axes2.set_title("RF bucket #" + str(desired_RF_bucket)) already_plotted = 0 #rainbow = [ "red", "orange", "yellow", "green", "teal", "blue", "indigo", "violet" ] rainbow = [ "#dd0000", "#ff7700", "#bbbb00", "#00bb00", "#00bbbb", "#0000bb", "#4488ff", "#ff77ff" ] #colorarray = [ "red", "green", "orange", "purple", "blue", "saddlebrown", "dodgerblue", "black" ] #colorarray = [ "yellow", "red", "indigo", "teal", "green", "orange", "violet", "blue" ] colorarray = [ rainbow[2], rainbow[0], rainbow[6], rainbow[4], rainbow[3], rainbow[1], rainbow[7], rainbow[5] ] def colorarray_xrm(lin_ch): #if 70==lin_ch: # return "blue" #else: # return "black" carrier, asic, channel = xrm_map_linear_to_cac(lin_ch) return colorarray[int(carrier//2)*4+asic] #return colorarray[carrier] #return colorarray[asic] #return colorarray[channel] def threaded_xrm_trigger_boardstack_and_capture_data(N, duration): if be_verbose_when_collecting_data: info("expecting " + str(N) + " events") #ethudp.attempt_to_flush(0) #ethudp.attempt_to_flush(1) mythread = threading.Thread(target=ethudp.capture_triggered_data, args=(datafilename, N, number_of_bytes_to_expect_per_event, be_verbose_when_collecting_data)) mythread.start() diff = trigger_and_wait_for_xrm_triggers(duration) #diff = allow_xrm_triggers_for_a_while(duration) mythread.join() if not diff == N: IncrementErrorCount("discrepancy: " + str(diff) + " (event # difference) != " + str(N) + " (desired number of triggers)", 1) should_software_trigger = 0 extra_duration_to_wait_for_data = 1.0 def get_triggered_data(N, n, N_log2, desired_event_numbers): # N is how many sets of events that we want # n is how many bunch markers are active per set (usually from a call to count_frame_masks()) # plot_continuous==1 means plot each one right after acquisition set_desired_trigger_quantities(N, N, N, N) set_trig_prescale_N_log2(N_log2) enable_xrm_triggers() wait_at_least_until_next_frame9() duration = ((N*n)+0.0) / expected_trigger_rate[N_log2] + extra_duration_to_wait_for_data first_time_through = 1 global should_keep_going should_keep_going = 1 while should_keep_going: manualRunReset_if_necessary(BS, be_verbose_when_collecting_data) threaded_xrm_trigger_boardstack_and_capture_data(N*n, duration) if be_verbose_when_collecting_data: show_some_info() if len(desired_event_numbers): quick_temp_status(BS) # if plot_continuous: # parse_datafile_and_plot_waveformfile(desired_event_numbers) if "acquire"==xrm_mode: read_config_file_for_xrm_stuff() get_ready_for_data(BS) cycle_calibration_channel(BS) # if not xrm_run_continuous: # info("mode changed (from configfile) to no longer run in continuous mode") # if already_plotted: # plt.close("all") # should_keep_going = 0 # break if first_time_through: first_time_through = 0 if "acquire"==xrm_mode: should_keep_going = xrm_run_continuous if "sweep"==xrm_mode: should_keep_going = 0 # if plot_continuous and not should_keep_going: # plt.pause(0) if should_keep_going and "acquire"==xrm_mode: if should_cycle_slowly_through_bunch_markers: cycle_through_bunch_marker_a() else: update_bunch_marker_from_desired_RF_bucket_with_offset(0, 0) time.sleep(desired_pause_between_acquisitions) if datafilesize>= frame_mask_shift list = [] if frame_mask & 0x100: list.append(0) if frame_mask & 0x080: list.append(1) if frame_mask & 0x040: list.append(2) if frame_mask & 0x020: list.append(3) if frame_mask & 0x010: list.append(4) if frame_mask & 0x008: list.append(5) if frame_mask & 0x004: list.append(6) if frame_mask & 0x002: list.append(7) if frame_mask & 0x001: list.append(8) return list def show_frame_masks(): a = read_register(SCROD_AxiCommon_bunch_marker_a, BS) af = decode_frame_mask(a) a &= ~frame_mask_all info("bunch_marker_a: frames:" + str(af) + " bucket:" + str(a)) b = read_register(SCROD_AxiCommon_bunch_marker_b, BS) bf = decode_frame_mask(b) b &= ~frame_mask_all info("bunch_marker_b: frames:" + str(bf) + " bucket:" + str(b)) c = read_register(SCROD_AxiCommon_bunch_marker_c, BS) cf = decode_frame_mask(c) c &= ~frame_mask_all info("bunch_marker_c: frames:" + str(cf) + " bucket:" + str(c)) d = read_register(SCROD_AxiCommon_bunch_marker_d, BS) df = decode_frame_mask(d) d &= ~frame_mask_all info("bunch_marker_d: frames:" + str(df) + " bucket:" + str(d)) #info("total frame masks active: " + str(count_frame_masks())) def count_frame_masks(): a = read_register(SCROD_AxiCommon_bunch_marker_a, BS) ac = len(decode_frame_mask(a)) b = read_register(SCROD_AxiCommon_bunch_marker_b, BS) bc = len(decode_frame_mask(b)) c = read_register(SCROD_AxiCommon_bunch_marker_c, BS) cc = len(decode_frame_mask(c)) d = read_register(SCROD_AxiCommon_bunch_marker_d, BS) dc = len(decode_frame_mask(d)) total = ac + bc + cc + dc info(str(total) + " frame masks") show_frame_masks() return total def cycle_calibration_channel(BS, init=0): if not enable_cal_signal: return 500 global calibration_channel_state if init or 128>4)%8 select_calibration_channel_multiple_destinations(BS, channel) calibration_channel_state += 16 else: carrier, asic, channel = xrm_map_linear_to_cac(calibration_channel_state) select_calibration_channel_single_destination(BS, carrier, asic, channel) calibration_channel_state += 2 wait_for_PS_on_each_carrier_to_pick_up_the_changes(BS) #show_calibration_signal_status(BS) return calibration_channel_state def change_pedestal_voltage(index, number_of_steps): vPed_min = 0.8 vPed_max = 1.3 slope = float(vPed_max-vPed_min) / (number_of_steps + 0.0) if index