Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@

from typing import Union, List, Dict
from pymodaq.control_modules.move_utility_classes import (DAQ_Move_base, comon_parameters_fun,
main, DataActuatorType, DataActuator)

from pymodaq_utils.utils import ThreadCommand # object used to send info back to the main thread
from pymodaq_gui.parameter import Parameter

from pymodaq_plugins_teaching.hardware.spectrometer import Spectrometer

# TODO:
# (1) change the name of the following class to DAQ_Move_TheNameOfYourChoice
# (2) change the name of this file to daq_move_TheNameOfYourChoice ("TheNameOfYourChoice" should be the SAME
# for the class name and the file name.)
# (3) this file should then be put into the right folder, namely IN THE FOLDER OF THE PLUGIN YOU ARE DEVELOPING:
# pymodaq_plugins_my_plugin/daq_move_plugins
class DAQ_Move_Monochromator(DAQ_Move_base):
""" Instrument plugin class for an actuator.

This object inherits all functionalities to communicate with PyMoDAQ’s DAQ_Move module through inheritance via
DAQ_Move_base. It makes a bridge between the DAQ_Move module and the Python wrapper of a particular instrument.

TODO Complete the docstring of your plugin with:
* The set of controllers and actuators that should be compatible with this instrument plugin.
* With which instrument and controller it has been tested.
* The version of PyMoDAQ during the test.
* The version of the operating system.
* Installation instructions: what manufacturer’s drivers should be installed to make it run?

Attributes:
-----------
controller: object
The particular object that allow the communication with the hardware, in general a python wrapper around the
hardware library.

# TODO add your particular attributes here if any

"""
is_multiaxes = False # TODO for your plugin set to True if this plugin is controlled for a multiaxis controller
_axis_names: Union[List[str], Dict[str, int]] = [''] # TODO for your plugin: complete the list
_controller_units: Union[str, List[str]] = 'nm' # TODO for your plugin: put the correct unit here, it could be
# TODO a single str (the same one is applied to all axes) or a list of str (as much as the number of axes)
_epsilon: Union[float, List[float]] = 0.1 # TODO replace this by a value that is correct depending on your controller
# TODO it could be a single float of a list of float (as much as the number of axes)
data_actuator_type = DataActuatorType.DataActuator # wether you use the new data style for actuator otherwise set this
# as DataActuatorType.float (or entirely remove the line)

params = [ {'title': 'info:', 'name': 'info', 'type': 'str', 'value': '', 'readonly': True},
{'title': 'grating:', 'name': 'grating', 'type': 'list', 'value' : Spectrometer.gratings[0] , 'limits': Spectrometer.gratings},
{'title': 'tau:', 'name': 'tau', 'type': 'float', 'value': 0.0}# TODO for your custom plugin: elements to be added here as dicts in order to control your custom stage
] + comon_parameters_fun(is_multiaxes, axis_names=_axis_names, epsilon=_epsilon)
# _epsilon is the initial default value for the epsilon parameter allowing pymodaq to know if the controller reached
# the target value. It is the developer responsibility to put here a meaningful value

def ini_attributes(self):
# TODO declare the type of the wrapper (and assign it to self.controller) you're going to use for easy
# autocompletion
self.controller: Spectrometer = None

#TODO declare here attributes you want/need to init with a default value
pass

def get_actuator_value(self):
"""Get the current value from the hardware with scaling conversion.

Returns
-------
float: The position obtained after scaling conversion.
"""
## TODO for your custom plugin
# raise NotImplemented # when writing your own plugin remove this line
pos = DataActuator(data=self.controller.get_wavelength(),
units='nm') # when writing your own plugin replace this line
pos = self.get_position_with_scaling(pos)
return pos

def user_condition_to_reach_target(self) -> bool:
""" Implement a condition for exiting the polling mechanism and specifying that the
target value has been reached

Returns
-------
bool: if True, PyMoDAQ considers the target value has been reached
"""
# TODO either delete this method if the usual polling is fine with you, but if need you can
# add here some other condition to be fullfilled either a completely new one or
# using or/and operations between the epsilon_bool and some other custom booleans
# for a usage example see DAQ_Move_brushlessMotor from the Thorlabs plugin
return True

def close(self):
"""Terminate the communication protocol"""
## TODO for your custom plugin
# raise NotImplemented # when writing your own plugin remove this line
if self.is_master:
self.controller.close_communication() # when writing your own plugin replace this line

def commit_settings(self, param: Parameter):
"""Apply the consequences of a change of value in the detector settings

Parameters
----------
param: Parameter
A given parameter (within detector_settings) whose value has been changed by the user
"""
## TODO for your custom plugin
if param.name() == 'axis':
self.axis_unit = self.controller.get_wavelength_axis()
# do this only if you can and if the units are not known beforehand, for instance
# if the motors connected to the controller are of different type (mm, µm, nm, , etc...)
# see BrushlessDCMotor from the thorlabs plugin for an exemple

elif param.name() == "grating":
self.controller.grating = param.value()
self.get_actuator_value()
else:
pass

def ini_stage(self, controller=None):
"""Actuator communication initialization

Parameters
----------
controller: (object)
custom object of a PyMoDAQ plugin (Slave case). None if only one actuator by controller (Master case)

Returns
-------
info: str
initialized: bool
False if initialization failed otherwise True
"""

self.ini_stage_init(slave_controller=controller) # will be useful when controller is slave

if self.is_master: # is needed when controller is master
self.controller = Spectrometer() # arguments for instantiation!)
initialized = self.controller.open_communication() # TODO
else:
self.controller = controller
initialized = True

