TNMR updates: workaround for the hardware module error. Added more dashboard support. Added class definition auto-generated by pycom (NTNMR.py)
This commit is contained in:
1596
frappy_psi/tnmr/NTNMR.py
Normal file
1596
frappy_psi/tnmr/NTNMR.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -93,6 +93,7 @@ class ProgrammedSequence(fc.Readable):
|
||||
|
||||
compiled_parameters = {} # so that we can store the values of parameters only when compiling, effectively giving us an instance of each parameter loaded into TNMR, as well as "targets" (those above)
|
||||
inited = False
|
||||
approx_sequence_length = 0
|
||||
|
||||
### SETUP
|
||||
def tnmr(self):
|
||||
@@ -207,11 +208,14 @@ class ProgrammedSequence(fc.Readable):
|
||||
# first, create the sequence
|
||||
seq = seq_gen.get_initial_block()
|
||||
i = 0
|
||||
self.approx_sequence_length = 0
|
||||
for s in self.sequence_data:
|
||||
seq = seq_gen.combine_blocks(seq, seq_gen.get_single_pulse_block(f'pulse_{i}', str(s['pulse_width']) + 'u',
|
||||
str(s['pulse_height']),
|
||||
str(s['delay_time']) + 'u',
|
||||
str(s['phase_cycle'])))
|
||||
self.approx_sequence_length += float(s['delay_time'])*1e-6
|
||||
self.approx_sequence_length += float(s['pulse_width'])*1e-6
|
||||
i += 1
|
||||
seq = seq_gen.combine_blocks(seq, seq_gen.get_final_block(str(self.ringdown_time) + 'u',
|
||||
str(self.pre_acquisition_time) + 'u',
|
||||
@@ -219,10 +223,13 @@ class ProgrammedSequence(fc.Readable):
|
||||
str(self.post_acquisition_time) + 'm',
|
||||
str(self.acq_phase_cycle)))
|
||||
|
||||
self.approx_sequence_length += float(self.acquisition_time)*1e-6
|
||||
self.approx_sequence_length += float(self.post_acquisition_time)*1e-6
|
||||
|
||||
# then, save the thing
|
||||
filepath = os.getcwd()
|
||||
filename = self.title + f'_{time.time()}'
|
||||
filename = filepath + '/' + filename.replace('.','')
|
||||
filename = filepath + '/sequences/' + filename.replace('.','')
|
||||
seq_gen.save_sequence(filename, seq)
|
||||
seq_gen.save_sequence_cfg(filename, seq)
|
||||
|
||||
@@ -240,12 +247,10 @@ class ProgrammedSequence(fc.Readable):
|
||||
|
||||
# then, load the thing into TNMR
|
||||
self.tnmr().load_sequence(filename)
|
||||
time.sleep(1.0) # hardware module issue???
|
||||
|
||||
# load some parameters back to TNMR
|
||||
for key, val in dashboard_params.items():
|
||||
self.tnmr().set_nmrparameter(key, val)
|
||||
time.sleep(0.5)
|
||||
|
||||
# finally, let ourselves know we're ready
|
||||
self.status = ('PREPARED', 'compiled')
|
||||
@@ -256,11 +261,11 @@ class ProgrammedSequence(fc.Readable):
|
||||
'''Tells TNMR to acquire data. Only call after __compile_sequence().'''
|
||||
if(self.status[0] != 'BUSY'):
|
||||
self.status = ('BUSY', 'acquiring')
|
||||
self.tnmr().ZeroGo(lock=True, interval=0.5)
|
||||
self.tnmr().ZeroGo(lock=True, interval=0.5, check_time=max(self.approx_sequence_length*5, 5))
|
||||
newvals = {}
|
||||
newvals['reals'] = self.tnmr().get_data()[0]
|
||||
newvals['imags'] = self.tnmr().get_data()[1]
|
||||
newvals['t'] = [ self.compiled_parameters['acquisition_time'] * i/self.compiled_parameters['num_scans'] for i in range(0, self.compiled_parameters['num_scans']) ]
|
||||
newvals['t'] = [ self.compiled_parameters['acquisition_time'] * i/1024 for i in range(0, 1024) ]
|
||||
self.value = newvals
|
||||
self.status = ('PREPARED', 'compiled')
|
||||
|
||||
@@ -272,7 +277,7 @@ class ProgrammedSequence(fc.Readable):
|
||||
thread: bool, determines if this should open a child thread and detach the process
|
||||
'''
|
||||
self.__compile_sequence()
|
||||
time.sleep(0.5)
|
||||
time.sleep(1.0)
|
||||
self.__zero_go()
|
||||
|
||||
|
||||
|
||||
5
frappy_psi/tnmr/templates/Scout.txt
Normal file
5
frappy_psi/tnmr/templates/Scout.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Acquisition = Nucleus, Observe Freq., Acq. Points, Points 1D, SW +/-, Filter, Dwell Time, Acq. Time, Last Delay, ::, Scans 1D, Actual Scans 1D, Scan Start 1D, Repeat Times, S.A. Dimension, Dummy Scans, Receiver Gain, ::, Points 2D, Actual Points 2D, Points Start 2D, Points 3D, Actual Points 3D, Points Start 3D, Points 4D, Actual Points 4D, Points Start 4D, ::, SW 2D, SW 3D, SW 4D, Dwell_2D, Dwell_3D, Dwell_4D
|
||||
Frequency = Observe Freq., Observe Ch., ::, F1 Freq., F2 Freq.
|
||||
Processing = Shift # Points, LB 1D, GB 1D, DM 1D, SB Shift 1D, SB Width 1D, SB Skew 1D, TZ 1 1D, TZ 2 1D, TZ 3 1D, TZ 4 1D, Traf 1D, Sys. Phase 0 1D, Sys. Phase 1 1D, Phase 0 1D, Phase 1 1D, Echo Center 1D, ::, LB 2D, GB 2D, DM 2D, SB Shift 2D, SB Width 2D, SB Skew 2D, TZ 1 2D, TZ 2 2D, TZ 3 2D, TZ 4 2D, Traf 2D, Sys. Phase 0 2D, Sys. Phase 1 2D, Phase 0 2D, Phase 1 2D, Echo Center 2D, ::, LB 3D, GB 3D, DM 3D, SB Shift 3D, SB Width 3D, SB Skew 3D, TZ 1 3D, TZ 2 3D, TZ 3 3D, TZ 4 3D, Traf 3D, Sys. Phase 0 3D, Sys. Phase 1 3D, Phase 0 3D, Phase 1 3D, Echo Center 3D, ::, LB 4D, GB 4D, DM 4D, SB Shift 4D, SB Width 4D, SB Skew 4D, TZ 1 4D, TZ 2 4D, TZ 3 4D, TZ 4 4D, Traf 4D, Sys. Phase 0 4D, Sys. Phase 1 4D, Phase 0 4D, Phase 1 4D, Echo Center 4D
|
||||
Misc. = Date, Magnet Field, Absolute Freq., Exp. Start Time, Exp. Finish Time, Exp. Elapsed Time
|
||||
|
||||
Binary file not shown.
@@ -15,8 +15,12 @@ TEMPLATE_FILE_PATH = os.path.dirname(os.path.realpath(__file__)) + '/templates/'
|
||||
|
||||
import win32com.client
|
||||
import pythoncom
|
||||
import frappy_psi.tnmr.NTNMR as NTNMR
|
||||
|
||||
import time
|
||||
import json
|
||||
import traceback
|
||||
import threading
|
||||
|
||||
class TNMRNotRunnningError(Exception):
|
||||
def __init__(self, msg=None):
|
||||
@@ -88,7 +92,7 @@ class TNMR:
|
||||
if filepath != "":
|
||||
print(f'Loading file {filepath}')
|
||||
ntnmr.OpenFile(filepath)
|
||||
self.ACTIVEFILE = ntnmr.GetActiveDocPath
|
||||
self.ACTIVEFILE = ntnmr.GetActiveDocPath()
|
||||
self.ACTIVEPATH = os.path.dirname(self.ACTIVEFILE)
|
||||
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
||||
|
||||
@@ -122,17 +126,17 @@ class TNMR:
|
||||
ntnmr = self.get_instance()
|
||||
ntnmr.OpenFile(filepath)
|
||||
if active:
|
||||
self.ACTIVEFILE = ntnmr.GetActiveDocPath
|
||||
self.ACTIVEFILE = ntnmr.GetActiveDocPath()
|
||||
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
||||
|
||||
def set_activefile(self):
|
||||
""" Sets TNMR active doc path to ACTIVEFILE
|
||||
"""
|
||||
self.ACTIVEFILE = self.get_instance().GetActiveDocPath
|
||||
self.ACTIVEFILE = self.get_instance().GetActiveDocPath()
|
||||
self.ACTIVEPATH = os.path.dirname(self.ACTIVEFILE)
|
||||
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
||||
|
||||
def ZeroGo(self, lock = True, interval = 0.5):
|
||||
def ZeroGo(self, lock = True, interval = 0.5, check_time=10):
|
||||
""" If possible, zeros and starts acquisition
|
||||
|
||||
Parameters
|
||||
@@ -141,19 +145,79 @@ class TNMR:
|
||||
if true, program waits until acquisition is done
|
||||
interval: float
|
||||
how often to check if acquisition done
|
||||
check_time: float
|
||||
how many seconds until not recieving new data is considered grounds for another Zero-Go attempt. Recommended to set as at least the length of 2-3 pulse sequences.
|
||||
"""
|
||||
# for some reason CheckAcquisition is False while an experiment is
|
||||
# running but true otherwise
|
||||
CHECK_MODE = 'thread' # thread OR data
|
||||
|
||||
print('Zero-going...')
|
||||
ntnmr = self.get_instance()
|
||||
if not(self.acquisition_running()):
|
||||
ntnmr.Reset # to avoid hardware issues?
|
||||
ntnmr.ZG
|
||||
print('Reset')
|
||||
ntnmr.Reset() # to avoid hardware issues? EDIT: Doesn't seem to do much...
|
||||
if(CHECK_MODE == 'data'):
|
||||
print('Artificially setting the zeroth point to NULL for error detection.')
|
||||
ntnmr.SetDataPoint(1, [0,0])
|
||||
print('ZG')
|
||||
try:
|
||||
def t(s):
|
||||
print('\nStart ZG lambda')
|
||||
try:
|
||||
s.get_instance().ZeroAndGo()
|
||||
except:
|
||||
print('\nException in ZG lambda')
|
||||
pass
|
||||
print('\nCompletion of ZG lambda')
|
||||
return
|
||||
thread = threading.Thread(target=t, args=(self,))
|
||||
thread.start()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print('ZG completed')
|
||||
else:
|
||||
print('An Acquisition is already running')
|
||||
print('An acquisition is already running')
|
||||
|
||||
if(CHECK_MODE == 'data'):
|
||||
elapsed = 0
|
||||
print('Waiting to recieve real data')
|
||||
while(True):
|
||||
try:
|
||||
d = ntnmr.GetData()
|
||||
if not(d is None):
|
||||
if(d[0] != 0):
|
||||
break
|
||||
except:
|
||||
traceback.print_exc()
|
||||
time.sleep(0.1)
|
||||
elapsed += 0.1
|
||||
print(f'\rElapsed: {elapsed:.1f}s/{check_time:.1f}s', end='')
|
||||
if(elapsed > check_time): # broken
|
||||
print('\nTimeout! No data!')
|
||||
ntnmr.Abort()
|
||||
self.ZeroGo(lock=lock, interval=interval, check_time=check_time)
|
||||
break
|
||||
print('\n')
|
||||
elif(CHECK_MODE == 'thread'):
|
||||
print('Giving ZeroGo command a grace period to terminate...')
|
||||
elapsed = 0.0
|
||||
while(elapsed < 2.0):
|
||||
if not(thread.is_alive()):
|
||||
print('\nZeroGo terminated in time. Continuing...', end='')
|
||||
break
|
||||
time.sleep(0.1)
|
||||
elapsed += 0.1
|
||||
print(f'\rElapsed: {elapsed:.1f}s/2.0s', end='')
|
||||
print('\n')
|
||||
if(thread.is_alive()): # technically possible that it dies at the verrrry last moment, so may as well add an if-condition. What can I say? I'm merciful.
|
||||
print('ZeroGo did not terminate. This is a sign of an error. Retrying...')
|
||||
# the thread still hasn't died - this is a sign that the ZeroGo got caught up with some sort of error. Abandon, and retry.
|
||||
ntnmr.Abort()
|
||||
self.ZeroGo(lock=lock, interval=interval, check_time=check_time)
|
||||
|
||||
if lock:
|
||||
print("Application locked during acquisition\n...waiting...")
|
||||
print("Application locked during acquisition. Waiting...")
|
||||
while self.acquisition_running():
|
||||
time.sleep(interval)
|
||||
# TODO: https://stackoverflow.com/questions/27586411/how-do-i-close-window-with-handle-using-win32gui-in-python to close any tecmag dialogues that show up. Need to determine proper search string, so next time it pops up, run some tests.
|
||||
@@ -168,7 +232,7 @@ class TNMR:
|
||||
False: if not running
|
||||
"""
|
||||
ntnmr = self.get_instance()
|
||||
res = not(ntnmr.CheckAcquisition)
|
||||
res = not(ntnmr.CheckAcquisition())
|
||||
return res
|
||||
|
||||
def get_data(self):
|
||||
@@ -178,7 +242,7 @@ class TNMR:
|
||||
-------
|
||||
a tuple of ([real_array], [imaginary_array])
|
||||
'''
|
||||
raw_data = self.get_instance().GetData
|
||||
raw_data = self.get_instance().GetData()
|
||||
reals = raw_data[::2]
|
||||
imags = raw_data[1::2]
|
||||
|
||||
@@ -314,7 +378,7 @@ class TNMR:
|
||||
|
||||
ntnmr = self.get_instance()
|
||||
print(f'Loading sequence at {filename}')
|
||||
ntnmr.CloseActiveFile
|
||||
ntnmr.CloseActiveFile()
|
||||
success = ntnmr.OpenFile(TEMPLATE_FILE_PATH + 'tmp.tnt')
|
||||
if(success):
|
||||
print('Template file reloaded')
|
||||
|
||||
Reference in New Issue
Block a user