Skip to content

Commit

Permalink
Merge pull request #99 from SweepMe/driver_contribution_jw
Browse files Browse the repository at this point in the history
Driver contribution jw
  • Loading branch information
afischer-sweepme authored Oct 22, 2024
2 parents f6889b1 + cab907a commit 5586a25
Show file tree
Hide file tree
Showing 8 changed files with 549 additions and 403 deletions.
6 changes: 3 additions & 3 deletions src/LockIn-Stanford_SR830/license.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ find those in the corresponding folders or contact the maintainer.

MIT License

Copyright (c) 2021-2023 SweepMe! GmbH (sweep-me.net)
Copyright (c) 2021-2024 SweepMe! GmbH (sweep-me.net)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -25,5 +25,5 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

We like to thank Jakob Wolansky/TU Dresden for contributing to the improvement
of the driver.
Contribution: We like to thank Jakob Wolansky/TU Dresden for contributing
to the improvement of the driver.
281 changes: 180 additions & 101 deletions src/LockIn-Stanford_SR830/main.py

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/Monochromator-QuantumDesign_MSH-300/license.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ find those in the corresponding folders or contact the maintainer.

MIT License

Copyright (c) 2022 SweepMe! GmbH (sweep-me.net)
Copyright (c) 2024 SweepMe! GmbH (sweep-me.net)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -25,4 +25,5 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Contribution: We like to thank TU Dresden (Toni Bärschneider and Jakob Wolansky) for providing the initial version of this driver.
Contribution: We like to thank TU Dresden (Toni Bärschneider and Jakob Wolansky)
for providing the initial version of this driver.
29 changes: 21 additions & 8 deletions src/Monochromator-QuantumDesign_MSH-300/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# MIT License

# Copyright (c) 2022 SweepMe! GmbH (sweep-me.net)
# Copyright (c) 2024 SweepMe! GmbH (sweep-me.net)

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand All @@ -29,9 +29,9 @@
# Contribution: We like to thank TU Dresden (Toni Bärschneider and Jakob Wolansky) for
# providing the initial version of this driver.

# SweepMe! device class
# Type: Monochromator
# Device: Quantum Design MSH-300
# SweepMe! driver
# * Module: Monochromator
# * Instrument: Quantum Design MSH-300

import time
import ctypes
Expand All @@ -44,7 +44,7 @@

from collections import OrderedDict

import FolderManager
from pysweepme import FolderManager
FoMa = FolderManager.FolderManager()
FolderManager.addFolderToPATH()

Expand Down Expand Up @@ -142,10 +142,10 @@ def __init__(self):
def set_GUIparameter(self):

