Skip to content

Andor iDus #5

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

Merged
merged 16 commits into from
Aug 9, 2024
Merged
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
10 changes: 9 additions & 1 deletion docs/api/instruments/thyracont/smartline_v2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ Smartline V2 Transmitter Series
:members:
:show-inheritance:

.. autoclass:: pymeasure.instruments.thyracont.smartline_v2.VSR
.. autoclass:: pymeasure.instruments.thyracont.smartline_v2.VSM
:members:
:show-inheritance:

.. autoclass:: pymeasure.instruments.thyracont.smartline_v2.VSP
:members:
:show-inheritance:

.. autoclass:: pymeasure.instruments.thyracont.smartline_v2.VSR
:members:
:show-inheritance:
4 changes: 2 additions & 2 deletions docs/tutorial/procedure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ Storing metadata
~~~~~~~~~~~~~~~~

Metadata (:class:`pymeasure.experiment.parameters.Metadata`) allows storing information (e.g. the actual starting time, instrument parameters) about the measurement in the header of the datafile.
These Metadata objects are evaluated and stored in the datafile only after the :python:`startup` method has ran; this way it is possible to e.g. retrieve settings from an instrument and store them in the file.
These Metadata objects are evaluated and stored in the datafile only after the :python:`startup` method has run; this way it is possible to e.g. retrieve settings from an instrument and store them in the file.
Using a Metadata is nearly as straightforward as using a Parameter; extending the example of above to include metadata, looks as follows: ::

from time import sleep, time
Expand Down Expand Up @@ -303,7 +303,7 @@ Using a Metadata is nearly as straightforward as using a Parameter; extending th
As with a Parameter, PyMeasure swaps out the Metadata with their values behind the scene, which makes accessing the values of Metadata very convenient.

The value of a Metadata can be set either using an :python:`fget` method or manually in the startup method.
The :python:`fget` method, if provided, is ran after startup method.
The :python:`fget` method, if provided, is run after startup method.
It can also be provided as a string; in that case it is assumed that the string contains the name of an attribute (either a callable or not) of the Procedure class which returns the value that is to be stored.
This also allows to retrieve nested attributes (e.g. in order to store a property or method of an instrument) by separating the attributes with a period: e.g. `instrument_name.attribute_name` (or even `instrument_name.subclass_name.attribute_name`); note that here only the final element (i.e. `attribute_name` in the example) is allowed to refer to a callable.
If neither an :python:`fget` method is provided or a value manually set, the Metadata will return to its default value, if set.
Expand Down
25 changes: 25 additions & 0 deletions pymeasure/instruments/andor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#
# This file is part of the PyMeasure package.
#
# Copyright (c) 2013-2024 PyMeasure Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# 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.
#

from .idus401 import IDUS401
14 changes: 14 additions & 0 deletions pymeasure/instruments/andor/idus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#Driver code to command Andor Idus camera to take images

Check failure on line 1 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E265 block comment should start with '# '

Check warning on line 1 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W291 trailing whitespace

import logging
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())


from andor_dlls import *

Check warning on line 8 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

F403 'from andor_dlls import *' used; unable to detect undefined names

Check warning on line 8 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

F401 'andor_dlls.*' imported but unused

Check failure on line 8 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E402 module level import not at top of file

class AndorIdus():

Check failure on line 10 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E302 expected 2 blank lines, found 1

Check warning on line 10 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W291 trailing whitespace
def __init__(self, camera_name):

Check warning on line 11 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W291 trailing whitespace
self.camera_name = "" #must add camera name

Check failure on line 12 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E261 at least two spaces before inline comment

Check failure on line 12 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E262 inline comment should start with '# '
self.camera = None
self.initialize_camera()

Check warning on line 14 in pymeasure/instruments/andor/idus.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W292 no newline at end of file
116 changes: 116 additions & 0 deletions pymeasure/instruments/andor/idus401.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#Purpose: Driver code to command Andor Idus camera to take images. Methods added have error codes for debugging purposes.

Check failure on line 1 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E265 block comment should start with '# '

Check failure on line 1 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E501 line too long (121 > 100 characters)

Check warning on line 1 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W291 trailing whitespace
import logging
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

from andor_dlls.AndorSDK.Python.pyAndorSDK2.pyAndorSDK2.atmcd import atmcd

Check failure on line 6 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E402 module level import not at top of file
from andor_dlls.AndorSDK.Python.pyAndorSDK2.pyAndorSDK2.atmcd_errors import Error_Codes

Check failure on line 7 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E402 module level import not at top of file

class IDUS401():

Check failure on line 9 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

E302 expected 2 blank lines, found 1

Check warning on line 9 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W291 trailing whitespace
"""Class to control Andor Indus Camera"""
def __init__(self):
self.camera = atmcd() #calls atmcd class from atmcd.py
self.camera._load_library(r"C:\Users\desha\Codes\andor_dlls\AndorSDK\Python\pyAndorSDK2\pyAndorSDK2\libs\Windows\64") #add path to dll file
self.camera.SetTemperature = -100
log.info(f" Available cameras: {self.camera.GetAvailableCameras()}")
serial_number = self.camera.GetCameraSerialNumber()
log.info(f"Camera initialized with serial number {serial_number}")
self.camera.Initialize(serial_number)

