A few things: 1. Got it working again; 2. Renamed files to make more sense; 3. Replaced template tmp.tnt with an emptied out file that previously took data, now data is collected correctly (bug, I'm not sure where this need comes from but this is, as far as I know, a permanent workaround); 4. Added automatic COM interface restart on errors compiling; 5. Implemented variable acquisition times.

This commit is contained in:
2025-06-12 11:04:57 +02:00
parent 05324a8966
commit 365f0a2374
8 changed files with 125 additions and 115 deletions

View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
"""
SequenceGeneration
______________________
Version: 1.0
Authors: Davis Garrad (Paul Scherrer Institute, CH)
______________________
Wrapper for the API I wrote to generate pulse sequences programmatically in TNMR (Tecmag).
"""
import frappy_psi.tnmr.sequence_fileformat as se
from pydantic.utils import deep_update
import json
def get_single_pulse_block(name, pulse_width, pulse_height, relaxation_time, phase_cycle='0'):
'''Generates a single block of data to create a sequence with.
Parameters
----------
name: str, just the prefix for the column names. Ensure this is unique over the whole sequence!
pulse_width: str, in the format '10u' (10 microseconds)
pulse_height: str, in the format '40' (I'm not honestly sure what units this is in...)
relaxation_time: str, in the format '10u'
phase_cycle: a given phase cycle (steps of 4, 0-3 inc.) (eg., '0 0 1 1 2 3 0 1', etc.)
Returns
-------
a dictionary which can be updated with others to generate a larger, more complex sequence.
'''
ph = name + '_phase'
rl = name + '_relaxation'
block = se.generate_default_sequence([ ph, rl ], [ pulse_width, relaxation_time ])
# COLUMNNS
# PH column
block['columns'][ph]['F1_Ampl']['value'] = str(pulse_height)
block['columns'][ph]['Delay'] = str(pulse_width)
block['columns'][ph]['F1_UnBlank']['value'] = '1'
block['columns'][ph]['Rx_Blank']['value'] = '1'
# relaxation column
block['columns'][rl]['F1_UnBlank']['value'] = '1'
block['columns'][rl]['Rx_Blank']['value'] = '1'
if(phase_cycle != ''):
table_name = f'ph_{name}'
block['columns'][ph]['F1_Ph']['table'] = table_name
block['tables'][table_name] = { 'values': phase_cycle, 'typestr': 'HP', 'start': 1 }
return block
def get_initial_block():
block = se.generate_default_sequence(['Phase reset', 'Unblank'], ['1u', '10u'])
# Phase reset
block['columns']['Phase reset']['F1_PhRst']['value'] = '1'
# Unblank
block['columns']['Unblank']['F1_UnBlank']['value'] = '1'
block['columns']['Unblank']['Rx_Blank']['value'] = '1'
return block
def get_final_block(ringdown_time, preacquire_time, acquire_time, cooldown_time, acq_phase_cycle='0'):
'''Generates the final block of data to create a sequence with.
Parameters
----------
ringdown_time: str, of format '10u', how long to ringdown
preacquire_time: str, in the format '10u', how long to wait after ringdown before acquiring data. A good default is 1 usec
acquire_time: str, in the format '10u', how long to acquire data for
cooldown_time: str, in the format '40u', how long to wait after acquisition.
acq_phase_cycle: str, the phase cycle that the acquisition should follow
Returns
-------
a dictionary which can be updated with others to generate a larger, more complex sequence.
'''
block = se.generate_default_sequence(['Ringdown', 'RX On', 'Acquisition', 'Finish', ''], [ringdown_time, preacquire_time, acquire_time, cooldown_time, '1u'])
block = se.generate_default_sequence(['Ringdown', 'RX On', 'Acquisition', 'Finish', ''], [ringdown_time, preacquire_time, acquire_time, cooldown_time, '1u'])
# ringdown
block['columns']['Ringdown']['Rx_Blank']['value'] = '1'
# Acquire
block['columns']['Acquisition']['Acq']['value'] = '1'
#block['columns']['Acquisition']['Acq_phase']['value'] = '0'
if(acq_phase_cycle != ''):
block['columns']['Acquisition']['Acq_phase']['table'] = 'phacq'
block['tables']['phacq'] = { 'values': acq_phase_cycle, 'typestr': 'HP', 'start': 1 }
return block
def combine_blocks(l, r):
return deep_update(l, r)
def save_sequence(filename, sequence):
se.create_sequence_file(filename, sequence)
def save_sequence_cfg(filename, sequence):
with open(filename + '.cfg', 'w') as file:
json.dump(sequence, file, indent=4)
file.close()