Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLE scan #132

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
287bf3b
Created simple PLE experiment which can set a voltage
LaneUW Oct 26, 2023
a31792c
Added custom controller and scanner for interfacing with SPCM in a PL…
LaneUW Nov 13, 2023
0798297
Changed Side Panel to have all necessary scan parameters. Added GoTo …
LaneUW Nov 16, 2023
ace09bc
Fixed some typos
LaneUW Nov 16, 2023
7b6f9e7
Can set voltage and read from SPCM.
LaneUW Nov 22, 2023
733e79a
Fixed issues with PL display.
LaneUW Nov 25, 2023
6bf3425
Changed module names to be pythonic
LaneUW Dec 27, 2023
8b9222c
Cleaned up comments, return types, and unnecessary imports
LaneUW Dec 27, 2023
f0d9a42
VControl no longer inherits from nipiezojenapy's base control
LaneUW Dec 27, 2023
49ff40f
Removed extraneous goto() inner function
LaneUW Dec 27, 2023
81505bd
Added type hinting for all new classes
LaneUW Dec 27, 2023
b553d39
Movd plescan.py to its own application directory
LaneUW Jan 8, 2024
80265ec
Added qt3ple to pyproject.toml
LaneUW Jan 8, 2024
2929b23
Reformatted PLE's main.py for readability.
LaneUW Jan 11, 2024
e63e588
Added Save Scan and Stop Scan buttons
LaneUW Jan 13, 2024
0e7cafb
Merge branch 'qt3uw:main' into Yaml
LaneUW Jan 13, 2024
6c6b85f
Changed QT3PLE to run off of YAML files (untested)
LaneUW Jan 16, 2024
14fa1a9
Removed redundant config button. Changed controller to plescanner.py
LaneUW Jan 18, 2024
f29c60a
Added changes to make yaml configuration functional.
LaneUW Jan 18, 2024
fe4bd63
Added wavemeter controller.
LaneUW Feb 4, 2024
c81d809
Added WavemeterAndScanner for experiment to interface with hardware.
LaneUW Feb 8, 2024
c48cbec
Integrated way to switch between PLE hardware from Yaml file only
LaneUW Feb 8, 2024
020df1c
Fixed issues connecting to wavemeter
YZWWW Feb 9, 2024
b38a8d8
Added comments to new functionality
LaneUW Feb 9, 2024
cb48d03
Added pythonic docstrings, variable names, and import order
LaneUW Feb 11, 2024
aee149f
Addressed PR requests by changing many style and clarity
LaneUW Feb 12, 2024
7f21586
Generalized plescanner to run any number of readers based on YAML file
LaneUW Feb 23, 2024
0d4ef2f
Added lockin controller
LaneUW Feb 24, 2024
7ac51ae
Addressed issues from hardware test
YZWWW Feb 24, 2024
1780f22
Added batch scan mode
LaneUW Feb 27, 2024
8edb03d
Saves as pickle.
YZWWW Mar 1, 2024
8eda17d
Adjusted comments and display names
LaneUW Mar 28, 2024
6ff982a
Changed PLE main verbose logger functionality
LaneUW Mar 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description = "A package for performing experiments in the QT3 lab at UW."
readme = "README.md"
requires-python = ">=3.8"
license = {file = "LICENSE"}
keywords = ["qt3", "confocal scan", "nidaqmx", "piezo", "stage", "control", "electron spin control"]
keywords = ["qt3", "confocal scan", "nidaqmx", "piezo", "stage", "control", "electron spin control", "ple"]

