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:
@@ -1,6 +1,5 @@
|
|||||||
import frappy.core as fc
|
import frappy.core as fc
|
||||||
import TNMRExt.OTFModule as mod
|
|
||||||
|
|
||||||
Node('example_TNMR.psi.ch', 'The NMR system running the Scout and controlled with TNMR', interface='tcp://5000')
|
Node('example_TNMR.psi.ch', 'The NMR system running the Scout and controlled with TNMR', interface='tcp://5000')
|
||||||
|
|
||||||
Mod('tnmr_otf_module', mod.ProgrammedSequence, 'NMR Sequence')
|
Mod('tnmr_otf_module', 'frappy_psi.tnmr.OTFModule.ProgrammedSequence', 'NMR Sequence')
|
||||||
@@ -11,8 +11,8 @@ frappy-based module for generating and running pulse sequences on TNMR (Tecmag).
|
|||||||
"""
|
"""
|
||||||
#On-the-fly!
|
#On-the-fly!
|
||||||
|
|
||||||
import TNMRExt.TNMR_DG_Extension as te
|
import frappy_psi.tnmr.tnmr_interface as te
|
||||||
import TNMRExt.SequenceGeneration as seq_gen
|
import frappy_psi.tnmr.sequence_generation as seq_gen
|
||||||
|
|
||||||
import frappy.core as fc
|
import frappy.core as fc
|
||||||
import frappy
|
import frappy
|
||||||
@@ -31,7 +31,7 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
Instance Attributes
|
Instance Attributes
|
||||||
-------------------
|
-------------------
|
||||||
(parameter) title: a title which will be embedded to the sequence files. Use this for identification.
|
(parameter) title: a title which will be embedded to the sequence files. Use this for identification.
|
||||||
(parameter) sequence_data: a dictionary describing the currently-built sequence
|
(parameter) sequence_data: an array of structs: keys are { 'pulse_width': (width of pulse in us), 'pulse_height': (amplitude of pulse in a.u.), 'relaxation_time': (relaxation time in us), 'phase_cycle': (a str denoting a phase cycle, e.g., '0 1 2 3') }
|
||||||
(parameter) value: an array of complexes representing the TNMR data return (technically inherited from Readable)
|
(parameter) value: an array of complexes representing the TNMR data return (technically inherited from Readable)
|
||||||
(parameter) acquisition_time: float (usecs) which describes the length of acquisition
|
(parameter) acquisition_time: float (usecs) which describes the length of acquisition
|
||||||
(parameter) ringdown_time: float (usecs) which describes the length of ringdown
|
(parameter) ringdown_time: float (usecs) which describes the length of ringdown
|
||||||
@@ -64,7 +64,10 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# inherited
|
# inherited
|
||||||
value = fc.Parameter('data_return', fc.ArrayOf(fc.FloatRange(), maxlen=4096), default=[])
|
value = fc.Parameter('data_return', fc.StructOf(reals=fc.ArrayOf(fc.FloatRange(), maxlen=4096), # real values
|
||||||
|
imags=fc.ArrayOf(fc.FloatRange(), maxlen=4096), # imag values
|
||||||
|
t =fc.ArrayOf(fc.FloatRange(), maxlen=4096)), # times (starting from zero)
|
||||||
|
default={ 'reals': [], 'imags': [], 't': [] })
|
||||||
status = fc.Parameter(datatype=frappy.datatypes.StatusType(fc.Readable, "DISABLED", 'PREPARED', 'BUSY'))
|
status = fc.Parameter(datatype=frappy.datatypes.StatusType(fc.Readable, "DISABLED", 'PREPARED', 'BUSY'))
|
||||||
pollinterval = fc.Parameter(default=1)
|
pollinterval = fc.Parameter(default=1)
|
||||||
|
|
||||||
@@ -73,19 +76,19 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
sequence_data = fc.Parameter('sequence_config', fc.ArrayOf(fc.StructOf(pulse_width=fc.FloatRange(unit='u'),
|
sequence_data = fc.Parameter('sequence_config', fc.ArrayOf(fc.StructOf(pulse_width=fc.FloatRange(unit='u'),
|
||||||
pulse_height=fc.FloatRange(),
|
pulse_height=fc.FloatRange(),
|
||||||
relaxation_time=fc.FloatRange(unit='u'),
|
relaxation_time=fc.FloatRange(unit='u'),
|
||||||
phase_cycle=fc.StringType())))
|
phase_cycle=fc.StringType())), default=[], readonly=False)
|
||||||
|
|
||||||
# sequence edit
|
# sequence edit
|
||||||
pulse_width = fc.Parameter('pulse_width', fc.FloatRange(unit='u'), readonly=False, group='pulse_editor')
|
#pulse_width = fc.Parameter('pulse_width', fc.FloatRange(unit='u'), readonly=False, group='pulse_editor', default=5)
|
||||||
pulse_height = fc.Parameter('pulse_height', fc.FloatRange(), readonly=False, group='pulse_editor')
|
#pulse_height = fc.Parameter('pulse_height', fc.FloatRange(), readonly=False, group='pulse_editor', default=40)
|
||||||
relaxation_time = fc.Parameter('relaxation_time', fc.FloatRange(unit='u', min=0.1), readonly=False, group='pulse_editor')
|
#relaxation_time = fc.Parameter('relaxation_time', fc.FloatRange(unit='u', min=0.1), readonly=False, group='pulse_editor', default=50)
|
||||||
phase_cycle = fc.Parameter('phase_cycle', fc.StringType(), readonly=False, group='pulse_editor', default='')
|
#phase_cycle = fc.Parameter('phase_cycle', fc.StringType(), readonly=False, group='pulse_editor', default='')
|
||||||
|
|
||||||
# final details
|
# final details
|
||||||
acquisition_time = fc.Parameter('acquisition_time', fc.FloatRange(unit='u'), readonly=True, group='sequence_editor', default=204.8) # this is a limit set by the dwell limit and number of acquisition points (1024, TODO: Make this adjustable)
|
acquisition_time = fc.Parameter('acquisition_time', fc.FloatRange(unit='u'), readonly=False, group='sequence_editor', default=204.8) # this is a limit set by the dwell limit and number of acquisition points (1024, TODO: Make this adjustable)
|
||||||
ringdown_time = fc.Parameter('ringdown_time', fc.FloatRange(unit='u'), readonly=False, group='sequence_editor')
|
ringdown_time = fc.Parameter('ringdown_time', fc.FloatRange(unit='u'), readonly=False, group='sequence_editor', default=1)
|
||||||
pre_acquisition_time = fc.Parameter('pre_acquisition_time', fc.FloatRange(unit='u'), readonly=False, group='sequence_editor')
|
pre_acquisition_time = fc.Parameter('pre_acquisition_time', fc.FloatRange(unit='u'), readonly=False, group='sequence_editor', default=1)
|
||||||
post_acquisition_time = fc.Parameter('post_acquisition_time', fc.FloatRange(unit='m'), readonly=False, group='sequence_editor')
|
post_acquisition_time = fc.Parameter('post_acquisition_time', fc.FloatRange(unit='m'), readonly=False, group='sequence_editor', default=500)
|
||||||
acq_phase_cycle = fc.Parameter('acq_phase_cycle', fc.StringType(), readonly=False, group='sequence_editor', default='')
|
acq_phase_cycle = fc.Parameter('acq_phase_cycle', fc.StringType(), readonly=False, group='sequence_editor', default='')
|
||||||
|
|
||||||
inited = False
|
inited = False
|
||||||
@@ -101,112 +104,80 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
### COMMANDS
|
### COMMANDS
|
||||||
@fc.Command(description="Add Pulse", group='pulse_editor', argument={ 'type': 'struct' }, members={ 'a': { 'type': 'string' }})
|
#@fc.Command(description="Add Pulse", group='pulse_editor')
|
||||||
def add_pulse(self):
|
#def add_pulse(self):
|
||||||
if(self.status == ('PREPARED', 'compiled')):
|
# if(self.status == ('PREPARED', 'compiled')):
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
# self.status = ('IDLE', 'ok - uncompiled')
|
||||||
data = list(self.sequence_data) # should be a tuple when it comes out of ArrayOf __call__, so make it mutable
|
# data = list(self.sequence_data) # should be a tuple when it comes out of ArrayOf __call__, so make it mutable
|
||||||
data += [ { 'pulse_width': self.pulse_width, 'pulse_height': self.pulse_height, 'relaxation_time': self.relaxation_time, 'phase_cycle': self.phase_cycle } ]
|
# data += [ { 'pulse_width': self.pulse_width, 'pulse_height': self.pulse_height, 'relaxation_time': self.relaxation_time, 'phase_cycle': self.phase_cycle } ]
|
||||||
self.sequence_data = data
|
# self.sequence_data = data
|
||||||
|
|
||||||
@fc.Command(description="Pop Pulse", group='pulse_editor')
|
#@fc.Command(description="Pop Pulse", group='pulse_editor')
|
||||||
def pop_pulse(self):
|
#def pop_pulse(self):
|
||||||
if(self.status == ('PREPARED', 'compiled')):
|
# if(self.status == ('PREPARED', 'compiled')):
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
# self.status = ('IDLE', 'ok - uncompiled')
|
||||||
data = list(self.sequence_data) # should be a tuple when it comes out of ArrayOf __call__, so make it mutable
|
# data = list(self.sequence_data) # should be a tuple when it comes out of ArrayOf __call__, so make it mutable
|
||||||
data = data[:-1] # chop off the tail
|
# data = data[:-1] # chop off the tail
|
||||||
self.sequence_data = data
|
# self.sequence_data = data
|
||||||
|
|
||||||
@fc.Command(description="Compile", group='sequence_editor')
|
#@fc.Command(description="Compile", group='sequence_editor')
|
||||||
def compile_sequence(self):
|
#def compile_sequence(self):
|
||||||
threading.Thread(target=lambda s=self: s.__compile_sequence()).start()
|
# threading.Thread(target=lambda s=self: s.__compile_sequence()).start()
|
||||||
|
|
||||||
@fc.Command(description="Run")
|
#@fc.Command(description="Run")
|
||||||
def run(self):
|
#def run(self):
|
||||||
threading.Thread(target=lambda s=self: s.__zero_go()).start()
|
# threading.Thread(target=lambda s=self: s.__zero_go()).start()
|
||||||
|
|
||||||
@fc.Command(description="Compile & Run")
|
@fc.Command(description="Compile & Run", argument={'type': 'bool'})
|
||||||
def compile_and_run(self):
|
def compile_and_run(self, thread=True):
|
||||||
|
if(thread):
|
||||||
threading.Thread(target=lambda s=self: s.__compile_and_run()).start()
|
threading.Thread(target=lambda s=self: s.__compile_and_run()).start()
|
||||||
|
else:
|
||||||
|
self.__compile_and_run()
|
||||||
|
|
||||||
### READ/WRITE
|
### READ/WRITE
|
||||||
def read_value(self):
|
|
||||||
return self.value # TODO: this is only reals
|
|
||||||
|
|
||||||
def read_title(self):
|
|
||||||
return self.title
|
|
||||||
|
|
||||||
def write_title(self, t):
|
def write_title(self, t):
|
||||||
self.title = t
|
self.title = t
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
return self.read_title()
|
return self.read_title()
|
||||||
|
|
||||||
def read_sequence_data(self):
|
#def write_pulse_width(self, t):
|
||||||
return self.sequence_data
|
# self.pulse_width = t
|
||||||
|
# return self.read_pulse_width()
|
||||||
|
|
||||||
def read_pulse_width(self):
|
#def write_pulse_height(self, t):
|
||||||
return self.pulse_width
|
# self.pulse_height = t
|
||||||
|
# return self.read_pulse_height()
|
||||||
|
|
||||||
def write_pulse_width(self, t):
|
#def write_relaxation_time(self, t):
|
||||||
self.pulse_width = t
|
# self.relaxation_time = t
|
||||||
return self.read_pulse_width()
|
# return self.read_relaxation_time()
|
||||||
|
|
||||||
def read_pulse_height(self):
|
#def write_phase_cycle(self, t):
|
||||||
return self.pulse_height
|
# self.phase_cycle = t
|
||||||
|
# return self.read_phase_cycle()
|
||||||
def write_pulse_height(self, t):
|
|
||||||
self.pulse_height = t
|
|
||||||
return self.read_pulse_height()
|
|
||||||
|
|
||||||
def read_relaxation_time(self):
|
|
||||||
return self.relaxation_time
|
|
||||||
|
|
||||||
def write_relaxation_time(self, t):
|
|
||||||
self.relaxation_time = t
|
|
||||||
return self.read_relaxation_time()
|
|
||||||
|
|
||||||
def read_phase_cycle(self):
|
|
||||||
return self.phase_cycle
|
|
||||||
|
|
||||||
def write_phase_cycle(self, t):
|
|
||||||
self.phase_cycle = t
|
|
||||||
return self.read_phase_cycle()
|
|
||||||
|
|
||||||
def read_acquisition_time(self):
|
|
||||||
return self.acquisition_time
|
|
||||||
|
|
||||||
def write_acquisition_time(self, t):
|
def write_acquisition_time(self, t):
|
||||||
self.acquisition_time = t
|
self.acquisition_time = t
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
return self.read_acquisition_time()
|
return self.read_acquisition_time()
|
||||||
|
|
||||||
def read_ringdown_time(self):
|
|
||||||
return self.ringdown_time
|
|
||||||
|
|
||||||
def write_ringdown_time(self, t):
|
def write_ringdown_time(self, t):
|
||||||
self.ringdown_time = t
|
self.ringdown_time = t
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
return self.read_ringdown_time()
|
return self.read_ringdown_time()
|
||||||
|
|
||||||
def read_pre_acquisition_time(self):
|
|
||||||
return self.pre_acquisition_time
|
|
||||||
|
|
||||||
def write_pre_acquisition_time(self, t):
|
def write_pre_acquisition_time(self, t):
|
||||||
self.pre_acquisition_time = t
|
self.pre_acquisition_time = t
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
return self.read_pre_acquisition_time()
|
return self.read_pre_acquisition_time()
|
||||||
|
|
||||||
def read_post_acquisition_time(self):
|
|
||||||
return self.post_acquisition_time
|
|
||||||
|
|
||||||
def write_post_acquisition_time(self, t):
|
def write_post_acquisition_time(self, t):
|
||||||
self.post_acquisition_time = t
|
self.post_acquisition_time = t
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
return self.read_post_acquisition_time()
|
return self.read_post_acquisition_time()
|
||||||
|
|
||||||
def read_acq_phase_cycle(self):
|
|
||||||
return self.acq_phase_cycle
|
|
||||||
|
|
||||||
def write_acq_phase_cycle(self, t):
|
def write_acq_phase_cycle(self, t):
|
||||||
self.acq_phase_cycle = t
|
self.acq_phase_cycle = t
|
||||||
self.status = ('IDLE', 'ok - uncompiled')
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
@@ -214,7 +185,7 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
|
|
||||||
### PRIVATE (Utility)
|
### PRIVATE (Utility)
|
||||||
def __compile_sequence(self):
|
def __compile_sequence(self):
|
||||||
if(self.status != ('PREPARED', 'compiled')) and (self.status[0] != 'BUSY'):
|
if(self.status[0] != 'BUSY'):
|
||||||
self.status = ('BUSY', 'compiling')
|
self.status = ('BUSY', 'compiling')
|
||||||
# first, create the sequence
|
# first, create the sequence
|
||||||
seq = seq_gen.get_initial_block()
|
seq = seq_gen.get_initial_block()
|
||||||
@@ -248,13 +219,30 @@ class ProgrammedSequence(fc.Readable):
|
|||||||
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)
|
||||||
self.value = self.tnmr().get_data()[0] # TODO: this is only reals...
|
newvals = {}
|
||||||
print(self.value)
|
newvals['reals'] = self.tnmr().get_data()[0]
|
||||||
|
newvals['imags'] = self.tnmr().get_data()[1]
|
||||||
|
newvals['t'] = self.tnmr().get_data_times()
|
||||||
|
self.value = newvals
|
||||||
self.status = ('PREPARED', 'compiled')
|
self.status = ('PREPARED', 'compiled')
|
||||||
|
|
||||||
def __compile_and_run(self):
|
def __compile_and_run(self, thread=True, recurse=True):
|
||||||
|
pythoncom.CoInitialize()
|
||||||
|
try:
|
||||||
self.__compile_sequence()
|
self.__compile_sequence()
|
||||||
self.__zero_go()
|
self.__zero_go()
|
||||||
|
except AttributeError as e:
|
||||||
|
print(f'Attribute error on compile and run.{" Resetting the COM interface and retrying..." if recurse else " Resetting did not fix this problem!"}')
|
||||||
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
|
self.tnmr().reset_NTNMR_instance()
|
||||||
|
self.__compile_and_run(thread, recurse=False)
|
||||||
|
except Exception as e:
|
||||||
|
print('Failed to compile and run!')
|
||||||
|
print(str(e))
|
||||||
|
print(repr(e))
|
||||||
|
self.status = ('IDLE', 'ok - uncompiled')
|
||||||
|
if(thread):
|
||||||
|
pythoncom.CoUninitialize()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,9 @@ def get_event_header(event_type, vals, tables, table_reg, tuning_number, col_del
|
|||||||
event_type: str describing the event
|
event_type: str describing the event
|
||||||
vals: an array of strs to be written.
|
vals: an array of strs to be written.
|
||||||
tables: an array of dictionaries of table names to be written in format [ { '1D': None/str } (for col0), { '1D': None/str } (for col1) ... ]
|
tables: an array of dictionaries of table names to be written in format [ { '1D': None/str } (for col0), { '1D': None/str } (for col1) ... ]
|
||||||
|
table_reg: a dictionary of the table registry
|
||||||
|
tuning_number: the number of columns, minus 1
|
||||||
|
col_delays: the array of column delays
|
||||||
'''
|
'''
|
||||||
codes = event_codes[event_type]
|
codes = event_codes[event_type]
|
||||||
headerstr = ''
|
headerstr = ''
|
||||||
@@ -191,18 +194,23 @@ def get_event_header(event_type, vals, tables, table_reg, tuning_number, col_del
|
|||||||
headerstr += fm(str(vals[i]))
|
headerstr += fm(str(vals[i]))
|
||||||
if(event_type == 'Acq' and str(vals[i]) == '1'):
|
if(event_type == 'Acq' and str(vals[i]) == '1'):
|
||||||
acq_points = 1024
|
acq_points = 1024
|
||||||
sweep = '2500000.0Hz'
|
acq_time = col_delays[i]
|
||||||
filtr = '2500000.0Hz'
|
if('u' in acq_time):
|
||||||
dwell = '200.0n' # hard limit apparently...
|
acq_time = float(acq_time.strip()[:-1])
|
||||||
#acq_length = col_delays[i]
|
elif('m' in acq_time):
|
||||||
#if('u' in acq_length):
|
acq_time = 1000*float(acq_time.strip()[:-1])
|
||||||
# acq_length = float(acq_length.strip()[:-1])
|
elif('n' in acq_time):
|
||||||
#elif('m' in acq_length):
|
acq_time = 0.001*float(acq_time.strip()[:-1])
|
||||||
# acq_length = 1000*float(acq_length.strip()[:-1])
|
|
||||||
#elif('n' in acq_length):
|
dwell_us = acq_time / acq_points
|
||||||
# acq_length = 0.001*float(acq_length.strip()[:-1])
|
dwell = f'{dwell_us*1000}n'
|
||||||
#dwell = acq_length / acq_points
|
freq = 1/(dwell_us/1e6) / 2 # put it in Hz. TODO: Figure out why the factor of 2 is necessary...
|
||||||
#dwell = str(dwell) + 'u'
|
sweep = f'{freq}Hz'
|
||||||
|
filtr = f'{freq}Hz'
|
||||||
|
|
||||||
|
#sweep = '2500000.0Hz'
|
||||||
|
#filtr = '2500000.0Hz'
|
||||||
|
#dwell = '400.0n' # hard limit apparently...
|
||||||
|
|
||||||
headerstr += Z*52
|
headerstr += Z*52
|
||||||
headerstr += f'\x01{Z*3}' + fm(str(acq_points))
|
headerstr += f'\x01{Z*3}' + fm(str(acq_points))
|
||||||
@@ -257,7 +265,6 @@ def generate_default_sequence(col_names, col_delays):
|
|||||||
a data dictionary in the form required by create_sequence_file.
|
a data dictionary in the form required by create_sequence_file.
|
||||||
'''
|
'''
|
||||||
full_dict = { 'columns': {}, 'tables': {} }
|
full_dict = { 'columns': {}, 'tables': {} }
|
||||||
print(full_dict)
|
|
||||||
for c, delay in zip(col_names, col_delays):
|
for c, delay in zip(col_names, col_delays):
|
||||||
sub_dict = {}
|
sub_dict = {}
|
||||||
for e in event_types:
|
for e in event_types:
|
||||||
@@ -9,7 +9,7 @@ ______________________
|
|||||||
|
|
||||||
Wrapper for the API I wrote to generate pulse sequences programmatically in TNMR (Tecmag).
|
Wrapper for the API I wrote to generate pulse sequences programmatically in TNMR (Tecmag).
|
||||||
"""
|
"""
|
||||||
import TNMRSeq.sequence_generator as se
|
import frappy_psi.tnmr.sequence_fileformat as se
|
||||||
|
|
||||||
from pydantic.utils import deep_update
|
from pydantic.utils import deep_update
|
||||||
|
|
||||||
BIN
frappy_psi/tnmr/templates/tmp.tnt
Normal file
BIN
frappy_psi/tnmr/templates/tmp.tnt
Normal file
Binary file not shown.
Binary file not shown.
@@ -11,7 +11,7 @@ Wrapper for communication with TecMag TNMR software, specifically in the context
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
TEMPLATE_FILE_PATH = os.path.dirname(os.path.realpath(__file__)) + '/templates/' # TODO: Make some sort of installer/initialiser that sets this all up...
|
TEMPLATE_FILE_PATH = os.path.dirname(os.path.realpath(__file__)) + '/templates/' # TODO: make prettier
|
||||||
|
|
||||||
import win32com.client
|
import win32com.client
|
||||||
import pythoncom
|
import pythoncom
|
||||||
@@ -58,14 +58,10 @@ class TNMR:
|
|||||||
"""
|
"""
|
||||||
#first we check if an instance of TNMR is running an get it or create it
|
#first we check if an instance of TNMR is running an get it or create it
|
||||||
print('Opening TNMR connection')
|
print('Opening TNMR connection')
|
||||||
try:
|
|
||||||
if(NTNMR_inst is None):
|
if(NTNMR_inst is None):
|
||||||
self.NTNMR = win32com.client.GetActiveObject("NTNMR.Application")
|
self.reset_NTNMR_instance()
|
||||||
else:
|
else:
|
||||||
self.NTNMR = NTNMR_inst
|
self.NTNMR = NTNMR_inst
|
||||||
except pythoncom.com_error:
|
|
||||||
raise TNMRNotRunnningError
|
|
||||||
|
|
||||||
# next we open a specified file. If none is specified, then we use the active file
|
# next we open a specified file. If none is specified, then we use the active file
|
||||||
if filepath != "":
|
if filepath != "":
|
||||||
print(f'Loading file {filepath}')
|
print(f'Loading file {filepath}')
|
||||||
@@ -74,6 +70,12 @@ class TNMR:
|
|||||||
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 reset_NTNMR_instance(self):
|
||||||
|
try:
|
||||||
|
self.NTNMR = win32com.client.GetActiveObject("NTNMR.Application")
|
||||||
|
except pythoncom.com_error:
|
||||||
|
raise TNMRNotRunnningError
|
||||||
|
|
||||||
def execute_cmd(self, cmd):
|
def execute_cmd(self, cmd):
|
||||||
print('W: Executing arbitrary command: ' + f'out = self.NTNMR.{cmd}')
|
print('W: Executing arbitrary command: ' + f'out = self.NTNMR.{cmd}')
|
||||||
out = 0
|
out = 0
|
||||||
@@ -145,6 +147,20 @@ class TNMR:
|
|||||||
|
|
||||||
return (reals, imags)
|
return (reals, imags)
|
||||||
|
|
||||||
|
def get_data_times(self):
|
||||||
|
#acq_n = int(self.NTNMR.GetNMRParameter('Acq. Points')) # TODO: These do NOT return the actual used values!
|
||||||
|
#acq_t = self.NTNMR.GetNMRParameter('Acq. Time')
|
||||||
|
#acq_t = acq_t.strip()
|
||||||
|
#if(acq_t[-1] == 'm'):
|
||||||
|
# acq_t = float(acq_t[:-1]) * 1000
|
||||||
|
#elif(acq_t[-1] == 'u'):
|
||||||
|
# acq_t = float(acq_t[:-1])
|
||||||
|
#elif(acq_t[-1] == 'n'):
|
||||||
|
# acq_t = float(acq_t[:-1]) / 1000
|
||||||
|
acq_t = 204.8 # us
|
||||||
|
acq_n = 1024
|
||||||
|
return [ i * (acq_t / (acq_n - 1)) for i in range(0, acq_n+1) ]
|
||||||
|
|
||||||
def save_file(self, filepath=''):
|
def save_file(self, filepath=''):
|
||||||
""" Save file to filepath. if no filepath specified, save current active file
|
""" Save file to filepath. if no filepath specified, save current active file
|
||||||
|
|
||||||
Reference in New Issue
Block a user