SuperKEKB XRM system  Not logged in ELOG logo
Entry  Tue Jan 22 07:56:56 2019, M. Andrew, documentation, instructions for setup, compiling and data acquisition XRM.instructions.txt
    Reply  Fri Oct 4 08:55:23 2019, M. Andrew, documentation, instructions for pdu control 
    Reply  Fri Oct 4 10:04:12 2019, M. Andrew, documentation, instructions for programming boardstack 
    Reply  Fri Oct 4 10:18:44 2019, M. Andrew, documentation, instructions for checking boardstack status and temperature 
    Reply  Fri Oct 4 10:33:53 2019, M. Andrew, documentation, instructions for boardstack configuration 
    Reply  Tue Oct 29 09:27:14 2019, M. Andrew, documentation, instructions on taking a full revolution of waveforms 2019-10-30.062954.s17a.SCROD004.xrm.log2019-10-30.063506.waveforms.425events.png
       Reply  Wed Oct 30 15:23:57 2019, M. Andrew, documentation, sample waveform files 8x
          Reply  Mon Nov 18 13:30:44 2019, M. Andrew, documentation, first light! 
          Reply  Wed Nov 6 13:35:45 2024, M. Andrew, documentation, sample waveform files 2024-04-17.135507.zip2024-04-17.135507.waveforms.32windows.pngxrm.py
    Reply  Tue Nov 5 11:47:36 2019, M. Andrew, documentation, instructions on taking data around a desired RF bucket 2019-11-05.121045.waveforms.0099.png
Message ID: 30     Entry time: Wed Nov 6 13:35:45 2024     In reply to: 26
Author: M. Andrew 
Type: documentation 
Subject: sample waveform files 
Attached is a sample datafile (in raw, root and waveforms formats) showing self-pulser data taken in April 2024, along with the most recent version of the xrm.py script.
Attachment 1: 2024-04-17.135507.zip  867 kB
Attachment 2: 2024-04-17.135507.waveforms.32windows.png  921 kB  | Show | Hide all
Attachment 3: xrm.py  141 kB  | Hide | Hide all
#!/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()
... 3541 more lines ...
ELOG V3.1.5-3a5f2f0