authors = [
{name = "G. Adam Cox", email = "gadamc@gmail.com" },
Expand Down Expand Up @@ -64,6 +64,7 @@ dependencies = [
[project.scripts]
qt3scope = "qt3utils.applications.qt3scope.main:main"
qt3scan = "qt3utils.applications.qt3scan.main:main"
qt3ple = "qt3utils.applications.qt3ple.main:main"

[tool.setuptools.package-data]
"qt3utils.applications.controllers" = ["*.yaml"]
31 changes: 31 additions & 0 deletions src/qt3utils/applications/controllers/lockin_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import logging
import numpy as np

import nidaqmx

class Lockin:
def __init__(self, logger_level) -> None:
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logger_level)
self.device_name = ""
self.signal_channel = ""
self.sample_number = 20
self.rate = 20.0
self.timeout = 10

def read(self) -> np.ndarray:
with nidaqmx.Task() as task:
task.ai_channels.add_ai_voltage_chan(self.device_name + '/' + self.signal_channel, max_val=10)
task.timing.cfg_samp_clk_timing(rate=self.rate, samps_per_chan=self.sample_number)
c = task.read(number_of_samples_per_channel=self.sample_number, timeout=self.timeout)
return np.array(c)

def configure(self, config_dict: dict) -> None:
"""
This method is used to configure the data controller.
"""
self.device_name = config_dict.get('daq_name', self.device_name)
self.signal_channel = config_dict.get('signal_channels', self.signal_channel)
self.sample_number = config_dict.get('sample_number', self.sample_number)
self.rate = config_dict.get('rate', self.rate)
self.timeout = config_dict.get('timeout', self.timeout)
51 changes: 51 additions & 0 deletions src/qt3utils/applications/controllers/nidaq_rate_counter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
QT3PLE:
ApplicationController:
import_path : qt3utils.datagenerators.plescanner
class_name : PleScanner
configure :
controllers:
daq_writers:
daq_writer : VoltageController
readers :
daq_readers:
daq_reader : DAQCounter
wm_readers:

DAQCounter:
import_path : qt3utils.applications.controllers.nidaqedgecounter
class_name : QT3ScopeNIDAQEdgeCounterController
configure :
daq_name : Dev1 # NI DAQ Device Name
signal_terminal : PFI0 # NI DAQ terminal connected to input digital TTL signal
clock_terminal : # Specifies the digital input terminal to the NI DAQ to use for a clock. If left blank, interprets as None or NULL
clock_rate: 100000 # NI DAQ clock rate in Hz
num_data_samples_per_batch : 1000
read_write_timeout : 10 # timeout in seconds for read/write operations
signal_counter : ctr2 # NI DAQ counter to use for counting the input signal, e.g. ctr0, ctr1, ctr2, or ctr3

VoltageController:
import_path : qt3utils.nidaq.customcontrollers
class_name : VControl
configure :
daq_name : Dev1 # NI DAQ Device Name
write_channels : ao0 # NI DAQ analog output channels to use for writing position
read_channels : ai0 # NI DAQ analog input channels to use for reading position
min_position: -10 # conversion factor from volts to microns, can also supply a list [8,8,8] or [6,4.2,5]
max_position: 10 # the voltage value that defines the position 0,0,0, can also supply a list [0,0,0] or [5,5,5]
scale_nm_per_volt: 1 # microns


# notes

# clock_rate:
# Specifies the clock rate in Hz. If using an external clock,
# you should specifiy the clock rate here so that the correct counts per
# second are displayed. If using the internal NI DAQ clock (default behavior),
# this value specifies the clock rate to use. Per the NI DAQ manual,
# use a suitable clock rate for the device for best performance, which is an integer
# multiple downsample of the digital sample clock.

# clock_terminal:
# Specifies the digital input terminal to the NI DAQ to use for a clock.
# If None, the internal NI DAQ clock is used. Otherwise, a string value
# specifies the terminal to use for the clock.
39 changes: 39 additions & 0 deletions src/qt3utils/applications/controllers/nidaq_wm_ple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
QT3PLE:
ApplicationController:
import_path : qt3utils.datagenerators.plescanner
class_name : PleScanner
configure :
controller: VoltageController
readers :
daq_readers:
daq_reader : DAQReader
wm_readers:
wm_reader : WavemeterDllController

DAQReader:
import_path : qt3utils.applications.controllers.lockin_controller
class_name : Lockin
configure :
daq_name : Silicon_DAQ # NI DAQ Device Name
signal_channels : ai21 # NI DAQ analog input channels to use for reading position
sample_number: 20 # Specifies the sampling rate in samples per channel per second
rate: 20.0 #Specifies the number of samples to acquire or generate for each channel in the task
timeout: 20 # Specifies the amount of time in seconds to wait for samples to become available

VoltageController:
import_path : qt3utils.nidaq.customcontrollers
class_name : VControl
configure :
daq_name : Silicon_DAQ # NI DAQ Device Name
write_channels : ao3 # NI DAQ analog output channels to use for writing voltage
read_channels : ai0 # NI DAQ analog input channels to use for reading voltage
min_position: -10 # conversion factor from volts to microns, can also supply a list [8,8,8] or [6,4.2,5]
max_position: 10 # the voltage value that defines the position 0,0,0, can also supply a list [0,0,0] or [5,5,5]
scale_nm_per_volt: 1 # microns
num_measurements_per_batch: 10

WavemeterDllController:
import_path : qt3utils.applications.controllers.wavemeter_controller
class_name : WavemeterDllController
configure :
dll_path : C:/Users/Fulab/Downloads/00392-2-06-A_CustomerCD621/00392-2-06-A_Customer CD 621/Programming Interface/x64/CLDevIFace.dll
1 change: 1 addition & 0 deletions src/qt3utils/applications/controllers/nidaqedgecounter.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,4 @@ def num_data_samples_per_batch(self) -> int:
@num_data_samples_per_batch.setter
def num_data_samples_per_batch(self, value: int):
self.data_generator.num_data_samples_per_batch = value

87 changes: 87 additions & 0 deletions src/qt3utils/applications/controllers/wavemeter_controller.py
LaneUW marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you need to implement a gui for the user to update the configuration through.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import abc
import ctypes
import logging


class WavemeterController(abc.ABC):
"""
Base class for other types of wavemeter controllers to inherit from
"""
def __init__(self, logger_level):
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logger_level)

