Hi,
In Global CTF (and refinement jobs where on the fly global CTF refinement is activated), currently CTF params are printed out per group, in one long list.
This is fine when we have only a few, but often in the case of image shift groups we often have 100+ groups, and seeing how/if the beam tilt is systematically varying between groups can be important for judging whether it is worth splitting into so many groups (and also for judging whether hardware corrections are working well).
Would it be possible to print a summary table to the log at the end, with the exposure group ID and the values of any refined parameters (e.g. beam tilt and trefoil)? Even better would be an X-Y scatter plot of the beam tilt values, although this is easy enough to make from a table.
Cheers
Oli
1 Like
Hi @olibclarke,
Thank you for the request – noted! As more exposure groups is becoming more common, this makes a lot of sense.
Best,
Michael
1 Like
Was coming here to submit a feature request for an X-Y scatter plot of beam tilt values but I see Oli beat me to it by a year and a half. Sometimes I see these values changing quite a bit during early refinements and would really help to determine if exposure groups are large enough or refinement is good enough to be measuring these accurately.
1 Like
This would still be useful to have! In the meantime, here is a script to extract the beam tilt values from the event log (in txt) and output them to a csv that you can plot how you like:
#!/usr/bin/env python3
import re
import csv
import sys
def extract_tilts(log_path, csv_path):
"""
Extracts beam-tilt values from a text log and writes them to a CSV.
Looks for every line containing 'New group params' and then grabs
the first 'Tilt (mrad)' line within the next 5 lines, parsing the
last two floats on that line as X and Y.
Args:
log_path (str): Path to the input text log.
csv_path (str): Path to the output CSV file.
"""
tilt_records = []
with open(log_path, 'r') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if 'New group params' in line:
# scan the next few lines for Tilt (mrad)
for j in range(i+1, min(i+6, len(lines))):
if 'Tilt (mrad)' in lines[j]:
nums = re.findall(r'-?\d+\.\d+', lines[j])
if len(nums) >= 2:
x_val, y_val = nums[-2], nums[-1]
tilt_records.append((x_val, y_val))
break
# write to CSV
with open(csv_path, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['TiltX_mrad', 'TiltY_mrad'])
writer.writerows(tilt_records)
print(f"Extracted {len(tilt_records)} entries → {csv_path}")
if __name__ == '__main__':
# allow override of filenames via command‑line
input_log = sys.argv[1] if len(sys.argv) > 1 else 'log.txt'
output_csv = sys.argv[2] if len(sys.argv) > 2 else 'tilts.csv'
extract_tilts(input_log, output_csv)