gui_parameter = {
"SweepMode": ["Wavelength in nm", "None"], # "Reflection (zero order)", "Slitwidth [µm]" needs additional fix wavelength option
"SweepMode": ["Wavelength in nm", "Energy in eV", "None"],
"EndPosition": "",
"Input": list(self.slitinputs.keys()), # TODO: Is this self.inport?
"Output": list(self.slitoutputs.keys()), # TODO: Is this self.outport?
"Input": list(self.slitinputs.keys()),
"Output": list(self.slitoutputs.keys()),
"Filter": ["Auto"] + self.filters,
"Grating": ["Auto"] + self.gratings,
# "SlitOutput": ["2000 (max)", "1500", "6 (min)"],
Expand Down Expand Up @@ -308,8 +308,21 @@ def unconfigure(self):
def apply(self):

if self.sweep_mode.startswith("Wavelength"):
# if self.value is below than 10, it's probably an energy and not a wavelength
if float(self.value) < 10:
raise Exception("Check sweepmode. Wavelength expected, but probably energy received.")
# Based on the wavelength the grating and the filter will be chosen automatically
self.set_wavelength(self.value)

elif self.sweep_mode.startswith("Energy"):
if float(self.value)>100:
self.set_wavelength(self.value)
else:
# conversion from eV to nm
c = 2.99792e8 # speed of light in m/s
p = 4.135667e-15 # Planck constant in eV·s
wavelength_to_set = round(float(p*c/(float(self.value)))*1e9, 3)
self.set_wavelength(wavelength_to_set)

def measure(self):

Expand Down
2 changes: 1 addition & 1 deletion src/Switch-Acton_FA-448/license.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ find those in the corresponding folders or contact the maintainer.

MIT License

Copyright (c) 2021 SweepMe! GmbH
Copyright (c) 2024 SweepMe! GmbH (sweep-me.net)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
131 changes: 75 additions & 56 deletions src/Switch-Acton_FA-448/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# MIT License

# Copyright (c) 2021 SweepMe! GmbH
# Copyright (c) 2024 SweepMe! GmbH (sweep-me.net)

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand All @@ -27,30 +27,30 @@

# Contribution: We like to thank TU Dresden/Jakob Wolansky for providing the initial version of this driver.

# SweepMe! device class
# Type: Switch
# Device: Acton FA-448
# SweepMe! driver
# * Module: Switch
# * Instrument: Acton FA-448

from EmptyDeviceClass import EmptyDevice #sweepMe base class
from pysweepme.EmptyDeviceClass import EmptyDevice
import numpy as np

import time

class Device(EmptyDevice):

description = """
<p><strong>Usage:</strong></p>
<ul>
<li>If Sweep mode == "Position", the selected Sweep value is used.</li>
<li>If Sweep mode == "Wavelength in nm", the filter is selected in accordance to the 'Filter position'.</li>
<li>If Sweep mode == "Energy in eV", the filter is selected in accordance to the 'Filter position'.</li>
To define custom filter and grating ranges, copy the template file Switch-Acton_FA-448.ini inside this driver folder to the "CustomFiles" folder of your public SweepMe! folder.<br>
Define your own filter-wavelength dependencies using the format:<br>
wl -> filter slot &lt;- wl -> filter slot &lt;- wl
<li>If Sweep mode == "None", the position given in the field 'Value' is used, if button apply is pressed. It can be used as convenience setting for when no sweep is made (equivalent to one value sweep)</li>
<li>If button "Apply" is pressed, the position given in the field 'Value' is set except for Sweep Mode "Energy in eV"</li>
<li>Home position: position to return to at end of program ("None" = stay) or after pressing "Stop"</li>
"""
<p><strong>Usage:</strong></p>
<ul>
<li>If Sweep mode == "Position", the selected Sweep value is used.</li>
<li>If Sweep mode == "Wavelength in nm", the filter is selected in accordance to the 'Filter position'.</li>
<li>If Sweep mode == "Energy in eV", the filter is selected in accordance to the 'Filter position'.</li>
To define custom filter and grating ranges, copy the template file Switch-Acton_FA-448.ini inside this driver folder to the "CustomFiles" folder of your public SweepMe! folder.<br>
Define your own filter-wavelength dependencies using the format:<br>
wl -> filter slot &lt;- wl -> filter slot &lt;- wl
<li>If Sweep mode == "None", the position given in the field 'Value' is used, if button apply is pressed. It can be used as convenience setting for when no sweep is made (equivalent to one value sweep)</li>
<li>If button "Apply" is pressed, the position given in the field 'Value' is set except for Sweep Mode "Energy in eV"</li>
<li>Home position: position to return to at end of program ("None" = stay) or after pressing "Stop"</li>
"""

def __init__(self):

Expand All @@ -61,14 +61,13 @@ def __init__(self):

self.variables = ["Position"]
self.units = ["#"]
self.plottype = [True] # True to plot data
self.savetype = [False] # True to save data
self.plottype = [True] # True to plot data
self.savetype = [True] # True to save data

# Filter positions
self.positions = ["1","2","3","4","5","6"]
# loads from further Filter configurations from Switch-Acton_FA-448.ini that is expected in public folder "CustomFiles"
self.positions_to_add = list(self.get_configoptions("Filter").values())

self.positions = ["1", "2", "3", "4", "5", "6"]
# loads further filter options from Switch-Acton_FA-448.ini that is expected in public folder "CustomFiles"
self.positions_to_add = list(self.getConfigOptions("Filter").values())

self.port_manager = True
self.port_types = ["GPIB", "COM"]
Expand All @@ -80,14 +79,14 @@ def __init__(self):

def set_GUIparameter(self):


GUIparameter = {
"Filter position" : self.positions + self.positions_to_add,
"Home position" : ["None"] + self.positions,
"SweepMode": ["Position", "None", "Wavelength in nm", "Energy in eV"],
}
gui_parameter = {
"Filter position" : self.positions + self.positions_to_add,
"Home position" : ["None"] + self.positions,
"SweepMode": ["Position", "None", "Wavelength in nm", "Energy in eV"],
"Configuration": "",
}

return GUIparameter
return gui_parameter

def get_GUIparameter(self, parameter={}):

Expand All @@ -96,11 +95,12 @@ def get_GUIparameter(self, parameter={}):
self.pos = (parameter["Filter position"])
self.filter_readout = self.pos.replace("<", "").replace(">", "").replace("nm", "").replace(" ", "").split("-")

self.pos_list = np.array(self.filter_readout[::2], dtype = int)
self.filter_wavelengths = np.array(self.filter_readout[1::2], dtype = float)
self.pos_list = np.array(self.filter_readout[::2], dtype=int)
self.filter_wavelengths = np.array(self.filter_readout[1::2], dtype=float)

self.home = parameter["Home position"]


self.config = parameter["Configuration"]

def connect(self):
# figure out early whether a connection is established
Expand All @@ -111,11 +111,14 @@ def disconnect(self):
pass

def initialize(self):
''' set instrument at GUI selected state and ready for next commands'''
"""Set instrument at GUI selected state and ready for next commands"""
if len(self.config) > 1:
msg = "Please use a single filter in field 'Configuration' if you choose Set value."
raise Exception(msg)
if self.sweepmode == "None":
if len(self.pos_list) > 1:
self.stop_Measurement("Please use a single filter in field 'Filter position' if Sweep mode is None.")
return False
msg = "Please use a single filter in field 'Filter position' if Sweep mode is None."
raise Exception(msg)

def deinitialize(self):
if self.home != "None":
Expand All @@ -131,6 +134,8 @@ def deinitialize(self):
"""
self.port.write("FHOME")
self.port.write("?Filter")
answer = self.port.read()

# set individual home position
self.port.write(str(int(self.home)) + " Filter")
self.port.write("?Filter")
Expand All @@ -155,64 +160,78 @@ def unconfigure(self):
"""
self.port.write("FHOME")
self.port.write("?Filter")
answer = self.port.read()

# set individual home position
self.port.write(str(int(self.home)) + " Filter")
self.port.write("?Filter")
answer = self.port.read()

def apply(self):
# if set value is not a filter position, return error
if self.sweepmode != "Wavelength in nm" and self.sweepmode != "Energy in eV" and not str(int(self.value)) in self.positions:
self.stop_Measurement("Filter position %s not in 1-6 range" % str(int(self.value)))
return False
if (self.sweepmode != "Wavelength in nm" and self.sweepmode != "Energy in eV"
and not str(int(self.value)) in self.positions):
msg = "Filter position %s not in 1-6 range" % str(int(self.value))
raise Exception(msg)

if self.sweepmode == "Position":
self.port.write(str(int(self.value)) + " Filter")
# for apply case: to confirm the latest command, send "?Filter" command
self.port.write("?Filter")
answer = (self.port.read())

elif self.sweepmode == "Wavelength in nm":
# if self.value is below than 10, it's probably an energy and not a wavelength
if self.value < 10:
msg = "Check sweepmode. Wavelength expected, but probably energy or position received."
raise Exception(msg)

# do not send more than three digits after decimal separator
self.wavelength_to_set = round(float(self.value),3)
# Based on the wavelength the filter will be chosen
# 1. step: find the index at which between two wavelengths, the filter has to be changed
# 2. step: find the filter slot based on that index
filter_to_set = self.pos_list[np.sum(np.array(self.filter_wavelengths, dtype = float) < self.wavelength_to_set)]
# if apply is pressed and not run, then value in "configuration box" is set, otherwise the filter in accordance to the "filter position box" is set
filter_to_set = self.pos_list[np.sum(np.array(self.filter_wavelengths, dtype=float) < self.wavelength_to_set)]
# if apply is pressed and not run, then value in "configuration box" is set,
# otherwise the filter in accordance to the "filter position box" is set
if self.value in self.positions:
self.port.write(str(int(self.value)) + " Filter")
self.port.write("?Filter")
self.port.write("?Filter")
answer = (self.port.read())
else:
self.port.write(str(int(filter_to_set)) + " Filter")

elif self.sweepmode == "Energy in eV":
# if self.value is higher than 10, it's probably a wavelength and not an energy
if self.value > 10:
msg = "Check sweepmode. Energy expected, but probably wavelength received."
raise Exception(msg)
# if apply is pressed and not run, then value in "Values" is not set, if "Energy in eV" is selected

# do not send more than three digits after decimal separator
# change eV into nm
self.wavelength_to_set = round(float(4.135667e-15*2.99792e8/(float(self.value)*1e-9)),3)
# change eV into nm
c = 2.99792e8 # speed of light in m/s
p = 4.135667e-15 # Planck constant in eV·s
self.wavelength_to_set = round(float(p*c/(float(self.value)*1e-9)),3)
# Based on the wavelength the filter will be chosen
# 1. step: find the index at which between two wavelengths, the filter has to be changed
# 2. step: find the filter slot based on that index
filter_to_set = self.pos_list[np.sum(np.array(self.filter_wavelengths, dtype = float) < self.wavelength_to_set)]
self.port.write(str(int(filter_to_set)) + " Filter")
elif self.sweepmode == "None": #case for set value

elif self.sweepmode == "None": # case for set value
self.port.write(str(self.value) + " Filter")
# for apply case: to confirm the latest command, send "?Filter" command
self.port.write("?Filter")
answer = (self.port.read())

# for apply case: to confirm the latest command, send "?Filter" command
self.port.write("?Filter")
answer = self.port.read()

def reach(self):
# makes sure the new filter is reached before the next measurement is done
self.port.write("?Filter")
answer = (self.port.read())
answer = self.port.read()

def measure(self):
self.port.write("?Filter") # we ask for the filter in 'measure' and read the result in 'read_result', still necessary after each comment which was sent
# we ask for the filter in 'measure' and read the result in 'read_result'
self.port.write("?Filter")

def read_result(self):
self.answer = (self.port.read())
self.answer = self.port.read()

def call(self):
return self.answer
2 changes: 1 addition & 1 deletion src/Switch-Stanford_SR570/license.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ find those in the corresponding folders or contact the maintainer.

MIT License

Copyright (c) 2019-2023 SweepMe! GmbH (sweep-me.net)
Copyright (c) 2024 SweepMe! GmbH (sweep-me.net)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit 5586a25

Please sign in to comment.