# todo: enter here whatever is needed for your controller initialization and eventual
# opening of the communication channel

info = "Whatever info you want to log"

self.settings.child("info").setValue(self.controller.infos)
return info, initialized

def move_abs(self, value: DataActuator):
""" Move the actuator to the absolute target defined by value

Parameters
----------
value: (float) value of the absolute target positioning
"""

value = self.check_bound(value) #if user checked bounds, the defined bounds are applied here
self.target_value = value
value = self.set_position_with_scaling(value) # apply scaling if the user specified one
## TODO for your custom plugin

self.controller.set_wavelength(value.value('nm'), 'abs') # when writing your own plugin replace this line
self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log']))

def move_rel(self, value: DataActuator):
""" Move the actuator to the relative target actuator value defined by value

Parameters
----------
value: (float) value of the relative target positioning
"""
value = self.check_bound(self.current_position + value) - self.current_position
self.target_value = value + self.current_position
value = self.set_position_relative_with_scaling(value)

## TODO for your custom plugin

self.controller.set_wavelength(value.value(self.axis_unit), 'rel') # when writing your own plugin replace this line
self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log']))

def move_home(self):
"""Call the reference method of the controller"""

## TODO for your custom plugin

self.move_abs(532, 'nm') # when writing your own plugin replace this line
self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log']))

def stop_motion(self):
"""Stop the actuator and emits move_done signal"""

## TODO for your custom plugin

self.controller.stop() # when writing your own plugin replace this line
self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log']))


if __name__ == '__main__':
main(__file__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import numpy as np

from pymodaq_utils.utils import ThreadCommand
from pymodaq_data.data import DataToExport
from pymodaq_gui.parameter import Parameter

from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base, comon_parameters, main
from pymodaq.utils.data import DataFromPlugins

from pymodaq_plugins_teaching.hardware.spectrometer import Spectrometer

class PythonWrapperOfYourInstrument:
# TODO Replace this fake class with the import of the real python wrapper of your instrument
pass

# TODO:
# (1) change the name of the following class to DAQ_0DViewer_TheNameOfYourChoice
# (2) change the name of this file to daq_0Dviewer_TheNameOfYourChoice ("TheNameOfYourChoice" should be the SAME
# for the class name and the file name.)
# (3) this file should then be put into the right folder, namely IN THE FOLDER OF THE PLUGIN YOU ARE DEVELOPING:
# pymodaq_plugins_my_plugin/daq_viewer_plugins/plugins_0D

class DAQ_0DViewer_Photodiode(DAQ_Viewer_base):
""" Instrument plugin class for a OD viewer.

This object inherits all functionalities to communicate with PyMoDAQ’s DAQ_Viewer module through inheritance via
DAQ_Viewer_base. It makes a bridge between the DAQ_Viewer module and the Python wrapper of a particular instrument.

TODO Complete the docstring of your plugin with:
* The set of instruments that should be compatible with this instrument plugin.
* With which instrument it has actually been tested.
* The version of PyMoDAQ during the test.
* The version of the operating system.
* Installation instructions: what manufacturer’s drivers should be installed to make it run?

Attributes:
-----------
controller: object
The particular object that allow the communication with the hardware, in general a python wrapper around the
hardware library.

# TODO add your particular attributes here if any

"""
params = comon_parameters+[
## TODO for your custom plugin: elements to be added here as dicts in order to control your custom stage
]

def ini_attributes(self):
# TODO declare the type of the wrapper (and assign it to self.controller) you're going to use for easy
# autocompletion
self.controller: Spectrometer = None

#TODO declare here attributes you want/need to init with a default value
pass

def commit_settings(self, param: Parameter):
"""Apply the consequences of a change of value in the detector settings

Parameters
----------
param: Parameter
A given parameter (within detector_settings) whose value has been changed by the user
"""
## TODO for your custom plugin
if param.name() == "a_parameter_you've_added_in_self.params":
self.controller.your_method_to_apply_this_param_change() # when writing your own plugin replace this line
# elif ...
##

def ini_detector(self, controller=None):
"""Detector communication initialization

Parameters
----------
controller: (object)
custom object of a PyMoDAQ plugin (Slave case). None if only one actuator/detector by controller
(Master case)

Returns
-------
info: str
initialized: bool
False if initialization failed otherwise True
"""

if self.is_master:
self.controller = Spectrometer() #instantiate you driver with whatever arguments are needed
self.controller.open_communication() # call eventual methods
initialized = self.controller.open_communication() # TODO
else:
self.controller = controller
initialized = True

info = "Whatever info you want to log"

return info, initialized

def close(self):
"""Terminate the communication protocol"""
## TODO for your custom plugin
if self.is_master:
self.controller.close_communication() # when writing your own plugin replace this line

def grab_data(self, Naverage=1, **kwargs):
"""Start a grab from the detector

Parameters
----------
Naverage: int
Number of hardware averaging (if hardware averaging is possible, self.hardware_averaging should be set to
True in class preamble and you should code this implementation)
kwargs: dict
others optionals arguments
"""
## TODO for your custom plugin: you should choose EITHER the synchrone or the asynchrone version following

# synchrone version (blocking function)
data_tot = self.controller.grab_monochromator()
self.dte_signal.emit(DataToExport(name='myplugin',
data=[DataFromPlugins(name='Mock1', data=data_tot,
dim='Data0D', labels=['dat0', 'data1'])]))
#########################################################

def stop(self):
"""Stop the current grab hardware wise if necessary"""
## TODO for your custom plugin
self.controller.stop() # when writing your own plugin replace this line
self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log']))
##############################
return ''


if __name__ == '__main__':
main(__file__)
Loading