@abc.abstractmethod
def open(self):
"""
Override this method to open and initialize wavemeter
"""
pass

@abc.abstractmethod
def read_wavemeter(self):
"""
Override this method to read the value from the wavemeter
"""
pass

@abc.abstractmethod
def close_wavemeter(self):
"""
Override this method to close the connection to the wavemeter
"""
pass
LaneUW marked this conversation as resolved.
Show resolved Hide resolved

@abc.abstractmethod
def configure(self, config_dict: dict):
"""
Override this method to configure the wavemeter from a dict set via yaml file
"""
pass


class WavemeterDllController(WavemeterController):
"""
Class for interfacing with wavemeter hardware
"""
def __init__(self, logger_level, dll_path=""):
super(WavemeterDllController, self).__init__(logger_level)
self.dll_path = dll_path
if not dll_path == "":
self.open(self.dll_path)
self.last_config_dict = {}

def open(self, dll_path) -> None:
"""
Set the path to the dll used for interfacing with the wavemeter
"""
self._mydll = ctypes.cdll.LoadLibrary(dll_path)
self._mydll.CLGetLambdaReading.restype = ctypes.c_double
self._dh = self._mydll.CLOpenUSBSerialDevice(4)
if self._dh == -1:
raise Exception("Failed to connect to wave meter.")

def read(self) -> float:
"""
Return the value from the wavemeter via the dll
"""
return self._mydll.CLGetLambdaReading(self._dh)

def close(self) -> None:
"""
Close the connection to the wavemeter via the dll
"""
ending = self._mydll.CLCloseDevice(self._dh)
if ending == -1:
raise Exception("Failed to properly close connection to wave meter.")
else:
device_handle=None

def configure(self, config_dict: dict) -> None:
"""
This method is used to configure the data controller.
"""
self.logger.debug("calling configure on the wave meter controller")
self.dll_path = config_dict.get('dll_path', self.dll_path)
self.open(self.dll_path)

Loading