Skip to content

Commit

Permalink
Merge pull request #90 from qt3uw/fix-cwodmr-bug-when-returning-summe…
Browse files Browse the repository at this point in the history
…d-raw-trace

Fixes issue with converting list of heterogeneous type to numpy array. 

Tested locally on QLM
  • Loading branch information
gadamc authored Feb 10, 2023
2 parents 8d97cee + c8a53c9 commit 11f0145
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 40 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "qt3utils"
version = "1.0.2.dev0"
version = "1.0.2.dev1"

description = "A package for performing experiments in the QT3 lab at UW."
readme = "README.md"
Expand Down
21 changes: 12 additions & 9 deletions src/qt3utils/experiments/cwodmr.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ def experimental_conditions(self):
def run(self, N_cycles = 500000,
post_process_function = simple_measure_contrast,
random_order = False):
'''
Performs the CWODMR scan over the specificed range of frequencies.
"""
Performs the CWODMR scan over the specified range of frequencies.
For each frequency, some number of cycles of data are acquired. A cycle
For each frequency, the specified number of cycles of data are acquired. A cycle
is one full sequence of the pulse train used in the experiment. For CWODMR,
a cycle is {RF on for pulser.rf_pulse_duration time, RF off for pulser.rf_pulse_duration time}.
Expand All @@ -109,7 +109,7 @@ def run(self, N_cycles = 500000,
which is useful to reduce the required memory to hold the raw data.
After data acquisition for each frequency in the scan,
the post_process_function function is called and takes two arguments:
the post_process_function is called and takes two arguments:
1) data_buffer: the full trace of data acquired
2) self: a reference to an instance of this object
Expand All @@ -118,15 +118,18 @@ def run(self, N_cycles = 500000,
If post_process_function = None, the full raw data trace will be kept.
The return from this function is a list. Each element of the list
The return from this function is a numpy array. Each element of the array
is a list of the following values
RF Frequency,
data_post_processing_output (or raw data trace)
RF Frequency (float),
data_post_processing_output, or raw data trace (typically of type numpy array(dtype = float))
Because of the mixed types in this array, the numpy array data type returned
here is an 'object'.
The remaining (fixed) values for analysis can be obtained from the
self.experimental_conditions function.
'''
"""

self.N_cycles = int(N_cycles)

Expand Down Expand Up @@ -203,7 +206,7 @@ def run(self, N_cycles = 500000,
logger.error(f'in finally.close. {type(e)}: {e}')

self.rfsynth.rf_off(self.rfsynth_channel)
data = np.array(data)
data = np.array(data, dtype=object)
data = data[data[:,0].argsort()] #sorts the data by values in zeroth column... this is necessary if random_order = True
return data

Expand Down
17 changes: 10 additions & 7 deletions src/qt3utils/experiments/podmr.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def _stop_and_close_daq_tasks(self):
def run(self, N_cycles = 500000,
post_process_function = simple_measure_contrast,
random_order = False):
'''
"""
Performs the PulsedODMR scan over the specificed range of frequencies.
For each frequency, some number of cycles of data are acquired. A cycle
Expand All @@ -117,7 +117,7 @@ def run(self, N_cycles = 500000,
which is useful to reduce the required memory to hold the raw data.
After data acquisition for each frequency in the scan,
the post_process_function function is called and takes two arguments:
the post_process_function is called and takes two arguments:
1) data_buffer: the full trace of data acquired
2) self: a reference to an instance of this object
Expand All @@ -126,16 +126,19 @@ def run(self, N_cycles = 500000,
If post_process_function = None, the full raw data trace will be kept.
The return from this function is a list. Each element of the list
The return from this function is a numpy array. Each element of the array
is a list of the following values
RF Frequency,
data_post_processing_output (or raw data trace)
RF Frequency (float),
data_post_processing_output, or raw data trace (typically of type numpy array(dtype = float))
Because of the mixed types in this array, the numpy array data type returned
here is an 'object'.
The remaining (fixed) values for analysis can be obtained from the
self.experimental_conditions function.
'''
"""

self.N_cycles = int(N_cycles)

Expand Down Expand Up @@ -210,7 +213,7 @@ def run(self, N_cycles = 500000,
except Exception as e:
logger.error(f'in finally.close. {type(e)}: {e}')
#rfsynth.rf_off(self.rfsynth_channel)
data = np.array(data)
data = np.array(data, dtype=object)
data = data[data[:,0].argsort()] #sorts the data by values in zeroth column... this is necessary if random_order = True

return data
16 changes: 9 additions & 7 deletions src/qt3utils/experiments/rabi.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def _acquire_data_at_parameter(self, rf_pulse_duration, N_cycles = 10000,

def run(self, N_cycles = 50000,
post_process_function = qt3utils.experiments.podmr.simple_measure_contrast):
'''
"""
Performs the scan over the specificed range of RF widths.
For each RF width, some number of cycles of data are acquired. A cycle
Expand Down Expand Up @@ -221,14 +221,17 @@ def run(self, N_cycles = 50000,
If post_process_function = None, the full raw data trace will be kept.
The return from this function is a list. Each element of the list
The return from this function is a numpy array. Each element of the array
is a list of the following values
RF width,
data_post_processing_output (or raw data trace)
RF width (float),
data_post_processing_output, or raw data trace (typically of type numpy array(dtype = float))
Because of the mixed types in this array, the numpy array data type returned
here is an 'object'.
The remaining (fixed) values for analysis can be obtained from the
self.experimental_conditions function.
'''
"""

#first check that the pulser width is large enough
try:
Expand Down Expand Up @@ -267,8 +270,7 @@ def run(self, N_cycles = 50000,
except Exception as e:
pass
#rfsynth.rf_off(self.rfsynth_channel)
data = np.array(data)
data = np.array(data, dtype=object)

return data

return data
31 changes: 15 additions & 16 deletions src/qt3utils/experiments/ramsey.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, ramsey_pulser, rfsynth, edge_counter_config,
of an experiment and the hardware system setup.
Hardware Settings
ramsey_pulser - a qt3utils.experiments.pulsers.pulseblaster.PulseBlasterRamHahnDD object
ramsey_pulser - a qt3utils.pulsers.pulseblaster.PulseBlasterRamHahnDD object
rfsynth - a qt3rfsynthcontrol.Pulser object
edge_counter_config - a qt3utils.nidaq.config.EdgeCounter object
Expand Down Expand Up @@ -101,27 +101,24 @@ def experimental_conditions(self):

def run(self, N_cycles = 50000,
post_process_function = qt3utils.experiments.podmr.simple_measure_contrast):
'''
"""
Performs the scan over the specificed range of free precession times.
For each RF width, some number of cycles of data are acquired. A cycle
is one full sequence of the pulse train used in the experiment.
For Rabi, a cycle is {AOM on, AOM off/RF on, AOM on, AOM off/RF off}.
For each RF pulse delay, tau, some number of cycles of data are acquired. A cycle
is one full sequence of the pulse train used in the experiment as specified
by the supplied ramsey_pulser object.
The N_cycles specifies the total number of these cycles to
acquire. Your choice depends on your desired resolution or signal-to-noise
ratio, your post-data acquisition processing choices, and the amount of memory
available on your computer.
For each width, the number of data read from the NI DAQ will be
For each free precession time, tau, the number of data read from the NI DAQ will be
N_clock_ticks_per_cycle * N_cycles, where N_clock_ticks_per_cycle
is the value returned by self.set_pulser_state(tau).
Given the way our pulser is configured, N_clock_ticks_per_cycle will
grow linearly by tau.
The acquired data are stored in a data_buffer within this method. They
may be analyzed with a function passed to post_process_function,
may be processed with a function passed to post_process_function,
which is useful to reduce the required memory to hold the raw data.
After data acquisition for each width in the scan,
Expand All @@ -134,14 +131,17 @@ def run(self, N_cycles = 50000,
If post_process_function = None, the full raw data trace will be kept.
The return from this function is a list. Each element of the list
The return from this function is a numpy array. Each element of the array
is a list of the following values
RF width,
data_post_processing_output (or raw data trace)
RF Frequency (float),
data_post_processing_output, or raw data trace (typically of type numpy array(dtype = float))
Because of the mixed types in this array, the numpy array data type returned
here is an 'object'.
The remaining (fixed) values for analysis can be obtained from the
self.experimental_conditions function.
'''
"""

#first check that the pulser width is large enough
try:
Expand Down Expand Up @@ -228,8 +228,7 @@ def run(self, N_cycles = 50000,
except Exception as e:
logger.error(f'in finally.close. {type(e)}: {e}')
#rfsynth.rf_off(self.rfsynth_channel)
data = np.array(data)
data = np.array(data, dtype=object)

return data

return data

0 comments on commit 11f0145

Please sign in to comment.