Completed
Pull Request — master (#380)
by
unknown
03:38
created

Camera.SetBinning()   A

Complexity

Conditions 4

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 4
dl 0
loc 9
rs 9.2
c 3
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#   AndoriDus - A Python wrapper for Andor's scientific cameras
3
#
4
#   Original code by
5
#   Copyright (C) 2009  Hamid Ohadi
6
#
7
#   Adapted for iDus, qtlab and Windows XP
8
#   2010 Martijn Schaafsma
9
#
10
#   Reworked by Simon Dickreuter 2016
11
#   Reworked by Alrik Durand 2018
12
#
13
#
14
#   This program is free software: you can redistribute it and/or modify
15
#   it under the terms of the GNU General Public License as published by
16
#   the Free Software Foundation, either version 3 of the License, or
17
#   (at your option) any later version.
18
#
19
#   This program is distributed in the hope that it will be useful,
20
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
21
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
#   GNU General Public License for more details.
23
#
24
#   You should have received a copy of the GNU General Public License
25
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
27
'''
28
This module offers basic functionality for the Andor Cameras
29
'''
30
31
# Modules for Andor functionality
32
import platform
33
import sys
34
import time
35
from ctypes import *
36
from .errorcodes import ERROR_CODE
37
38
39
class Camera():
40
    """
41
    Camera class which is meant to provide the Python version of the same
42
    functions that are defined in the Andor's SDK. Extensive documentation
43
    on the functions used and error codes can be
44
    found in the Andor SDK Users Guide
45
    """
46
47
    def __init__(self):
48
        '''
49
        Loads and initializes the hardware driver.
50
        Initializes local parameters
51
        '''
52
53
        # Check operating system and load library
54
        # for Windows
55
        if platform.system() == "Windows":
56
            if platform.architecture()[0] == "64bit":
57
                self._init_path = "C:\\Program Files\\Andor SOLIS\\"
58
                self._dll = cdll.LoadLibrary("C:\\Program Files\\Andor SOLIS\\atmcd64d_legacy")
59
            else:
60
                raise RuntimeError("Only 64bit Version is supported")
61
        # for Linux
62
        elif platform.system() == "Linux":
63
            #self._init_path = "/usr/local/etc/andor"
64
            self._init_path = ""
65
            dllname = "/usr/local/lib/libandor.so"
66
            self._dll = cdll.LoadLibrary(dllname)
67
        else:
68
            raise RuntimeError("Cannot detect operating system, will now stop")
69
70
       # Initiate parameters
71
72
        self._temperature  = None
73
        self._set_T        = None
74
        self._gain         = None
75
        self._gainRange    = None
76
        self._verbosity    = False
77
        self._preampgain   = None
78
        self._channel      = None
79
        self._outamp       = None
80
        self._hsspeed      = None
81
        self._vsspeed      = None
82
        self._serial       = None
83
        self._exposure     = None
84
        self._accumulate   = None
85
        self._kinetic      = None
86
        self._bitDepths    = []
87
        self._preAmpGain   = []
88
        self._VSSpeeds     = []
89
        self._noGains      = None
90
        self._imageArray   = []
91
        self._noVSSpeeds   = None
92
        self._HSSpeeds     = []
93
        self._noADChannels = None
94
        self._noHSSpeeds   = None
95
        self._ReadMode     = None
96
        self._cooling      = False
97
        self._on           = False
98
99
        # Initialize the device
100
        error = self.Initialize(self._init_path)
101
        if error == 20002:
102
            self.GetCameraSerialNumber()
103
            #print("Camera %s initalized" % (self._serial))
104
        else:
105
            raise RuntimeError("Camera could not be initialized, aborting.")
106
107
        self._status       = ERROR_CODE[error]
108
109
        cw = c_int()
110
        ch = c_int()
111
        self._dll.GetDetector(byref(cw), byref(ch))
112
113
        self._width        = cw.value
114
        self._height       = ch.value
115
        self._on           = True
116
117
118
    def __del__(self):
119
        if self._cooling :
120
            self.SetTemperature(0)
121
            warm = False
122
            while not warm:
123
                time.sleep(0.5)
124
                temp = self.GetTemperature()
125
                if temp > 0:
126
                    warm = True
127
            self.CoolerOFF()
128
        error = self._dll.ShutDown()
129
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
130
131
    def verbose(self, error, function=''):
132
        if self._verbosity is True:
133
            print("[%s]: %s" % (function, error))
134
135
    def SetVerbose(self, state=True):
136
        self._verbosity = state
137
138
    def AbortAcquisition(self):
139
        error = self._dll.AbortAcquisition()
140
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
141
        return ERROR_CODE[error]
142
143
    def Initialize(self, path):
144
        error = self._dll.Initialize(path)
145
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
146
        return error
147
148
    def ShutDown(self):
149
        error = self._dll.ShutDown()
150
        self._on = False
151
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
152
        return ERROR_CODE[error]
153
154
    def GetCameraSerialNumber(self):
155
        serial = c_int()
156
        error = self._dll.GetCameraSerialNumber(byref(serial))
157
        self._serial = serial.value
158
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
159
        return ERROR_CODE[error]
160
161
    def SetReadMode(self, mode):
162
        # 0: Full vertical binning
163
        # 1: multi track
164
        # 2: random track
165
        # 3: single track
166
        # 4: image
167
        error = self._dll.SetReadMode(mode)
168
        self._ReadMode = mode
169
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
170
        return ERROR_CODE[error]
171
172
    def SetAcquisitionMode(self, mode):
173
        # 1: Single scan
174
        # 3: Kinetic scan
175
        error = self._dll.SetAcquisitionMode(mode)
176
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
177
        self._AcquisitionMode = mode
178
        return ERROR_CODE[error]
179
180
    def SetNumberKinetics(self, numKin):
181
        error = self._dll.SetNumberKinetics(numKin)
182
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
183
        self._scans = numKin
184
        return ERROR_CODE[error]
185
186
    def SetNumberAccumulations(self, number):
187
        error = self._dll.SetNumberAccumulations(number)
188
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
189
        return ERROR_CODE[error]
190
191
    def SetAccumulationCycleTime(self, time):
192
        error = self._dll.SetAccumulationCycleTime(c_float(time))
193
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
194
        return ERROR_CODE[error]
195
196
    def SetKineticCycleTime(self, time):
197
        error = self._dll.SetKineticCycleTime(c_float(time))
198
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
199
        return ERROR_CODE[error]
200
201
    def SetShutter(self, typ, mode, closingtime, openingtime):
202
        error = self._dll.SetShutter(typ, mode, closingtime, openingtime)
203
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
204
        return ERROR_CODE[error]
205
206
    def SetImage(self, hbin, vbin, hstart, hend, vstart, vend):
207
        self._hbin = hbin
208
        self._vbin = vbin
209
        self._hstart = hstart
210
        self._hend = hend
211
        self._vstart = vstart
212
        self._vend = vend
213
214
        error = self._dll.SetImage(hbin, vbin, hstart, hend, vstart, vend)
215
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
216
        return ERROR_CODE[error]
217
218
    def StartAcquisition(self):
219
        if not self._on:
220
            return None
221
        error = self._dll.StartAcquisition()
222
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
223
        return ERROR_CODE[error]
224
225
    def WaitForIdle(self):
226
        if self.GetStatus()=='DRV_ACQUIRING':
227
            return self._dll.WaitForAcquisition()
228
        else:
229
            return
230
231
    def GetAcquiredData(self, imageArray):
232
        if not self._on:
233
            return None
234
        if (self._ReadMode == 4):
235
            if (self._AcquisitionMode == 1):
236
                dim = self._width * self._height / self._hbin / self._vbin
237
            elif (self._AcquisitionMode == 3):
238
                dim = self._width * self._height / self._hbin / self._vbin * self._scans
239
        elif (self._ReadMode == 3 or self._ReadMode == 0):
240
            if (self._AcquisitionMode == 1):
241
                dim = self._width
242
            elif (self._AcquisitionMode == 3):
243
                dim = self._width * self._scans
244
245
        dim = int(dim)
246
        dim_c = c_int(int(dim))
247
        cimageArray = c_int * dim
248
        cimage = cimageArray()
249
        error = self._dll.GetAcquiredData(pointer(cimage), dim_c)
250
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
251
252
        for i in range(len(cimage)):
253
            imageArray.append(cimage[i])
254
255
        self._imageArray = imageArray[:]
256
        # self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
257
        return ERROR_CODE[error]
258
259
    def SetExposureTime(self, seconds):
260
        error = self._dll.SetExposureTime(c_float(seconds))
261
        self._exposure = seconds
262
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
263
        return ERROR_CODE[error]
264
265
    def GetAcquisitionTimings(self):
266
        exposure = c_float()
267
        accumulate = c_float()
268
        kinetic = c_float()
269
        error = self._dll.GetAcquisitionTimings(byref(exposure), byref(accumulate), byref(kinetic))
270
        self._exposure = exposure.value
271
        self._accumulate = accumulate.value
272
        self._kinetic = kinetic.value
273
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
274
        return ERROR_CODE[error]
275
276
    def SetSingleScan(self):
277
        self.SetReadMode(4)
278
        self.SetAcquisitionMode(1)
279
        self.SetImage(1, 1, 1, self._width, 1, self._height)
280
281
    def SetCoolerMode(self, mode):
282
        error = self._dll.SetCoolerMode(mode)
283
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
284
        return ERROR_CODE[error]
285
286
    def SetImageRotate(self, iRotate):
287
        error = self._dll.SetImageRotate(iRotate)
288
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
289
290
    def CoolerON(self):
291
        error = self._dll.CoolerON()
292
        self._cooling = True
293
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
294
        return ERROR_CODE[error]
295
296
    def CoolerOFF(self):
297
        error = self._dll.CoolerOFF()
298
        self._cooling = False
299
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
300
        return ERROR_CODE[error]
301
302
    def IsCoolerOn(self):
303
        iCoolerStatus = c_int()
304
        error = self._dll.IsCoolerOn(byref(iCoolerStatus))
305
        self._cooling = iCoolerStatus
306
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
307
        return iCoolerStatus.value
308
309
    def GetTemperature(self):
310
        if not self._on:
311
            return None
312
        ctemperature = c_int()
313
        error = self._dll.GetTemperature(byref(ctemperature))
314
        self._temperature = ctemperature.value
315
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
316
        return self._temperature
317
318
    def SetTemperature(self, temperature):
319
        # ctemperature = c_int(temperature)
320
        # error = self.dll.SetTemperature(byref(ctemperature))
321
        error = self._dll.SetTemperature(temperature)
322
        self._set_T = temperature
323
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
324
        return ERROR_CODE[error]
325
326
    def GetEMCCDGain(self):
327
        gain = c_int()
328
        error = self._dll.GetEMCCDGain(byref(gain))
329
        self._gain = gain.value
330
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
331
        return ERROR_CODE[error]
332
333
    def SetEMCCDGainMode(self, gainMode):
334
        error = self._dll.SetEMCCDGainMode(gainMode)
335
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
336
        return ERROR_CODE[error]
337
338
    def SetEMCCDGain(self, gain):
339
        error = self._dll.SetEMCCDGain(gain)
340
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
341
        return ERROR_CODE[error]
342
343
    def SetEMAdvanced(self, gainAdvanced):
344
        error = self._dll.SetEMAdvanced(gainAdvanced)
345
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
346
        return ERROR_CODE[error]
347
348
    def GetEMGainRange(self):
349
        low = c_int()
350
        high = c_int()
351
        error = self._dll.GetEMGainRange(byref(low), byref(high))
352
        self._gainRange = (low.value, high.value)
353
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
354
        return ERROR_CODE[error]
355
356
    def GetNumberADChannels(self):
357
        noADChannels = c_int()
358
        error = self._dll.GetNumberADChannels(byref(noADChannels))
359
        self._noADChannels = noADChannels.value
360
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
361
        return ERROR_CODE[error]
362
363
    def GetBitDepth(self):
364
        bitDepth = c_int()
365
366
        self._bitDepths = []
367
368
        for i in range(self._noADChannels):
369
            self._dll.GetBitDepth(i, byref(bitDepth))
370
            self._bitDepths.append(bitDepth.value)
371
372
    def SetADChannel(self, index):
373
        error = self._dll.SetADChannel(index)
374
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
375
        self._channel = index
376
        return ERROR_CODE[error]
377
378
    def SetOutputAmplifier(self, index):
379
        error = self._dll.SetOutputAmplifier(index)
380
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
381
        self._outamp = index
382
        return ERROR_CODE[error]
383
384
    def GetNumberHSSpeeds(self):
385
        noHSSpeeds = c_int()
386
        error = self._dll.GetNumberHSSpeeds(self.channel, self.outamp, byref(noHSSpeeds))
387
        self._noHSSpeeds = noHSSpeeds.value
388
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
389
        return ERROR_CODE[error]
390
391
    def GetHSSpeed(self):
392
        HSSpeed = c_float()
393
394
        self._HSSpeeds = []
395
396
        for i in range(self.noHSSpeeds):
397
            self._dll.GetHSSpeed(self.channel, self.outamp, i, byref(HSSpeed))
398
            self._HSSpeeds.append(HSSpeed.value)
399
400
    def SetHSSpeed(self, itype, index):
401
        error = self._dll.SetHSSpeed(itype, index)
402
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
403
        self._hsspeed = index
404
        return ERROR_CODE[error]
405
406
    def GetNumberVSSpeeds(self):
407
        noVSSpeeds = c_int()
408
        error = self._dll.GetNumberVSSpeeds(byref(noVSSpeeds))
409
        self._noVSSpeeds = noVSSpeeds.value
410
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
411
        return ERROR_CODE[error]
412
413
    def GetVSSpeed(self):
414
        VSSpeed = c_float()
415
416
        self._VSSpeeds = []
417
418
        for i in range(self._noVSSpeeds):
419
            self._dll.GetVSSpeed(i, byref(VSSpeed))
420
            self._preVSpeeds.append(VSSpeed.value)
421
422
    def SetVSSpeed(self, index):
423
        error = self._dll.SetVSSpeed(index)
424
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
425
        self._vsspeed = index
426
        return ERROR_CODE[error]
427
428
    def GetNumberPreAmpGains(self):
429
        noGains = c_int()
430
        error = self._dll.GetNumberPreAmpGains(byref(noGains))
431
        self._noGains = noGains.value
432
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
433
        return ERROR_CODE[error]
434
435
    def GetPreAmpGain(self):
436
        gain = c_float()
437
438
        self._preAmpGain = []
439
440
        for i in range(self._noGains):
441
            self._dll.GetPreAmpGain(i, byref(gain))
442
            self._preAmpGain.append(gain.value)
443
444
    def SetPreAmpGain(self, index):
445
        error = self._dll.SetPreAmpGain(index)
446
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
447
        self._preampgain = index
448
        return ERROR_CODE[error]
449
450
    def SetTriggerMode(self, mode):
451
        error = self._dll.SetTriggerMode(mode)
452
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
453
        return ERROR_CODE[error]
454
455
    def GetStatus(self):
456
        status = c_int()
457
        error = self._dll.GetStatus(byref(status))
458
        self._status = ERROR_CODE[status.value]
459
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
460
        return self._status
461
462
    def GetSeriesProgress(self):
463
        acc = c_long()
464
        series = c_long()
465
        error = self._dll.GetAcquisitionProgress(byref(acc), byref(series))
466
        if ERROR_CODE[error] == "DRV_SUCCESS":
467
            return series.value
468
        else:
469
            return None
470
471
    def GetAccumulationProgress(self):
472
        acc = c_long()
473
        series = c_long()
474
        error = self._dll.GetAcquisitionProgress(byref(acc), byref(series))
475
        if ERROR_CODE[error] == "DRV_SUCCESS":
476
            return acc.value
477
        else:
478
            return None
479
480
    def SetFrameTransferMode(self, frameTransfer):
481
        error = self._dll.SetFrameTransferMode(frameTransfer)
482
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
483
        return ERROR_CODE[error]
484
485
    def SetShutterEx(self, typ, mode, closingtime, openingtime, extmode):
486
        error = self._dll.SetShutterEx(typ, mode, closingtime, openingtime, extmode)
487
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
488
        return ERROR_CODE[error]
489
490
    def SetSpool(self, active, method, path, framebuffersize):
491
        error = self._dll.SetSpool(active, method, c_char_p(path), framebuffersize)
492
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
493
        return ERROR_CODE[error]
494
495
    def SetSingleTrack(self, centre, height):
496
        error = self._dll.SetSingleTrack(centre, height)
497
        self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name)
498
        return ERROR_CODE[error]
499
500
    def SetDemoReady(self):
501
        error = self.SetSingleScan()
502
        error = self.SetTriggerMode(0)
503
        error = self.SetShutter(1, 0, 50, 50)
504
        error = self.SetExposureTime(5.0)
505
        return error
506
507
    def SetBinning(self, binningmode):
508
        if (binningmode == 1):
509
            self.SetImage(1, 1, 1, self._width, 1, self._height)
510
        elif (binningmode == 2):
511
            self.SetImage(2, 2, 1, self._width, 1, self._height)
512
        elif (binningmode == 4):
513
            self.SetImage(4, 4, 1, self._width, 1, self._height)
514
        else:
515
            self.verbose("Binning mode not found")
516
517
    def qChange(self, pvname=None, value=None, char_value=None):
518
        self._qVal = value
519
        if self._qVal > 25:
520
            self.GetEMCCDGain()
521
            if self._gain > 1:
522
                self.SetEMCCDGain(1)
523
                #print('Charge above 25 pC, setting gain to 1')
524
525
    def getResolutionWdith(self):
526
        return self._width
527
528
    def getResolutionHeight(self):
529
        return self._height
530
531