-
Notifications
You must be signed in to change notification settings - Fork 112
/
MMDevice.h
1445 lines (1298 loc) · 56.2 KB
/
MMDevice.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
///////////////////////////////////////////////////////////////////////////////
// FILE: MMDevice.h
// PROJECT: Micro-Manager
// SUBSYSTEM: MMDevice - Device adapter kit
//-----------------------------------------------------------------------------
// DESCRIPTION: The interface to the Micro-Manager devices. Defines the
// plugin API for all devices.
//
// AUTHOR: Nenad Amodaj, nenad@amodaj.com, 06/08/2005
//
// COPYRIGHT: University of California, San Francisco, 2006-2014
// 100X Imaging Inc, 2008
//
// LICENSE: This file is distributed under the BSD license.
// License text is included with the source distribution.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.
#pragma once
///////////////////////////////////////////////////////////////////////////////
// Header version
// If any of the class definitions changes, the interface version
// must be incremented
#define DEVICE_INTERFACE_VERSION 71
///////////////////////////////////////////////////////////////////////////////
// N.B.
//
// Never add parameters or return values that are not POD
// (http://stackoverflow.com/a/146454) to any method of class Device and its
// derived classes defined in this file. For example, a std::string parameter
// is not acceptable (use const char*). This is to prevent inter-DLL
// incompatibilities.
#include "MMDeviceConstants.h"
#include "DeviceUtils.h"
#include "ImageMetadata.h"
#include "DeviceThreads.h"
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#ifdef MMDEVICE_CLIENT_BUILD
// Hide deprecation warnings when building MMCore
# define MM_DEPRECATED(prototype) prototype
#else
# ifdef _MSC_VER
# define MM_DEPRECATED(prototype) __declspec(deprecated) prototype
# elif defined(__GNUC__)
# define MM_DEPRECATED(prototype) prototype __attribute__((deprecated))
# else
# define MM_DEPRECATED(prototype) prototype
# endif
#endif
// To be removed once the deprecated Get/SetModuleHandle() is removed:
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef HMODULE HDEVMODULE;
#else
typedef void* HDEVMODULE;
#endif
class ImgBuffer;
namespace MM {
// forward declaration for the MMCore callback class
class Core;
/**
* Utility class used both MMCore and devices to maintain time intervals
* in the uniform, platform independent way.
*/
class MMTime
{
long long microseconds_;
public:
MMTime() : microseconds_(0LL) {}
explicit MMTime(double uSecTotal) :
microseconds_(static_cast<long long>(uSecTotal))
{}
explicit MMTime(long sec, long uSec) :
microseconds_(sec * 1'000'000LL + uSec)
{}
static MMTime fromUs(long long us)
{
// Work around our lack of a constructor that directly sets the
// internal representation.
// (Note that we cannot add a constructor from 'long long' because
// many existing uses would then get an error (ambiguous with the
// 'double' overload).)
MMTime ret;
ret.microseconds_ = us;
return ret;
}
static MMTime fromMs(double ms)
{
return MMTime(ms * 1000.0);
}
static MMTime fromSeconds(long secs)
{
return MMTime(secs, 0);
}
MMTime operator+(const MMTime &other) const
{
return fromUs(microseconds_ + other.microseconds_);
}
MMTime operator-(const MMTime &other) const
{
return fromUs(microseconds_ - other.microseconds_);
}
bool operator>(const MMTime &other) const
{
return microseconds_ > other.microseconds_;
}
bool operator>=(const MMTime &other) const
{
return microseconds_ >= other.microseconds_;
}
bool operator<(const MMTime &other) const
{
return microseconds_ < other.microseconds_;
}
bool operator<=(const MMTime &other) const
{
return microseconds_ <= other.microseconds_;
}
bool operator==(const MMTime &other) const
{
return microseconds_ == other.microseconds_;
}
bool operator!=(const MMTime &other) const
{
return !(*this == other);
}
double getMsec() const
{
return microseconds_ / 1000.0;
}
double getUsec() const
{
return static_cast<double>(microseconds_);
}
std::string toString() const {
long long absUs = std::abs(microseconds_);
long long seconds = absUs / 1'000'000LL;
long long fracUs = absUs - seconds * 1'000'000LL;
const char *sign = microseconds_ < 0 ? "-" : "";
using namespace std;
ostringstream s;
s << sign << seconds << '.' <<
setfill('0') << right << setw(6) << fracUs;
return s.str();
}
};
/**
* Timeout utility class
*/
class TimeoutMs
{
public:
// arguments: MMTime start time, millisecond interval time
explicit TimeoutMs(const MMTime startTime, const unsigned long intervalMs) :
startTime_(startTime),
interval_(0, 1000*intervalMs)
{
}
explicit TimeoutMs(const MMTime startTime, const MMTime interval) :
startTime_(startTime),
interval_(interval)
{
}
bool expired(const MMTime tnow)
{
MMTime elapsed = tnow - startTime_;
return ( interval_ < elapsed );
}
private:
MMTime startTime_; // start time
MMTime interval_; // interval in milliseconds
};
/**
* Generic device interface.
*/
class Device {
public:
Device() {}
virtual ~Device() {}
virtual unsigned GetNumberOfProperties() const = 0;
virtual int GetProperty(const char* name, char* value) const = 0;
virtual int SetProperty(const char* name, const char* value) = 0;
virtual bool HasProperty(const char* name) const = 0;
virtual bool GetPropertyName(unsigned idx, char* name) const = 0;
virtual int GetPropertyReadOnly(const char* name, bool& readOnly) const = 0;
virtual int GetPropertyInitStatus(const char* name, bool& preInit) const = 0;
virtual int HasPropertyLimits(const char* name, bool& hasLimits) const = 0;
virtual int GetPropertyLowerLimit(const char* name, double& lowLimit) const = 0;
virtual int GetPropertyUpperLimit(const char* name, double& hiLimit) const = 0;
virtual int GetPropertyType(const char* name, MM::PropertyType& pt) const = 0;
virtual unsigned GetNumberOfPropertyValues(const char* propertyName) const = 0;
virtual bool GetPropertyValueAt(const char* propertyName, unsigned index, char* value) const = 0;
/**
* Sequences can be used for fast acquisitions, synchronized by TTLs rather than
* computer commands.
* Sequences of states can be uploaded to the device. The device will cycle through
* the uploaded list of states (triggered by an external trigger - most often coming
* from the camera). If the device is capable (and ready) to do so isSequenceable will
* be true
*/
virtual int IsPropertySequenceable(const char* name, bool& isSequenceable) const = 0;
/**
* The largest sequence that can be stored in the device
*/
virtual int GetPropertySequenceMaxLength(const char* propertyName, long& nrEvents) const = 0;
/**
* Starts execution of the sequence
*/
virtual int StartPropertySequence(const char* propertyName) = 0;
/**
* Stops execution of the device
*/
virtual int StopPropertySequence(const char* propertyName) = 0;
/**
* remove previously added sequence
*/
virtual int ClearPropertySequence(const char* propertyName) = 0;
/**
* Add one value to the sequence
*/
virtual int AddToPropertySequence(const char* propertyName, const char* value) = 0;
/**
* Signal that we are done sending sequence values so that the adapter can send the whole sequence to the device
*/
virtual int SendPropertySequence(const char* propertyName) = 0;
virtual bool GetErrorText(int errorCode, char* errMessage) const = 0;
virtual bool Busy() = 0;
virtual double GetDelayMs() const = 0;
virtual void SetDelayMs(double delay) = 0;
virtual bool UsesDelay() = 0;
MM_DEPRECATED(virtual HDEVMODULE GetModuleHandle() const) = 0;
MM_DEPRECATED(virtual void SetModuleHandle(HDEVMODULE hLibraryHandle)) = 0;
virtual void SetLabel(const char* label) = 0;
virtual void GetLabel(char* name) const = 0;
virtual void SetModuleName(const char* moduleName) = 0;
virtual void GetModuleName(char* moduleName) const = 0;
virtual void SetDescription(const char* description) = 0;
virtual void GetDescription(char* description) const = 0;
virtual int Initialize() = 0;
/**
* Shuts down (unloads) the device.
* Required by the MM::Device API.
* Ideally this method will completely unload the device and release all resources.
* Shutdown() may be called multiple times in a row.
* After Shutdown() we should be allowed to call Initialize() again to load the device
* without causing problems.
*/
virtual int Shutdown() = 0;
virtual DeviceType GetType() const = 0;
virtual void GetName(char* name) const = 0;
virtual void SetCallback(Core* callback) = 0;
//device discovery API
virtual bool SupportsDeviceDetection(void) = 0;
virtual MM::DeviceDetectionStatus DetectDevice(void) = 0;
// hub-peripheral relationship
virtual void SetParentID(const char* parentId) = 0;
virtual void GetParentID(char* parentID) const = 0;
// virtual void SetID(const char* id) = 0;
// virtual void GetID(char* id) const = 0;
};
/**
* Generic Device
*/
class Generic : public Device
{
public:
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
};
/**
* Camera API
*/
class Camera : public Device {
public:
Camera() {}
virtual ~Camera() {}
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// Camera API
/**
* Performs exposure and grabs a single image.
* Required by the MM::Camera API.
*
* SnapImage should start the image exposure in the camera and block until
* the exposure is finished. It should not wait for read-out and transfer of data.
* Return DEVICE_OK on success, error code otherwise.
*/
virtual int SnapImage() = 0;
/**
* Returns pixel data.
* Required by the MM::Camera API.
* GetImageBuffer will be called shortly after SnapImage returns.
* Use it to wait for camera read-out and transfer of data into memory
* Return a pointer to a buffer containing the image data
* The calling program will assume the size of the buffer based on the values
* obtained from GetImageBufferSize(), which in turn should be consistent with
* values returned by GetImageWidth(), GetImageHeight(), GetImageBytesPerPixel(),
* and getNumberOfComponents().
* The calling program also assumes that camera never changes the size of
* the pixel buffer on its own. In other words, the buffer can change only if
* appropriate properties are set (such as binning, pixel type, etc.)
* Multi-Channel cameras should return the content of the first channel in this call.
*
* Supported data types are byte (8 bits per pixel, 1 component), short
* (16 bits per pixel, 1 component), float (32 bits per pixel, 1 component, not
* supported by the UI yet), RGB_32 (8 bits per component, 4 components), RGB_64
* (16 bits per component, 4 components, not supported by UI yet).
* RGB buffers are expected to be in big endian ARGB format (ARGB8888), which means that
* on little endian format (currently most/all? code is compiled for little endian
* architecture), the format is BGRA888 (see: https://en.wikipedia.org/wiki/RGBA_color_model).
*
*/
virtual const unsigned char* GetImageBuffer() = 0;
/**
* Returns pixel data for cameras with multiple channels.
* See description for GetImageBuffer() for details.
* Use this overloaded version for cameras with multiple channels
* When calling this function for a single channel camera, this function
* should return the content of the imagebuffer as returned by the function
* GetImageBuffer(). This behavior is implemented in the DeviceBase.
* When GetImageBuffer() is called for a multi-channel camera, the
* camera adapter should return the ImageBuffer for the first channel
* @param channelNr Number of the channel for which the image data are requested.
*/
virtual const unsigned char* GetImageBuffer(unsigned channelNr) = 0;
/**
* Returns pixel data with interleaved RGB pixels in 32 bpp format
*/
virtual const unsigned int* GetImageBufferAsRGB32() = 0;
/**
* Returns the number of components in this image. This is '1' for grayscale cameras,
* and '4' for RGB cameras.
*/
virtual unsigned GetNumberOfComponents() const = 0;
/**
* Returns the name for each component
*/
virtual int GetComponentName(unsigned component, char* name) = 0;
/**
* Returns the number of simultaneous channels that camera is capable of.
* This should be used by devices capable of generating multiple channels of imagedata simultaneously.
* Note: this should not be used by color cameras (use getNumberOfComponents instead).
*/
virtual int unsigned GetNumberOfChannels() const = 0;
/**
* Returns the name for each Channel.
* An implementation of this function is provided in DeviceBase.h. It will return an empty string
*/
virtual int GetChannelName(unsigned channel, char* name) = 0;
/**
* Returns the size in bytes of the image buffer.
* Required by the MM::Camera API.
* For multi-channel cameras, return the size of a single channel
*/
virtual long GetImageBufferSize() const = 0;
/**
* Returns image buffer X-size in pixels.
* Required by the MM::Camera API.
*/
virtual unsigned GetImageWidth() const = 0;
/**
* Returns image buffer Y-size in pixels.
* Required by the MM::Camera API.
*/
virtual unsigned GetImageHeight() const = 0;
/**
* Returns image buffer pixel depth in bytes.
* Required by the MM::Camera API.
*/
virtual unsigned GetImageBytesPerPixel() const = 0;
/**
* Returns the bit depth (dynamic range) of the pixel.
* This does not affect the buffer size, it just gives the client application
* a guideline on how to interpret pixel values.
* Required by the MM::Camera API.
*/
virtual unsigned GetBitDepth() const = 0;
/**
* Returns binnings factor. Used to calculate current pixelsize
* Not appropriately named. Implemented in DeviceBase.h
*/
virtual double GetPixelSizeUm() const = 0;
/**
* Returns the current binning factor.
*/
virtual int GetBinning() const = 0;
/**
* Sets binning factor.
*/
virtual int SetBinning(int binSize) = 0;
/**
* Sets exposure in milliseconds.
*/
virtual void SetExposure(double exp_ms) = 0;
/**
* Returns the current exposure setting in milliseconds.
*/
virtual double GetExposure() const = 0;
/**
* Sets the camera Region Of Interest.
* Required by the MM::Camera API.
* This command will change the dimensions of the image.
* Depending on the hardware capabilities the camera may not be able to configure the
* exact dimensions requested - but should try do as close as possible.
* If the hardware does not have this capability the software should simulate the ROI by
* appropriately cropping each frame.
* @param x - top-left corner coordinate
* @param y - top-left corner coordinate
* @param xSize - width
* @param ySize - height
*/
virtual int SetROI(unsigned x, unsigned y, unsigned xSize, unsigned ySize) = 0;
/**
* Returns the actual dimensions of the current ROI.
*/
virtual int GetROI(unsigned& x, unsigned& y, unsigned& xSize, unsigned& ySize) = 0;
/**
* Resets the Region of Interest to full frame.
*/
virtual int ClearROI() = 0;
virtual bool SupportsMultiROI() = 0;
virtual bool IsMultiROISet() = 0;
virtual int GetMultiROICount(unsigned& count) = 0;
virtual int SetMultiROI(const unsigned* xs, const unsigned* ys,
const unsigned* widths, const unsigned* heights,
unsigned numROIs) = 0;
virtual int GetMultiROI(unsigned* xs, unsigned* ys, unsigned* widths,
unsigned* heights, unsigned* length) = 0;
/**
* Starts continuous acquisition.
*/
virtual int StartSequenceAcquisition(long numImages, double interval_ms, bool stopOnOverflow) = 0;
/**
* Starts Sequence Acquisition with given interval.
* Most camera adapters will ignore this number
* */
virtual int StartSequenceAcquisition(double interval_ms) = 0;
/**
* Stops an ongoing sequence acquisition
*/
virtual int StopSequenceAcquisition() = 0;
/**
* Sets up the camera so that Sequence acquisition can start without delay
*/
virtual int PrepareSequenceAcqusition() = 0;
/**
* Flag to indicate whether Sequence Acquisition is currently running.
* Return true when Sequence acquisition is active, false otherwise
*/
virtual bool IsCapturing() = 0;
/**
* Get the metadata tags stored in this device.
* These tags will automatically be add to the metadata of an image inserted
* into the circular buffer
*
*/
virtual void GetTags(char* serializedMetadata) = 0;
/**
* Adds new tag or modifies the value of an existing one
* These will automatically be added to images inserted into the circular buffer.
* Use this mechanism for tags that do not change often. For metadata that
* change often, create an instance of metadata yourself and add to one of
* the versions of the InsertImage function
*/
virtual void AddTag(const char* key, const char* deviceLabel, const char* value) = 0;
/**
* Removes an existing tag from the metadata associated with this device
* These tags will automatically be add to the metadata of an image inserted
* into the circular buffer
*/
virtual void RemoveTag(const char* key) = 0;
/**
* Returns whether a camera's exposure time can be sequenced.
* If returning true, then a Camera adapter class should also inherit
* the SequenceableExposure class and implement its methods.
*/
virtual int IsExposureSequenceable(bool& isSequenceable) const = 0;
// Sequence functions
// Sequences can be used for fast acquisitions, synchronized by TTLs rather than
// computer commands.
// Sequences of exposures can be uploaded to the camera. The camera will cycle through
// the uploaded list of exposures (triggered by either an internal or
// external trigger). If the device is capable (and ready) to do so isSequenceable will
// be true. If your device can not execute this (true for most cameras)
// simply set IsExposureSequenceable to false
virtual int GetExposureSequenceMaxLength(long& nrEvents) const = 0;
virtual int StartExposureSequence() = 0;
virtual int StopExposureSequence() = 0;
// Remove all values in the sequence
virtual int ClearExposureSequence() = 0;
// Add one value to the sequence
virtual int AddToExposureSequence(double exposureTime_ms) = 0;
// Signal that we are done sending sequence values so that the adapter can send the whole sequence to the device
virtual int SendExposureSequence() const = 0;
};
/**
* Shutter API
*/
class Shutter : public Device
{
public:
Shutter() {}
virtual ~Shutter() {}
// Device API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// Shutter API
virtual int SetOpen(bool open = true) = 0;
virtual int GetOpen(bool& open) = 0;
/**
* Opens the shutter for the given duration, then closes it again.
* Currently not implemented in any shutter adapters
*/
virtual int Fire(double deltaT) = 0;
};
/**
* Single axis stage API
*/
class Stage : public Device
{
public:
Stage() {}
virtual ~Stage() {}
// Device API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// Stage API
virtual int SetPositionUm(double pos) = 0;
virtual int SetRelativePositionUm(double d) = 0;
virtual int Move(double velocity) = 0;
virtual int Stop() = 0;
virtual int Home() = 0;
virtual int SetAdapterOriginUm(double d) = 0;
virtual int GetPositionUm(double& pos) = 0;
virtual int SetPositionSteps(long steps) = 0;
virtual int GetPositionSteps(long& steps) = 0;
virtual int SetOrigin() = 0;
virtual int GetLimits(double& lower, double& upper) = 0;
/**
* \brief Return the focus direction.
*
* Indicates whether increasing position corresponds to movement in the
* direction that brings the objective and sample closer together.
*
* Unless the direction is known for sure (does not depend on e.g. how
* the hardware is installed), this function must return
* FocusDirectionUnknown (the application can allow the user to specify
* the direction as needed).
*
* Non-focus single-axis stages must also return FocusDirectionUnknown.
*/
virtual int GetFocusDirection(FocusDirection& direction) = 0;
/**
* Indicates whether a stage can be sequenced (synchronized by TTLs).
*
* If true, the following methods must be implemented:
* GetStageSequenceMaxLength(), StartStageSequence(), StopStageSequence(),
* ClearStageSequence(), AddToStageSequence(), and SendStageSequence().
*/
virtual int IsStageSequenceable(bool& isSequenceable) const = 0;
/**
* Indicates whether the stage can perform linear TTL sequencing.
*
* Linear sequencing uses a delta and count instead of an arbitrary list
* of positions.
*
* If true, the following methods must be implemented:
* SetStageLinearSequence(), StartStageSequence(), StopStageSequence().
*/
virtual int IsStageLinearSequenceable(bool& isSequenceable) const = 0;
// Check if a stage has continuous focusing capability (positions can be set while continuous focus runs).
virtual bool IsContinuousFocusDrive() const = 0;
// Sequence functions
// Sequences can be used for fast acquisitions, synchronized by TTLs rather than
// computer commands.
// Sequences of positions can be uploaded to the stage. The device will cycle through
// the uploaded list of states (triggered by an external trigger - most often coming
// from the camera). If the device is capable (and ready) to do so isSequenceable will
// be true. If your device can not execute this (true for most stages)
// simply set isSequenceable to false
virtual int GetStageSequenceMaxLength(long& nrEvents) const = 0;
virtual int StartStageSequence() = 0;
virtual int StopStageSequence() = 0;
/**
* Remove all values in the sequence
*/
virtual int ClearStageSequence() = 0;
/**
* Add one value to the sequence
*/
virtual int AddToStageSequence(double position) = 0;
/**
* Signal that we are done sending sequence values so that the adapter
* can send the whole sequence to the device
*/
virtual int SendStageSequence() = 0;
/**
* Set up to perform an equally-spaced triggered Z stack.
*
* After calling this function, StartStageSequence() must cause the stage
* to step by dZ_um on each trigger. On the Nth trigger, the stage must
* return to the position where it was when StartStageSequence() was
* called.
*/
virtual int SetStageLinearSequence(double dZ_um, long nSlices) = 0;
};
/**
* Dual axis stage API
*/
class XYStage : public Device
{
public:
XYStage() {}
virtual ~XYStage() {}
// Device API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// XYStage API
// it is recommended that device adapters implement the "Steps" methods
// taking long integers but leave the default implementations (in
// DeviceBase.h) for the "Um" methods taking doubles. The latter utilize
// directionality and origin settings set by user and operate via the
// "Steps" methods. The step size is the inherent minimum distance/step
// and should be defined by the adapter.
virtual int SetPositionUm(double x, double y) = 0;
virtual int SetRelativePositionUm(double dx, double dy) = 0;
virtual int SetAdapterOriginUm(double x, double y) = 0;
virtual int GetPositionUm(double& x, double& y) = 0;
virtual int GetLimitsUm(double& xMin, double& xMax, double& yMin, double& yMax) = 0;
virtual int Move(double vx, double vy) = 0;
virtual int SetPositionSteps(long x, long y) = 0;
virtual int GetPositionSteps(long& x, long& y) = 0;
virtual int SetRelativePositionSteps(long x, long y) = 0;
virtual int Home() = 0;
virtual int Stop() = 0;
/**
* Define the current position as the (hardware) origin (0, 0).
*/
virtual int SetOrigin() = 0;
/**
* Define the current position as X = 0 (in hardware if possible).
* Do not alter the Y coordinates.
*/
virtual int SetXOrigin() = 0;
/**
* Define the current position as Y = 0 (in hardware if possible)
* Do not alter the X coordinates.
*/
virtual int SetYOrigin() = 0;
virtual int GetStepLimits(long& xMin, long& xMax, long& yMin, long& yMax) = 0;
virtual double GetStepSizeXUm() = 0;
virtual double GetStepSizeYUm() = 0;
/**
* Returns whether a stage can be sequenced (synchronized by TTLs)
* If returning true, then an XYStage class should also inherit
* the SequenceableXYStage class and implement its methods.
*/
virtual int IsXYStageSequenceable(bool& isSequenceable) const = 0;
// Sequence functions
// Sequences can be used for fast acquisitions, synchronized by TTLs rather than
// computer commands.
// Sequences of positions can be uploaded to the XY stage. The device will cycle through
// the uploaded list of states (triggered by an external trigger - most often coming
// from the camera). If the device is capable (and ready) to do so isSequenceable will
// be true. If your device can not execute this (true for most XY stages
// simply set isSequenceable to false
virtual int GetXYStageSequenceMaxLength(long& nrEvents) const = 0;
virtual int StartXYStageSequence() = 0;
virtual int StopXYStageSequence() = 0;
/**
* Remove all values in the sequence
*/
virtual int ClearXYStageSequence() = 0;
/**
* Add one value to the sequence
*/
virtual int AddToXYStageSequence(double positionX, double positionY) = 0;
/**
* Signal that we are done sending sequence values so that the adapter
* can send the whole sequence to the device
*/
virtual int SendXYStageSequence() = 0;
};
/**
* State device API, e.g. filter wheel, objective turret, etc.
*/
class State : public Device
{
public:
State() {}
virtual ~State() {}
// MMDevice API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// MMStateDevice API
virtual int SetPosition(long pos) = 0;
virtual int SetPosition(const char* label) = 0;
virtual int GetPosition(long& pos) const = 0;
virtual int GetPosition(char* label) const = 0;
virtual int GetPositionLabel(long pos, char* label) const = 0;
virtual int GetLabelPosition(const char* label, long& pos) const = 0;
virtual int SetPositionLabel(long pos, const char* label) = 0;
virtual unsigned long GetNumberOfPositions() const = 0;
virtual int SetGateOpen(bool open = true) = 0;
virtual int GetGateOpen(bool& open) = 0;
};
/**
* Serial port API.
*/
class Serial : public Device
{
public:
Serial() {}
virtual ~Serial() {}
// MMDevice API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// Serial API
virtual PortType GetPortType() const = 0;
virtual int SetCommand(const char* command, const char* term) = 0;
virtual int GetAnswer(char* txt, unsigned maxChars, const char* term) = 0;
virtual int Write(const unsigned char* buf, unsigned long bufLen) = 0;
virtual int Read(unsigned char* buf, unsigned long bufLen, unsigned long& charsRead) = 0;
virtual int Purge() = 0;
};
/**
* Auto-focus device API.
*/
class AutoFocus : public Device
{
public:
AutoFocus() {}
virtual ~AutoFocus() {}
// MMDevice API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// AutoFocus API
virtual int SetContinuousFocusing(bool state) = 0;
virtual int GetContinuousFocusing(bool& state) = 0;
virtual bool IsContinuousFocusLocked() = 0;
virtual int FullFocus() = 0;
virtual int IncrementalFocus() = 0;
virtual int GetLastFocusScore(double& score) = 0;
virtual int GetCurrentFocusScore(double& score) = 0;
virtual int AutoSetParameters() = 0;
virtual int GetOffset(double &offset) = 0;
virtual int SetOffset(double offset) = 0;
};
/**
* Image processor API.
*/
class ImageProcessor : public Device
{
public:
ImageProcessor() {}
virtual ~ImageProcessor() {}
// MMDevice API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// image processor API
virtual int Process(unsigned char* buffer, unsigned width, unsigned height, unsigned byteDepth) = 0;
};
/**
* ADC and DAC interface.
*/
class SignalIO : public Device
{
public:
SignalIO() {}
virtual ~SignalIO() {}
// MMDevice API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// signal io API
virtual int SetGateOpen(bool open = true) = 0;
virtual int GetGateOpen(bool& open) = 0;
virtual int SetSignal(double volts) = 0;
virtual int GetSignal(double& volts) = 0;
virtual int GetLimits(double& minVolts, double& maxVolts) = 0;
/**
* Lets the UI know whether or not this DA device accepts sequences
* If the device is sequenceable, it is usually best to add a property through which
* the user can set "isSequenceable", since only the user knows whether the device
* is actually connected to a trigger source.
* If isDASequenceable returns true, the device adapter must
* also inherit the SequenceableDA class and provide method
* implementations.
* @param isSequenceable signals whether other sequence functions will work
* @return errorcode (DEVICE_OK if no error)
*/
virtual int IsDASequenceable(bool& isSequenceable) const = 0;
// Sequence functions
// Sequences can be used for fast acquisitions, synchronized by TTLs rather than
// computer commands.
// Sequences of voltages can be uploaded to the DA. The device will cycle through
// the uploaded list of voltages (triggered by an external trigger - most often coming
// from the camera). If the device is capable (and ready) to do so isSequenceable will
// be true. If your device can not execute this simply set isSequenceable to false
/**
* Returns the maximum length of a sequence that the hardware can store
* @param nrEvents max length of sequence
* @return errorcode (DEVICE_OK if no error)
*/
virtual int GetDASequenceMaxLength(long& nrEvents) const = 0;
/**
* Tells the device to start running a sequence (i.e. start switching between voltages
* send previously, triggered by a TTL
* @return errorcode (DEVICE_OK if no error)
*/
virtual int StartDASequence() = 0;
/**
* Tells the device to stop running the sequence
* @return errorcode (DEVICE_OK if no error)
*/
virtual int StopDASequence() = 0;
/**
* Clears the DA sequence from the device and the adapter.
* If this functions is not called in between running
* two sequences, it is expected that the same sequence will run twice.
* To upload a new sequence, first call this functions, then call AddToDASequence(double
* voltage) as often as needed.
* @return errorcode (DEVICE_OK if no error)
*/
virtual int ClearDASequence() = 0;
/**
* Adds a new data point (voltage) to the sequence
* The data point can either be added to a representation of the sequence in the
* adapter, or it can be directly written to the device
* @return errorcode (DEVICE_OK if no error)
*/
virtual int AddToDASequence(double voltage) = 0;
/**
* Sends the complete sequence to the device
* If the individual data points were already send to the device, there is
* nothing to be done.
* @return errorcode (DEVICE_OK if no error)
*/
virtual int SendDASequence() = 0;
};
/**
* Devices that can change magnification of the system
*/
class Magnifier : public Device
{
public:
Magnifier() {}
virtual ~Magnifier() {}
// MMDevice API
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
virtual double GetMagnification() = 0;
};
/**
* Spatial Ligh Modulator (SLM) API. An SLM is a device that can display images.
* It is expected to represent a rectangular grid (i.e. it has width and height)
* of pixels that can be either 8 bit or 32 bit. Illumination (light source on
* or off) is logically independent of displaying the image. Likely the most
* widely used implmentation is the GenericSLM.
*/
class SLM : public Device
{
public:
SLM() {}
virtual ~SLM() {}
virtual DeviceType GetType() const { return Type; }
static const DeviceType Type;
// SLM API
/**
* Load the image into the SLM device adapter.
*/
virtual int SetImage(unsigned char * pixels) = 0;
/**
* Load a 32-bit image into the SLM device adapter.
*/
virtual int SetImage(unsigned int * pixels) = 0;
/**
* Command the SLM to display the loaded image.
*/
virtual int DisplayImage() = 0;
/**
* Command the SLM to display one 8-bit intensity.
*/