Check warning on line 19 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W293 blank line contains whitespace
def set_camera(self, index):
"""Sets the current camera and initialize based on the index list"""
self.camera.SetCurrentCamera(index)
serial_number = self.camera.GetCameraSerialNumber(index)
log.info(f"Camera set to {serial_number}")
error_code = self.camera.Initialize(serial_number)
self.check_for_errors(error_code)
log.info("Camera initialized")

Check warning on line 28 in pymeasure/instruments/andor/idus401.py

View workflow job for this annotation

GitHub Actions / Docs and Linting

W293 blank line contains whitespace
def set_temperature(self, temperature):
"""Sets the temperature of the camera in Celsius"""
error_code = self.camera.CoolerON()
self.check_for_errors(error_code)
log.info("Cooler is on")

temperature_range = self.camera.GetTemperatureRange()
if temperature_range[0] <= temperature <= temperature_range[1]:
error_code = self.camera.SetTemperature(temperature)
self.check_for_errors(error_code)
log.info(f"Temperature set to {temperature}")

def get_temperature(self):
"""Returns the temperature of the camera in Celsius"""
temperature = self.camera.GetTemperature()
self.check_for_errors(temperature)
return temperature

def set_cooler_mode(self, cooler_mode):
"""Sets cooler mode based on shutdown status.
0 -> Returns to ambient temperature at shutdown
1 -> Maintains temperature at shutdown"""
error_code = self.camera.SetCoolerMode(cooler_mode)
self.check_for_errors(error_code)

def cooler_off(self):
"""Cooler is turned off"""
error_code = self.camera.CoolerOFF()
self.check_for_errors(error_code)
log.info("Cooler is off")

def set_exposure_time(self, exposure_time):
"""Sets the exposure time of the camera in seconds"""
exposure_time = 0.01 #placeholder
error_code = self.camera.SetExposureTime(exposure_time)
self.check_for_errors(error_code)
log.ifo(f"Exposure time set to {exposure_time}")

def set_camera(self,acquisition_mode):
"""Sets the cameras mode.
1 -> Single scan
2 -> Accumulate
3 -> Kinetics
4 -> Fast Kinetics
5 -> Run till abort"""
error_code = self.camera.SetAcquisitionMode(acquisition_mode)
self.check_for_errors(error_code)

def set_read_mode(self, read_mode):
"""Sets the read mode of the camera
0 -> Full Vertical Binning
1 -> Multi-Track
2 -> Random-Track
3 -> Single-Track
4 -> Image"""
error_code = self.camera.SetReadMode(read_mode)
self.check_for_errors(error_code)

def set_trigger_mode(self, trigger_mode):
"""Sets the trigger mode of the camera
0 -> internal
1 -> External
6 -> External Start
7 -> External Exposure (Bulb)
9 -> External FVB EM (only valid for EM Newton models in FVB mode)
10 -> Software Trigger
12 -> External Charge Shifting"""
error_code = self.camera.SetTriggerMode(trigger_mode)
self.check_for_errors(error_code)


def acquistion(self):
"""Acquires the image data in an np array"""
data = self.camera.acquire()
self.check_for_errors(data)
return data

def shutdown(self):
"""Shuts down the camera"""
error_code = self.camera.ShutDown()
self.check_for_errors(error_code)
log.info("Camera shutdown")

def check_for_errors(self, error_code):
"""Checks for errors on commands"""
if error_code != Error_Codes.DRV_SUCCESS:
log.error(f"Error code {error_code}")
raise Exception(f"Error code: {error_code}")
2 changes: 1 addition & 1 deletion pymeasure/instruments/thyracont/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
#

from .smartline_v1 import SmartlineV1
from .smartline_v2 import SmartlineV2, VSR, VSH
from .smartline_v2 import SmartlineV2, VSH, VSM, VSP, VSR
13 changes: 13 additions & 0 deletions pymeasure/instruments/thyracont/smartline_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,21 @@ class VSH(SmartlineV2):
hotcathode = Instrument.ChannelCreator(HotCathode)


class VSM(SmartlineV2):
"""Vacuum transmitter of VSM series with both piece and cold cathode sensor."""

piezo = Instrument.ChannelCreator(Piezo)
coldcathode = Instrument.ChannelCreator(ColdCathode)


class VSR(SmartlineV2):
"""Vacuum transmitter of VSR/VCR series with both a piezo and a pirani sensor."""

piezo = Instrument.ChannelCreator(Piezo)
pirani = Instrument.ChannelCreator(Pirani)


class VSP(SmartlineV2):
"""Vacuum transmitter of VSP/VCP series with a piezo sensor."""

piezo = Instrument.ChannelCreator(Piezo)
36 changes: 36 additions & 0 deletions tests/instruments/andor/idus401_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Test code for Andor iDus camera

import pytest

from pymeasure.test import expected_protocol
from pymeasure.instruments.andor.idus401 import IDUS401


def test_set_camera():
with expected_protocol(
IDUS401,
[("SetCurrentCamera", 1),
("GetCameraSerialNumber", 12345),
("Initialize", None),
],
) as inst:
inst.set_camera(1)


def test_set_temperature():
with expected_protocol(
IDUS401,
[("CoolerON", None),
("GetTemperatureRange", (-100, 100)),
("SetTemperature", -50),
],
) as inst:
inst.set_temperature(-50)

def test_set_exposure_time():
with expected_protocol(
IDUS401,
[("SetExposureTime", 0.5),
],
) as inst:
inst.set_exposure_time(0.5)
Loading