Skip to content

Commit

Permalink
Merge pull request #7 from UW-Quantum-Defect-Lab/003-adding-qdlmove
Browse files Browse the repository at this point in the history
#3 adding qdlmove
  • Loading branch information
nyama8 authored Oct 24, 2024
2 parents 7d46145 + 18fbc69 commit 74eb97d
Show file tree
Hide file tree
Showing 8 changed files with 1,162 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ would have to `pip` install after each edit).


Finally confirm that the installation worked correctly by launching the
Python interpretter and then importing the package:
Python interpreter and then importing the package:

```
> Python
Expand Down
31 changes: 31 additions & 0 deletions src/qt3utils/applications/qdlmove/application_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import logging
import time

import numpy as np

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


class MovementController:
'''
This is a basic application controller backend for the `qdlmove` application.
In its current implementation, it manages calls to move or step the various
hardware by reference to their name as stored in the `self.positioners` dict.
In the future, if more features are desired of the `qdlmove` application,
for example recording/saving of positions, plotting points, etc. the developer
should add these features into this class and update the GUI/main application
to trigger methods or store data in this class.
'''
def __init__(self, positioners: dict = {}):
self.positioners = positioners # dictionary of the controller instantiations


def move_axis(self, axis_controller_name: str, position: float):
# Move the axis specified by the axis_controller_name
self.positioners[axis_controller_name].go_to_position(position)

def step_axis(self, axis_controller_name: str, dx: float):
# Step the axis specified by the axis_controller_name
self.positioners[axis_controller_name].step_position(dx)
157 changes: 157 additions & 0 deletions src/qt3utils/applications/qdlmove/application_gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import tkinter as tk

class PositionControllerApplicationView():
'''
Main Application GUI which houses the individual controller GUIs.
'''

def __init__(self, main_window: tk.Tk):
# Get the frame to pack the GUI
frame = tk.Frame(main_window)
frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=16, pady=16)

# ===============================================================================
# Edit here to add more controllers
# ===============================================================================
# 2. ADD APPLICATION CONTROLLER GUIs HERE
# Edit here to add more movement control
# This creates a GUI element for the specified axes with the provided names.
# You must make a controller of the right type and with correct associations
# in order for the GUI to work properly.
self.micros_view = TwoAxisApplicationView(root_frame=frame,
title='Micros',
axis_1_label='X axis',
axis_2_label='Y axis')
self.piezos_view = ThreeAxisApplicationView(root_frame=frame,
title='Piezos',
axis_1_label='X axis',
axis_2_label='Y axis',
axis_3_label='Z axis')


# ===============================================================================
# No edits below here!
# ===============================================================================


class TwoAxisApplicationView():
'''
Application control for two-axis movement
'''
def __init__(self, root_frame: tk.Frame, title: str, axis_1_label: str, axis_2_label: str):

# Frame to house this subwindow
self.base_frame = tk.Frame(root_frame)
self.base_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=4, pady=8)


row = 0
tk.Label(self.base_frame, text=title, font='Helvetica 14').grid(row=row, column=0, pady=[0,5], columnspan=5)

row += 1
# Enable/disable the stepper
self.stepping_active = tk.IntVar()
self.stepping_laser_toggle = tk.Checkbutton ( self.base_frame, var=self.stepping_active, text='Enable stepping')
self.stepping_laser_toggle.grid(row=row, column=0, pady=[0,0], columnspan=2)
tk.Label(self.base_frame, text='Set value', font='Helvetica 10', width=10).grid(row=row, column=2, pady=[0,0], columnspan=1)
tk.Label(self.base_frame, text='Step', font='Helvetica 10', width=10).grid(row=row, column=3, pady=[0,0], columnspan=1)
tk.Label(self.base_frame, text='Current', font='Helvetica 10', width=10).grid(row=row, column=4, pady=[0,0], columnspan=1)

row += 1
tk.Label(self.base_frame, text=axis_1_label, font='Helvetica 10', width=10).grid(row=row, column=0, pady=[0,0], columnspan=1)
self.axis_1_set_button = tk.Button(self.base_frame, text='Set position', width=10)
self.axis_1_set_button.grid(row=row, column=1, columnspan=1, padx=0)
self.axis_1_set_entry = tk.Entry(self.base_frame, width=10)
self.axis_1_set_entry.insert(0, 0)
self.axis_1_set_entry.grid(row=row, column=2)
self.axis_1_step_entry = tk.Entry(self.base_frame, width=10)
self.axis_1_step_entry.insert(0, 0)
self.axis_1_step_entry.grid(row=row, column=3)
self.axis_1_readout_entry = tk.Entry(self.base_frame, width=10)
self.axis_1_readout_entry.insert(0, 0)
self.axis_1_readout_entry.config(state='readonly')
self.axis_1_readout_entry.grid(row=row, column=4)

row += 1
tk.Label(self.base_frame, text=axis_2_label, font='Helvetica 10', width=10).grid(row=row, column=0, pady=[0,0], columnspan=1)
self.axis_2_set_button = tk.Button(self.base_frame, text='Set position', width=10)
self.axis_2_set_button.grid(row=row, column=1, columnspan=1, padx=0)
self.axis_2_set_entry = tk.Entry(self.base_frame, width=10)
self.axis_2_set_entry.insert(0, 0)
self.axis_2_set_entry.grid(row=row, column=2)
self.axis_2_step_entry = tk.Entry(self.base_frame, width=10)
self.axis_2_step_entry.insert(0, 0)
self.axis_2_step_entry.grid(row=row, column=3)
self.axis_2_readout_entry = tk.Entry(self.base_frame, width=10)
self.axis_2_readout_entry.insert(0, 0)
self.axis_2_readout_entry.config(state='readonly')
self.axis_2_readout_entry.grid(row=row, column=4)


class ThreeAxisApplicationView():
'''
Application control for two-axis movement
'''
def __init__(self, root_frame: tk.Frame, title: str, axis_1_label: str, axis_2_label: str, axis_3_label: str):

# Frame to house this subwindow
self.base_frame = tk.Frame(root_frame)
self.base_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=4, pady=8)


row = 0
tk.Label(self.base_frame, text=title, font='Helvetica 14').grid(row=row, column=0, pady=[0,5], columnspan=5)

row += 1
# Enable/disable the stepper
self.stepping_active = tk.IntVar()
self.stepping_laser_toggle = tk.Checkbutton ( self.base_frame, var=self.stepping_active, text='Enable stepping')
self.stepping_laser_toggle.grid(row=row, column=0, pady=[0,0], columnspan=2)
tk.Label(self.base_frame, text='Set value', font='Helvetica 10', width=10).grid(row=row, column=2, pady=[0,0], columnspan=1)
tk.Label(self.base_frame, text='Step', font='Helvetica 10', width=10).grid(row=row, column=3, pady=[0,0], columnspan=1)
tk.Label(self.base_frame, text='Current', font='Helvetica 10', width=10).grid(row=row, column=4, pady=[0,0], columnspan=1)

row += 1
tk.Label(self.base_frame, text=axis_1_label, font='Helvetica 10', width=10).grid(row=row, column=0, pady=[0,0], columnspan=1)
self.axis_1_set_button = tk.Button(self.base_frame, text='Set position', width=10)
self.axis_1_set_button.grid(row=row, column=1, columnspan=1, padx=0)
self.axis_1_set_entry = tk.Entry(self.base_frame, width=10)
self.axis_1_set_entry.insert(0, 0)
self.axis_1_set_entry.grid(row=row, column=2)
self.axis_1_step_entry = tk.Entry(self.base_frame, width=10)
self.axis_1_step_entry.insert(0, 0)
self.axis_1_step_entry.grid(row=row, column=3)
self.axis_1_readout_entry = tk.Entry(self.base_frame, width=10)
self.axis_1_readout_entry.insert(0, 0)
self.axis_1_readout_entry.config(state='readonly')
self.axis_1_readout_entry.grid(row=row, column=4)

row += 1
tk.Label(self.base_frame, text=axis_2_label, font='Helvetica 10', width=10).grid(row=row, column=0, pady=[0,0], columnspan=1)
self.axis_2_set_button = tk.Button(self.base_frame, text='Set position', width=10)
self.axis_2_set_button.grid(row=row, column=1, columnspan=1, padx=0)
self.axis_2_set_entry = tk.Entry(self.base_frame, width=10)
self.axis_2_set_entry.insert(0, 0)
self.axis_2_set_entry.grid(row=row, column=2)
self.axis_2_step_entry = tk.Entry(self.base_frame, width=10)
self.axis_2_step_entry.insert(0, 0)
self.axis_2_step_entry.grid(row=row, column=3)
self.axis_2_readout_entry = tk.Entry(self.base_frame, width=10)
self.axis_2_readout_entry.insert(0, 0)
self.axis_2_readout_entry.config(state='readonly')
self.axis_2_readout_entry.grid(row=row, column=4)

row += 1
tk.Label(self.base_frame, text=axis_3_label, font='Helvetica 10', width=10).grid(row=row, column=0, pady=[0,0], columnspan=1)
self.axis_3_set_button = tk.Button(self.base_frame, text='Set position', width=10)
self.axis_3_set_button.grid(row=row, column=1, columnspan=1, padx=0)
self.axis_3_set_entry = tk.Entry(self.base_frame, width=10)
self.axis_3_set_entry.insert(0, 0)
self.axis_3_set_entry.grid(row=row, column=2)
self.axis_3_step_entry = tk.Entry(self.base_frame, width=10)
self.axis_3_step_entry.insert(0, 0)
self.axis_3_step_entry.grid(row=row, column=3)
self.axis_3_readout_entry = tk.Entry(self.base_frame, width=10)
self.axis_3_readout_entry.insert(0, 0)
self.axis_3_readout_entry.config(state='readonly')
self.axis_3_readout_entry.grid(row=row, column=4)
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
QDLMOVE:
Positioners: # Add positioner configs defiend below; edit the GUI/application accordingly.
- MicroX
- MicroY
- PiezoX
- PiezoY
- PiezoZ

MicroX:
import_path : qt3utils.applications.qdlmove.newportmicrometer
class_name : NewportMicrometer
configure :
port: COM4 # Serial port name
min: 0.0 # Minimum position in microns
max: 25000.0 # Maximum position in microns
timeout: 10 # Time in seconds before timing out on movement

MicroY:
import_path : qt3utils.applications.qdlmove.newportmicrometer
class_name : NewportMicrometer
configure :
port: COM5 # Serial port name
min: 0.0 # Minimum position in microns
max: 25000.0 # Maximum position in microns
timeout: 10 # Time in seconds before timing out on movement

PiezoX:
import_path : qt3utils.applications.qdlmove.nidaqpiezo
class_name : NiDaqPiezoController
configure:
device_name: Dev1
write_channel: ao0
read_channel:
move_settle_time: 0.0 # Time in seconds to wait after movement
scale_microns_per_volt: 8 # Number of microns moved per volt
zero_microns_volt_offset: 5 # Value of voltage at position 0 microns
min_position: -40.0 # Minimum position in microns
max_position: 40.0 # Maximum position in microns
invert_axis: True # If True, modifies scale and offset internally to invert axis

PiezoY:
import_path : qt3utils.applications.qdlmove.nidaqpiezo
class_name : NiDaqPiezoController
configure:
device_name: Dev1
write_channel: ao1
read_channel:
move_settle_time: 0.0
scale_microns_per_volt: 8
zero_microns_volt_offset: 5
min_position: -40.0
max_position: 40.0
invert_axis: True

PiezoZ:
import_path : qt3utils.applications.qdlmove.nidaqpiezo
class_name : NiDaqPiezoController
configure:
device_name: Dev1
write_channel: ao2
read_channel:
move_settle_time: 0.0
scale_microns_per_volt: 8
zero_microns_volt_offset: 5
min_position: -40.0
max_position: 40.0
invert_axis: True
Loading

0 comments on commit 74eb97d

Please sign in to comment.