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)
|
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
|
inited = False
|
||||||
|
approx_sequence_length = 0
|
||||||
|
|
||||||
### SETUP
|
### SETUP
|
||||||
def tnmr(self):
|
def tnmr(self):
|
||||||
@@ -207,11 +208,14 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
# first, create the sequence
|
# first, create the sequence
|
||||||
seq = seq_gen.get_initial_block()
|
seq = seq_gen.get_initial_block()
|
||||||
i = 0
|
i = 0
|
||||||
|
self.approx_sequence_length = 0
|
||||||
for s in self.sequence_data:
|
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',
|
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['pulse_height']),
|
||||||
str(s['delay_time']) + 'u',
|
str(s['delay_time']) + 'u',
|
||||||
str(s['phase_cycle'])))
|
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
|
i += 1
|
||||||
seq = seq_gen.combine_blocks(seq, seq_gen.get_final_block(str(self.ringdown_time) + 'u',
|
seq = seq_gen.combine_blocks(seq, seq_gen.get_final_block(str(self.ringdown_time) + 'u',
|
||||||
str(self.pre_acquisition_time) + 'u',
|
str(self.pre_acquisition_time) + 'u',
|
||||||
@@ -219,10 +223,13 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
str(self.post_acquisition_time) + 'm',
|
str(self.post_acquisition_time) + 'm',
|
||||||
str(self.acq_phase_cycle)))
|
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
|
# then, save the thing
|
||||||
filepath = os.getcwd()
|
filepath = os.getcwd()
|
||||||
filename = self.title + f'_{time.time()}'
|
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(filename, seq)
|
||||||
seq_gen.save_sequence_cfg(filename, seq)
|
seq_gen.save_sequence_cfg(filename, seq)
|
||||||
|
|
||||||
@@ -240,12 +247,10 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
|
|
||||||
# then, load the thing into TNMR
|
# then, load the thing into TNMR
|
||||||
self.tnmr().load_sequence(filename)
|
self.tnmr().load_sequence(filename)
|
||||||
time.sleep(1.0) # hardware module issue???
|
|
||||||
|
|
||||||
# load some parameters back to TNMR
|
# load some parameters back to TNMR
|
||||||
for key, val in dashboard_params.items():
|
for key, val in dashboard_params.items():
|
||||||
self.tnmr().set_nmrparameter(key, val)
|
self.tnmr().set_nmrparameter(key, val)
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
# finally, let ourselves know we're ready
|
# finally, let ourselves know we're ready
|
||||||
self.status = ('PREPARED', 'compiled')
|
self.status = ('PREPARED', 'compiled')
|
||||||
@@ -256,11 +261,11 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
'''Tells TNMR to acquire data. Only call after __compile_sequence().'''
|
'''Tells TNMR to acquire data. Only call after __compile_sequence().'''
|
||||||
if(self.status[0] != 'BUSY'):
|
if(self.status[0] != 'BUSY'):
|
||||||
self.status = ('BUSY', 'acquiring')
|
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 = {}
|
||||||
newvals['reals'] = self.tnmr().get_data()[0]
|
newvals['reals'] = self.tnmr().get_data()[0]
|
||||||
newvals['imags'] = self.tnmr().get_data()[1]
|
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.value = newvals
|
||||||
self.status = ('PREPARED', 'compiled')
|
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
|
thread: bool, determines if this should open a child thread and detach the process
|
||||||
'''
|
'''
|
||||||
self.__compile_sequence()
|
self.__compile_sequence()
|
||||||
time.sleep(0.5)
|
time.sleep(1.0)
|
||||||
self.__zero_go()
|
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 win32com.client
|
||||||
import pythoncom
|
import pythoncom
|
||||||
|
import frappy_psi.tnmr.NTNMR as NTNMR
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
import traceback
|
||||||
|
import threading
|
||||||
|
|
||||||
class TNMRNotRunnningError(Exception):
|
class TNMRNotRunnningError(Exception):
|
||||||
def __init__(self, msg=None):
|
def __init__(self, msg=None):
|
||||||
@@ -88,7 +92,7 @@ class TNMR:
|
|||||||
if filepath != "":
|
if filepath != "":
|
||||||
print(f'Loading file {filepath}')
|
print(f'Loading file {filepath}')
|
||||||
ntnmr.OpenFile(filepath)
|
ntnmr.OpenFile(filepath)
|
||||||
self.ACTIVEFILE = ntnmr.GetActiveDocPath
|
self.ACTIVEFILE = ntnmr.GetActiveDocPath()
|
||||||
self.ACTIVEPATH = os.path.dirname(self.ACTIVEFILE)
|
self.ACTIVEPATH = os.path.dirname(self.ACTIVEFILE)
|
||||||
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
||||||
|
|
||||||
@@ -122,17 +126,17 @@ class TNMR:
|
|||||||
ntnmr = self.get_instance()
|
ntnmr = self.get_instance()
|
||||||
ntnmr.OpenFile(filepath)
|
ntnmr.OpenFile(filepath)
|
||||||
if active:
|
if active:
|
||||||
self.ACTIVEFILE = ntnmr.GetActiveDocPath
|
self.ACTIVEFILE = ntnmr.GetActiveDocPath()
|
||||||
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
||||||
|
|
||||||
def set_activefile(self):
|
def set_activefile(self):
|
||||||
""" Sets TNMR active doc path to ACTIVEFILE
|
""" 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)
|
self.ACTIVEPATH = os.path.dirname(self.ACTIVEFILE)
|
||||||
print(f'Active file: {self.ACTIVEFILE} in path {self.ACTIVEPATH}')
|
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
|
""" If possible, zeros and starts acquisition
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@@ -141,19 +145,79 @@ class TNMR:
|
|||||||
if true, program waits until acquisition is done
|
if true, program waits until acquisition is done
|
||||||
interval: float
|
interval: float
|
||||||
how often to check if acquisition done
|
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
|
# for some reason CheckAcquisition is False while an experiment is
|
||||||
# running but true otherwise
|
# running but true otherwise
|
||||||
|
CHECK_MODE = 'thread' # thread OR data
|
||||||
|
|
||||||
print('Zero-going...')
|
print('Zero-going...')
|
||||||
ntnmr = self.get_instance()
|
ntnmr = self.get_instance()
|
||||||
if not(self.acquisition_running()):
|
if not(self.acquisition_running()):
|
||||||
ntnmr.Reset # to avoid hardware issues?
|
print('Reset')
|
||||||
ntnmr.ZG
|
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:
|
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:
|
if lock:
|
||||||
print("Application locked during acquisition\n...waiting...")
|
print("Application locked during acquisition. Waiting...")
|
||||||
while self.acquisition_running():
|
while self.acquisition_running():
|
||||||
time.sleep(interval)
|
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.
|
# 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
|
False: if not running
|
||||||
"""
|
"""
|
||||||
ntnmr = self.get_instance()
|
ntnmr = self.get_instance()
|
||||||
res = not(ntnmr.CheckAcquisition)
|
res = not(ntnmr.CheckAcquisition())
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
@@ -178,7 +242,7 @@ class TNMR:
|
|||||||
-------
|
-------
|
||||||
a tuple of ([real_array], [imaginary_array])
|
a tuple of ([real_array], [imaginary_array])
|
||||||
'''
|
'''
|
||||||
raw_data = self.get_instance().GetData
|
raw_data = self.get_instance().GetData()
|
||||||
reals = raw_data[::2]
|
reals = raw_data[::2]
|
||||||
imags = raw_data[1::2]
|
imags = raw_data[1::2]
|
||||||
|
|
||||||
@@ -314,7 +378,7 @@ class TNMR:
|
|||||||
|
|
||||||
ntnmr = self.get_instance()
|
ntnmr = self.get_instance()
|
||||||
print(f'Loading sequence at {filename}')
|
print(f'Loading sequence at {filename}')
|
||||||
ntnmr.CloseActiveFile
|
ntnmr.CloseActiveFile()
|
||||||
success = ntnmr.OpenFile(TEMPLATE_FILE_PATH + 'tmp.tnt')
|
success = ntnmr.OpenFile(TEMPLATE_FILE_PATH + 'tmp.tnt')
|
||||||
if(success):
|
if(success):
|
||||||
print('Template file reloaded')
|
print('Template file reloaded')
|
||||||
|
|||||||
Reference in New Issue
Block a user