diff --git a/src/pymodaq_plugins_teaching/daq_move_plugins/daq_move_Monochromator.py b/src/pymodaq_plugins_teaching/daq_move_plugins/daq_move_Monochromator.py new file mode 100644 index 0000000..f6ec05b --- /dev/null +++ b/src/pymodaq_plugins_teaching/daq_move_plugins/daq_move_Monochromator.py @@ -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__) diff --git a/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_0D/daq_0Dviewer_Photodiode.py b/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_0D/daq_0Dviewer_Photodiode.py new file mode 100644 index 0000000..946ee63 --- /dev/null +++ b/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_0D/daq_0Dviewer_Photodiode.py @@ -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__) diff --git a/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_1D/daq_1Dviewer_Spectrometer.py b/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_1D/daq_1Dviewer_Spectrometer.py new file mode 100644 index 0000000..2c94576 --- /dev/null +++ b/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_1D/daq_1Dviewer_Spectrometer.py @@ -0,0 +1,158 @@ +import numpy as np + +from pymodaq_utils.utils import ThreadCommand +from pymodaq_data.data import DataToExport, Axis +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_1DViewer_TheNameOfYourChoice +# (2) change the name of this file to daq_1Dviewer_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_1D + + +class DAQ_1DViewer_Spectrometer(DAQ_Viewer_base): + """ Instrument plugin class for a 1D 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 + + self.x_axis = None + + 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() +# 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 + initialized = self.controller.open_communication() # TODO + else: + self.controller = controller + initialized = True + + ## TODO for your custom plugin + # get the x_axis (you may want to to this also in the commit settings if x_axis may have changed + data_x_axis = self.controller.get_wavelength_axis() # if possible + self.x_axis = Axis(data=data_x_axis, label='wavelength', units='nm', index=0) + + + 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 + + data_x_axis = self.controller.get_wavelength_axis() # if possible + self.x_axis = Axis(data=data_x_axis, label='wavelength', units='nm', index=0) + + ##synchrone version (blocking function) + data_tot = self.controller.grab_spectrum() + self.dte_signal.emit(DataToExport('myplugin', + data=[DataFromPlugins(name='Mock1', data=data_tot, + dim='Data1D', labels=['dat0', 'data1'], + axes=[self.x_axis])])) + + + def callback(self): + """optional asynchrone method called when the detector has finished its acquisition of data""" + data_tot = self.controller.your_method_to_get_data_from_buffer() + data_x_axis = self.controller.get_wavelength_axis() # if possible + self.x_axis = Axis(data=data_x_axis, label='wavelength', units='nm', index=0) + self.dte_signal.emit(DataToExport('myplugin', + data=[DataFromPlugins(name='Mock1', data=data_tot, + dim='Data1D', 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__) diff --git a/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_1D/daq_1Dviewer_SpectrometerAndMoment.py b/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_1D/daq_1Dviewer_SpectrometerAndMoment.py new file mode 100644 index 0000000..75915d1 --- /dev/null +++ b/src/pymodaq_plugins_teaching/daq_viewer_plugins/plugins_1D/daq_1Dviewer_SpectrometerAndMoment.py @@ -0,0 +1,86 @@ +import numpy as np + +from pymodaq_utils.utils import ThreadCommand +from pymodaq_data.data import DataToExport, Axis +from pymodaq_gui.parameter import Parameter + +from pymodaq_utils.math_utils import my_moment + +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 + +from pymodaq_plugins_teaching.daq_viewer_plugins.plugins_1D.daq_1Dviewer_Spectrometer import DAQ_1DViewer_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_1DViewer_TheNameOfYourChoice +# (2) change the name of this file to daq_1Dviewer_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_1D + + +class DAQ_1DViewer_SpectrometerAndMoment(DAQ_1DViewer_Spectrometer): + """ Instrument plugin class for a 1D 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 + + """ + + 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 + + data_x_axis = self.controller.get_wavelength_axis() # if possible + self.x_axis = Axis(data=data_x_axis, label='wavelength', units='nm', index=0) + + ##synchrone version (blocking function) + spectrum = self.controller.grab_spectrum() + wavelength = self.controller.get_wavelength_axis() + + moments = my_moment(wavelength, spectrum) + moments_bis = my_moment(spectrum, wavelength) + + self.dte_signal.emit(DataToExport('myplugin', + data=[DataFromPlugins(name='Raw Spectrum', data=[spectrum], + dim='Data1D', labels=['label00'], + axes=[self.x_axis]), + DataFromPlugins(name='Moments', data=[np.atleast_1d(moments[0]), + ], + dim='Data0D', labels=["Mean"]), + DataFromPlugins(name='Moments 2', data=[np.atleast_1d(moments_bis[1])], + dim='Data0D', labels=["Std"]) + ])) + +if __name__ == '__main__': + main(__file__)