From ab625de57db814f153243e8c690539c37b751e2c Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 8 Apr 2020 10:24:01 +0200 Subject: [PATCH 01/24] add parsing of marana 4.2 model add reading of pixel size from library change trigger mode handling: list of triggers read from sdk (no static enum) internal trigger mode in lima unit (IntTrig, ...) remove andor3 functions set/getTriggerMode : trigger mode has to be set using lima standards set/getTrigMode --- include/Andor3Camera.h | 14 +- sip/Andor3Camera.sip | 6 +- src/Andor3Camera.cpp | 282 ++++++++++++++++++++--------------------- tango/Andor3.py | 11 ++ 4 files changed, 159 insertions(+), 154 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index ef6f210..8e44939 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -70,7 +70,8 @@ namespace lima // In the same order/index as 'BitDepth' enum A3_BitDepth { b11 = 0, b16= 1 }; // The camera trigger mode (in the enum order) : - enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; +// enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; + // The binning system of andor3 : enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; // The fan speed @@ -167,8 +168,8 @@ namespace lima void getBitDepthString(std::string &oDepthString) const; void getPxEncoding(A3_PixelEncoding &oPxEncoding) const; void getPxEncodingString(std::string &oPxEncoding) const; - void setTriggerMode(A3_TriggerMode iMode); - void getTriggerMode(A3_TriggerMode &oMode) const; + // void setTriggerMode(A3_TriggerMode iMode); + // void getTriggerMode(A3_TriggerMode &oMode) const; void getTriggerModeString(std::string &oModeString) const; void setTemperatureSP(double temp); // à exporter (avec le get) void getTemperatureSP(double& temp) const; @@ -220,6 +221,8 @@ namespace lima void _setStatus(Camera::Status iStatus, bool iForce); private: + void initTrigMode(); + // -- andor3 Lower level functions int printInfoForProp(const AT_WC * iPropName, A3_TypeInfo iPropType) const; bool propImplemented(const AT_WC * iPropName) const; @@ -294,12 +297,13 @@ namespace lima A3_ReadOutRate m_adc_rate; A3_ShutterMode m_electronic_shutter_mode; A3_BitDepth m_bit_depth; - A3_TriggerMode m_trig_mode; bool m_cooler; double m_temperature_sp; bool m_temperature_control_available; - // std::map<TrigMode, int> m_trig_mode_maps; + TrigMode m_trig_mode; + // A3_TriggerMode m_trig_mode; + std::map<TrigMode, int> m_trig_mode_map; static int sAndorSDK3InittedCounter; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index c7c95f4..3b4312a 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -36,7 +36,7 @@ namespace Andor3 enum A3_ShutterMode { Rolling = 0, Global = 1 }; enum A3_ReadOutRate { MHz10 = 0, MHz100 = 1, MHz200 = 2, MHz280 = 3 }; enum A3_BitDepth { b11 = 0, b16= 1 }; - enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; +// enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; @@ -107,8 +107,8 @@ namespace Andor3 void getBitDepth(A3_BitDepth &oMode /Out/ ) const; void getBitDepthString(std::string &oDepthString /Out/ ) const; void getPxEncodingString(std::string &oPxEncoding /Out/ ) const; - void setTriggerMode(A3_TriggerMode iMode /In/ ); - void getTriggerMode(A3_TriggerMode &oMode /Out/ ) const; +// void setTriggerMode(A3_TriggerMode iMode /In/ ); +// void getTriggerMode(A3_TriggerMode &oMode /Out/ ) const; void getTriggerModeString(std::string &oModeString /Out/ ) const; void setTemperatureSP(double temp /In/ ); void getTemperatureSP(double& temp /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 3f4caff..33273c0 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -73,6 +73,8 @@ namespace lima { static const AT_WC* Overlap = L"Overlap"; static const AT_WC* PixelEncoding = L"PixelEncoding"; static const AT_WC* PixelReadoutRate = L"PixelReadoutRate"; + static const AT_WC* PixelHeight = L"PixelHeight"; + static const AT_WC* PixelWidth = L"PixelWidth"; static const AT_WC* PreAmpGainControl = L"PreAmpGainControl"; static const AT_WC* ReadoutTime = L"ReadoutTime"; static const AT_WC* SensorCooling = L"SensorCooling"; @@ -168,7 +170,7 @@ m_simple_gain(b16_lh_gain), m_adc_rate(MHz100), m_electronic_shutter_mode(Rolling), m_bit_depth(b16), -m_trig_mode(Internal), +m_trig_mode(IntTrig), m_cooler(true), m_temperature_sp(5.0), m_temperature_control_available(true), @@ -254,7 +256,9 @@ m_maximage_size_cb_active(false) if (! m_detector_model.compare(0, 7, "ZYLA5.5")) { m_detector_type = std::string("Zyla-5.5"); } - + if (! m_detector_model.compare(0, 12, "MARANA-4BV11")) { + m_detector_type = std::string("Marana-4.2"); + } if ( m_detector_model != "SIMCAM CMOS" ) { std::string the_serial, the_fw; @@ -291,7 +295,14 @@ m_maximage_size_cb_active(false) "Cannot get detector Y size"); m_detector_size= Size(static_cast<int>(xmax), static_cast<int>(ymax)); - + + // --- init trigger modes + initTrigMode(); + + // printInfoForProp(andor3::ElectronicShutteringMode, Enum); + // printInfoForProp(andor3::PixelReadoutRate, Enum); + // printInfoForProp(andor3::PixelEncoding, Enum); + // --- Initialise deeper parameters of the controller initialiseController(); @@ -451,7 +462,7 @@ lima::Andor3::Camera::prepareAcq() // Better to use continuous mode, smaller ring-buffer allocated by SDK. L.Claustre // excepted if the trigger mode is IntTrigMult (e.i Software) - if (m_trig_mode == Software) + if (m_trig_mode == IntTrigMult) { DEB_TRACE()<< "Software trigger ON, set CycleMode to Fixed mode"; AT_64 nb_frames = static_cast<AT_64>(m_nb_frames_to_collect); @@ -498,7 +509,7 @@ lima::Andor3::Camera::startAcq() sendCommand(andor3::AcquisitionStart); } - if ( Software == m_trig_mode ) { + if ( IntTrigMult == m_trig_mode ) { // If we are in software trigger mode, the call to startAcq serves as the trigger : sendCommand(andor3::SoftwareTrigger); } @@ -614,86 +625,97 @@ lima::Andor3::Camera::getBufferCtrlObj() } //-- Synch control object + +void +lima::Andor3::Camera::initTrigMode() +{ + DEB_MEMBER_FUNCT(); + AT_BOOL b_value; + int enum_count; + AT_WC s_value[1024]; + std::string s_mode; + + AT_GetEnumCount(m_camera_handle, andor3::TriggerMode, &enum_count); + + for (int idx=0; enum_count != idx; ++idx) { + AT_GetEnumStringByIndex(m_camera_handle, andor3::TriggerMode, idx, s_value, 1024); + AT_IsEnumIndexImplemented(m_camera_handle, andor3::TriggerMode, idx, &b_value); + if (b_value) { + s_mode = WStringToString(s_value); + if ( s_mode == "Internal" ) { + m_trig_mode_map.emplace(IntTrig, idx); + DEB_TRACE() << "Found IntTrig mode" ; + } else if ( s_mode == "Software" ) { + m_trig_mode_map.emplace(IntTrigMult, idx); + DEB_TRACE() << "Found IntTrigMult mode" ; + } else if ( s_mode == "External" ) { + m_trig_mode_map.emplace(ExtTrigMult, idx); + DEB_TRACE() << "Found ExtTrigMult mode" ; + } else if ( s_mode == "External Start" ) { + m_trig_mode_map.emplace(ExtTrigSingle, idx); + DEB_TRACE() << "Found ExtTrigSingle mode" ; + } else if ( s_mode == "External Exposure" ) { + m_trig_mode_map.emplace(ExtGate, idx); + DEB_TRACE() << "Found ExtGate mode" ; + } + } + } +} + bool lima::Andor3::Camera::checkTrigMode(TrigMode mode) { - switch (mode) { - case IntTrig: - case IntTrigMult: - case ExtTrigSingle: - case ExtTrigMult: - case ExtGate: - return true; - break; - - default: - return false; - break; - } + std::map<TrigMode,int>::iterator it; + + it = m_trig_mode_map.find(mode); + if (it != m_trig_mode_map.end()) + return true; + else + return false; } void -lima::Andor3::Camera::setTrigMode(TrigMode mode) +lima::Andor3::Camera::setTrigMode(TrigMode mode) { DEB_MEMBER_FUNCT(); - A3_TriggerMode the_trigger_mode; - switch (mode) { - case IntTrig: - the_trigger_mode = Internal; - break; - case IntTrigMult: - the_trigger_mode = Software; - break; - case ExtTrigSingle: - the_trigger_mode = ExternalStart; - break; - case ExtTrigMult: - the_trigger_mode = External; - break; - case ExtGate: - the_trigger_mode = ExternalExposure; - break; - - case ExtStartStop: - case ExtTrigReadout: - default: - the_trigger_mode = Internal; - THROW_HW_ERROR(Error) << "The triggering mode " << mode - << " is NOT implemented in this SDK"; - break; + std::map<TrigMode,int>::iterator it; + int i_setmode, i_getmode; + + if (m_real_camera) { + it = m_trig_mode_map.find(mode); + if (it == m_trig_mode_map.end()) + THROW_HW_ERROR(Error) << "The triggering mode " << mode + << " is NOT implemented in this SDK"; + + i_setmode = it->second; + setEnumIndex(andor3::TriggerMode, i_setmode); + + getEnumIndex(andor3::TriggerMode, &i_getmode); + if ( i_setmode != i_getmode ) { + DEB_ERROR() << "Proof-reading the trigger mode :" + << "\n\tGot " << i_getmode << ", while requesting " << i_setmode; + for (it=m_trig_mode_map.begin(); it!=m_trig_mode_map.end(); ++it) { + if (i_getmode == it->second) { + m_trig_mode = it->first; + } + } + } else { + m_trig_mode = mode; + } } - setTriggerMode(the_trigger_mode); + else { + setEnumString(andor3::TriggerMode, L"Advanced"); + DEB_TRACE() << "SIMCAM - forcing trigger mode to Advanced"; + m_trig_mode = mode; + } + DEB_TRACE() << "Trigger Mode is now : " << m_trig_mode; } - + void lima::Andor3::Camera::getTrigMode(TrigMode& mode) { DEB_MEMBER_FUNCT(); - A3_TriggerMode the_trigger_mode; - getTriggerMode(the_trigger_mode); - - switch (the_trigger_mode) { - case Internal: - mode = IntTrig; - break; - case Software: - mode = IntTrigMult; - break; - case ExternalStart: - mode = ExtTrigSingle; - break; - case External: - mode = ExtTrigMult; - break; - case ExternalExposure: - mode = ExtGate; - break; - default: - mode = IntTrig; - THROW_HW_ERROR(Error) << "The triggering mode of the SDK " << the_trigger_mode - << " does not correspond to any mode of LIMA, returning " << mode; - break; - } + mode = m_trig_mode; } void @@ -825,7 +847,7 @@ lima::Andor3::Camera::checkRoi(const Roi& set_roi, Roi& hw_roi) {2592, 304, 929, 1, 1, 1297, 1297}, { 240, 256, 953, 1169, 1177, 1289, 1297}, { 144, 128, 1017, 1217, 1225, 1289, 1297}, - NULL + // NULL }; // Trying to take the smallest enclosing possible ROI (depending on the bit-depth of the image) : @@ -1116,7 +1138,8 @@ void lima::Andor3::Camera::getPixelSize(double& sizex, double& sizey) { DEB_MEMBER_FUNCT(); - sizex = sizey = 6.5; // in micron ? + getFloat(andor3::PixelWidth, &sizex); + getFloat(andor3::PixelHeight, &sizey); } void @@ -1127,7 +1150,7 @@ lima::Andor3::Camera::getStatus(Camera::Status& status) status = m_status; //Check if the camera is not waiting for soft. trigger if (status == Camera::Readout && - m_trig_mode == Software) + m_trig_mode == IntTrigMult) { status = Camera::Ready; } @@ -1161,7 +1184,7 @@ lima::Andor3::Camera::initialiseController() // Carefully crafting the order, since some are affecting others... setElectronicShutterMode(m_electronic_shutter_mode); - setTriggerMode(m_trig_mode); + setTrigMode(m_trig_mode); setSimpleGain(the_simple_gain); setAdcRate(the_rate); setBitDepth(the_bd); @@ -1393,52 +1416,19 @@ lima::Andor3::Camera::getPxEncoding(A3_PixelEncoding &oPxEncoding) const oPxEncoding = static_cast<A3_PixelEncoding>(oPxEncoding); } - -/*! - @brief Setting the trigger mode of the camera through the SDK settings. - @param iMode : the mode to select - */ -void -lima::Andor3::Camera::setTriggerMode(A3_TriggerMode iMode) -{ - DEB_MEMBER_FUNCT(); - if ( m_real_camera ) { - int the_mode; - setEnumIndex(andor3::TriggerMode, static_cast<int>(iMode)); - getEnumIndex(andor3::TriggerMode, &the_mode); - m_trig_mode = static_cast<A3_TriggerMode>(the_mode); - if ( m_trig_mode != iMode ) { - DEB_ERROR() << "Proof-reading the trigger mode :" - << "\n\tGot " << m_trig_mode << " back," - << "\n\twhile requesting " << iMode; - } - } - else { // Simulated camera -> setting it forcibly to «Advanced» - int the_mode; - setEnumIndex(andor3::TriggerMode, 5); - getEnumIndex(andor3::TriggerMode, &the_mode); - m_trig_mode = static_cast<A3_TriggerMode>(the_mode); - DEB_TRACE() << "The SIMCAM has only one trigger-mode setting (Advanced), making sure that's what we are doing now"; - } -} - -/*! - @brief Getting the triggering mode the camera is in - @param oMode : the mode selected upon return - */ -void -lima::Andor3::Camera::getTriggerMode(A3_TriggerMode &oMode) const -{ - DEB_MEMBER_FUNCT(); - oMode = m_trig_mode; -} - void lima::Andor3::Camera::getTriggerModeString(std::string &oModeString) const { AT_WC the_string[256]; - getEnumStringByIndex(andor3::TriggerMode, m_trig_mode, the_string, 255); - oModeString = WStringToString(std::wstring(the_string)); + int i_trig; + if (m_real_camera) { + i_trig = m_trig_mode_map.at(m_trig_mode); + getEnumStringByIndex(andor3::TriggerMode, m_trig_mode, the_string, 255); + oModeString = WStringToString(std::wstring(the_string)); + } + else { + oModeString = "Advanced"; + } } @@ -2033,41 +2023,41 @@ lima::Andor3::Camera::printInfoForProp(const AT_WC * iPropName, A3_TypeInfo iPro AT_BOOL b_writable; AT_BOOL b_readable; - DEB_TRACE() << "Retrieving information on property named \"" << WStringToString(iPropName) << "\".\n"; + DEB_ALWAYS() << "Retrieving information on property named \"" << WStringToString(iPropName) << "\".\n"; int ret_code; // Implemented if ( AT_SUCCESS != (ret_code = AT_IsImplemented(m_camera_handle, iPropName, &b_exists)) ) { - DEB_TRACE() << "Error in printInfoForProp : " << error_code(ret_code); + DEB_ALWAYS() << "Error in printInfoForProp : " << error_code(ret_code); return i_err; } - DEB_TRACE() << "\tIsImplemented = " << atBoolToString(b_exists); + DEB_ALWAYS() << "\tIsImplemented = " << atBoolToString(b_exists); if ( ! b_exists ) { - DEB_TRACE() << "No more information to query, since the feature does not \"exists\" for this camera/driver/SDK."; + DEB_ALWAYS() << "No more information to query, since the feature does not \"exists\" for this camera/driver/SDK."; return i_err; } // ReadOnly AT_IsReadOnly(m_camera_handle, iPropName, &b_readonly); - DEB_TRACE() << "\tIsReadOnly = " << atBoolToString(b_readonly); + DEB_ALWAYS() << "\tIsReadOnly = " << atBoolToString(b_readonly); // Writable AT_IsWritable(m_camera_handle, iPropName, &b_writable); - DEB_TRACE() << "\tIsWritable = " << atBoolToString(b_writable); + DEB_ALWAYS() << "\tIsWritable = " << atBoolToString(b_writable); // Readable AT_IsReadable(m_camera_handle, iPropName, &b_readable); - DEB_TRACE() << "\tIsReadable = " << atBoolToString(b_readable); + DEB_ALWAYS() << "\tIsReadable = " << atBoolToString(b_readable); if ( ! b_readable ) { - DEB_TRACE() << "Since the property is not readable at this time, we will stop here."; + DEB_ALWAYS() << "Since the property is not readable at this time, we will stop here."; return i_err; } // Now getting the value itself : we absolutely need now to know the type of the feature : if ( Camera::Unknown == iPropType ) { - DEB_TRACE() << "Could not retrieve information on a property of unknown type !!\n" + DEB_ALWAYS() << "Could not retrieve information on a property of unknown type !!\n" << "Returning error code!!"; return -1; } @@ -2125,47 +2115,47 @@ lima::Andor3::Camera::printInfoForProp(const AT_WC * iPropName, A3_TypeInfo iPro break; case Camera::Enum: - DEB_TRACE() << "\tFeature of type ENUM"; + DEB_ALWAYS() << "\tFeature of type ENUM"; if ( AT_SUCCESS == (ret_code = AT_GetEnumIndex(m_camera_handle, iPropName, &enum_Value)) ) { - DEB_TRACE() << "\tValue = (" << enum_Value << ")"; + DEB_ALWAYS() << "\tValue = (" << enum_Value << ")"; if ( AT_SUCCESS == (ret_code = AT_GetEnumStringByIndex(m_camera_handle, iPropName, enum_Value, s_Value, 1024)) ) - DEB_TRACE() << " \"" << WStringToString(s_Value) << "\""; + DEB_ALWAYS() << " \"" << WStringToString(s_Value) << "\""; else - DEB_TRACE() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexImplemented(m_camera_handle, iPropName, enum_Value, &b_Value)) ) - DEB_TRACE() << "; implemented = " << atBoolToString(b_Value); + DEB_ALWAYS() << "; implemented = " << atBoolToString(b_Value); else - DEB_TRACE() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexAvailable(m_camera_handle, iPropName, enum_Value, &b_Value)) ) - DEB_TRACE() << "; available = " << atBoolToString(b_Value); + DEB_ALWAYS() << "; available = " << atBoolToString(b_Value); else - DEB_TRACE() << "\tError message : " << error_code(ret_code); - DEB_TRACE() << "."; + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "."; } else - DEB_TRACE() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_GetEnumCount(m_camera_handle, iPropName, &enum_Count)) ) { - DEB_TRACE() << "\tAvailable choices are (" << enum_Count << ") :"; + DEB_ALWAYS() << "\tAvailable choices are (" << enum_Count << ") :"; for ( int i=0; enum_Count != i; ++i ) { - DEB_TRACE() << "\t\t(" << i << ")"; + DEB_ALWAYS() << "\t\t(" << i << ")"; if ( AT_SUCCESS == (ret_code = AT_GetEnumStringByIndex(m_camera_handle, iPropName, i, s_Value, 1024)) ) - DEB_TRACE() << " \"" << WStringToString(s_Value) << "\""; + DEB_ALWAYS() << " \"" << WStringToString(s_Value) << "\""; else - DEB_TRACE() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexImplemented(m_camera_handle, iPropName, i, &b_Value)) ) - DEB_TRACE() << "; implemented = " << atBoolToString(b_Value); + DEB_ALWAYS() << "; implemented = " << atBoolToString(b_Value); else - DEB_TRACE() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexAvailable(m_camera_handle, iPropName, i, &b_Value)) ) - DEB_TRACE() << "; available = " << atBoolToString(b_Value); + DEB_ALWAYS() << "; available = " << atBoolToString(b_Value); else - DEB_TRACE() << "\tError message : " << error_code(ret_code); - DEB_TRACE() << "."; + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "."; } } else - DEB_TRACE() << "\tError message : " << error_code(ret_code); + DEB_ALWAYS() << "\tError message : " << error_code(ret_code); break; diff --git a/tango/Andor3.py b/tango/Andor3.py index 7c3f901..7812858 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -105,6 +105,7 @@ class Andor3(PyTango.Device_4Impl): 'readout_time': 'ReadoutTime', 'overlap': 'Overlap', 'spurious_noise_filter': 'SpuriousNoiseFilter', + 'serial_number': 'SerialNumber', } self.init_device() @@ -344,6 +345,16 @@ class Andor3Class(PyTango.DeviceClass): 'format': '', 'description': 'OFF or ON', }], + 'serial_number': + [[PyTango.DevString, + PyTango.SCALAR, + PyTango.READ], + { + 'label':'Read camera serial number', + 'unit': 'N/A', + 'format': '', + 'description': 'camera serial number', + }], } #------------------------------------------------------------------ -- GitLab From 7c89bd33b4d5492a82fe805cc10d4b0a21e3a1b7 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Thu, 9 Apr 2020 13:49:00 +0200 Subject: [PATCH 02/24] added gate and trigger level (normal or inverted) --- include/Andor3Camera.h | 13 ++++++--- sip/Andor3Camera.sip | 6 ++++ src/Andor3Camera.cpp | 66 +++++++++++++++++++++++++++++++++++++++--- tango/Andor3.py | 29 +++++++++++++++++++ 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 8e44939..2b412b5 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -69,14 +69,16 @@ namespace lima enum A3_ReadOutRate { MHz10 = 0, MHz100 = 1, MHz200 = 2, MHz280 = 3 }; // In the same order/index as 'BitDepth' enum A3_BitDepth { b11 = 0, b16= 1 }; - // The camera trigger mode (in the enum order) : -// enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; + // Gain Mode for Marana detector + enum A3_GainMode { FastFrameRate=0, HighDynamicRange=1 }; // The binning system of andor3 : enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; // The fan speed enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; + + enum A3_SignalLevel { Normal=0, Inverted=1}; struct SdkFrameDim { AT_64 width; @@ -157,6 +159,11 @@ namespace lima void getAdcGain(A3_Gain &oGain) const; void getAdcGainString(std::string &oGainString) const; + void setGateLevel(A3_SignalLevel iLevel); + void getGateLevel(A3_SignalLevel &iLevel); + void setTriggerLevel(A3_SignalLevel iLevel); + void getTriggerLevel(A3_SignalLevel &iLevel); + void setAdcRate(A3_ReadOutRate iRate); // à exporter (avec le get) void getAdcRate(A3_ReadOutRate &oRate) const; void getAdcRateString(std::string &oRateString) const; @@ -168,8 +175,6 @@ namespace lima void getBitDepthString(std::string &oDepthString) const; void getPxEncoding(A3_PixelEncoding &oPxEncoding) const; void getPxEncodingString(std::string &oPxEncoding) const; - // void setTriggerMode(A3_TriggerMode iMode); - // void getTriggerMode(A3_TriggerMode &oMode) const; void getTriggerModeString(std::string &oModeString) const; void setTemperatureSP(double temp); // à exporter (avec le get) void getTemperatureSP(double& temp) const; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index 3b4312a..09b0436 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -40,6 +40,7 @@ namespace Andor3 enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; + enum A3_SignalLevel {Normal=0, Inverted=1}; Camera(const std::string& bitflow_path, int camera_number=0); ~Camera(); @@ -94,6 +95,11 @@ namespace Andor3 // -- andor3 specific, LIMA don't worry about it ! void initialiseController(); + void setGateLevel(A3_SignalLevel iLevel /In/ ); + void getGateLevel(A3_SignalLevel &iLevel /Out/ ); + void setTriggerLevel(A3_SignalLevel iLevel /In/ ); + void getTriggerLevel(A3_SignalLevel &iLevel /Out/ ); + void setAdcGain(A3_Gain iGain /In/ ); void getAdcGain(A3_Gain &oGain /Out/ ) const; void getAdcGainString(std::string &oGainString /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 33273c0..1157325 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -92,6 +92,9 @@ namespace lima { static const AT_WC* TriggerMode = L"TriggerMode"; static const AT_WC* FrameCount = L"FrameCount"; + static const AT_WC* IOSelector = L"IOSelector"; + static const AT_WC* IOInvert = L"IOInvert"; + // For future !! // static const AT_WC* AccumulateCount = L"AccumulateCount"; // static const AT_WC* BaselineLevel = L"BaselineLevel"; @@ -299,9 +302,13 @@ m_maximage_size_cb_active(false) // --- init trigger modes initTrigMode(); - // printInfoForProp(andor3::ElectronicShutteringMode, Enum); - // printInfoForProp(andor3::PixelReadoutRate, Enum); - // printInfoForProp(andor3::PixelEncoding, Enum); +// --- to investiagte cam features +// printInfoForProp(andor3::ElectronicShutteringMode, Enum); +// printInfoForProp(andor3::PixelReadoutRate, Enum); +// printInfoForProp(andor3::PixelEncoding, Enum); +// printInfoForProp(andor3::SimplePreAmpGainControl, Enum); +// printInfoForProp(andor3::FanSpeed, Enum); +// printInfoForProp(andor3::BitDepth, Enum); // --- Initialise deeper parameters of the controller initialiseController(); @@ -1431,6 +1438,53 @@ lima::Andor3::Camera::getTriggerModeString(std::string &oModeString) const } } +void +lima::Andor3::Camera::setGateLevel(A3_SignalLevel iLevel) +{ + DEB_MEMBER_FUNCT(); + bool flag; + if (iLevel == Inverted) flag= true; + else flag= false; + setEnumString(andor3::IOSelector, L"External Exposure"); + setBool(andor3::IOInvert, flag); +} + +void +lima::Andor3::Camera::getGateLevel(A3_SignalLevel &iLevel) +{ + DEB_MEMBER_FUNCT(); + bool flag; + setEnumString(andor3::IOSelector, L"External Exposure"); + getBool(andor3::IOInvert, &flag); + if (flag) + iLevel = Inverted; + else + iLevel = Normal; +} + +void +lima::Andor3::Camera::setTriggerLevel(A3_SignalLevel iLevel) +{ + DEB_MEMBER_FUNCT(); + bool flag; + if (iLevel == Inverted) flag= true; + else flag= false; + setEnumString(andor3::IOSelector, L"External Trigger"); + setBool(andor3::IOInvert, flag); +} + +void +lima::Andor3::Camera::getTriggerLevel(A3_SignalLevel &iLevel) +{ + DEB_MEMBER_FUNCT(); + bool flag; + setEnumString(andor3::IOSelector, L"External Trigger"); + getBool(andor3::IOInvert, &flag); + if (flag) + iLevel = Inverted; + else + iLevel = Normal; +} //----------------------------------------------------- // @brief set the temperature set-point // DONE @@ -1620,7 +1674,11 @@ lima::Andor3::Camera::setSimpleGain(A3_SimpleGain i_gain) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::SimplePreAmpGainControl) ) { - setEnumIndex(andor3::SimplePreAmpGainControl, i_gain); + int the_err_code = setEnumIndex(andor3::SimplePreAmpGainControl, i_gain); + if ( AT_SUCCESS != the_err_code ) { + DEB_ERROR() << "Cannot set SimplePreAmpGainControl to " << i_gain + << " - " << DEB_VAR1(error_code(the_err_code)); + } } else { DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; diff --git a/tango/Andor3.py b/tango/Andor3.py index 7812858..e60c44a 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -92,6 +92,13 @@ class Andor3(PyTango.Device_4Impl): 'OFF': False} self.__SpuriousNoiseFilter = {'ON': True, 'OFF': False} + self.__GateLevel = { 'NORMAL': _Andor3Camera.Normal, + 'INVERTED': _Andor3Camera.Inverted, + } + self.__TriggerLevel = { 'NORMAL': _Andor3Camera.Normal, + 'INVERTED': _Andor3Camera.Inverted, + } + self.__Attribute2FunctionBase = {'adc_gain': 'SimpleGain', 'adc_rate': 'AdcRate', 'temperature': 'Temperature', @@ -106,6 +113,8 @@ class Andor3(PyTango.Device_4Impl): 'overlap': 'Overlap', 'spurious_noise_filter': 'SpuriousNoiseFilter', 'serial_number': 'SerialNumber', + 'gate_level': 'GateLevel', + 'trigger_level': 'TriggerLevel', } self.init_device() @@ -355,6 +364,26 @@ class Andor3Class(PyTango.DeviceClass): 'format': '', 'description': 'camera serial number', }], + 'trigger_level': + [[PyTango.DevString, + PyTango.SCALAR, + PyTango.READ_WRITE], + { + 'label':'External trigger level', + 'unit': 'N/A', + 'format': '', + 'description': 'NORMAl or INVERTED' + }], + 'gate_level': + [[PyTango.DevString, + PyTango.SCALAR, + PyTango.READ_WRITE], + { + 'label':'External gate level', + 'unit': 'N/A', + 'format': '', + 'description': 'NORMAl or INVERTED' + }], } #------------------------------------------------------------------ -- GitLab From ef7d8f141ec6b201821342a13e4d3c284cada275 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 18 Sep 2020 17:14:12 +0200 Subject: [PATCH 03/24] added output signal selection --- include/Andor3Camera.h | 7 +++++++ sip/Andor3Camera.sip | 3 +++ src/Andor3Camera.cpp | 27 +++++++++++++++++++++++++++ tango/Andor3.py | 16 ++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 2b412b5..d6379cf 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -78,7 +78,11 @@ namespace lima enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; + // trigger / gate level enum A3_SignalLevel { Normal=0, Inverted=1}; + + // output signal + enum A3_OutputSignal { FireRow1=0, FireRowN=1, FireAll=2, FireAny=3 }; struct SdkFrameDim { AT_64 width; @@ -164,6 +168,9 @@ namespace lima void setTriggerLevel(A3_SignalLevel iLevel); void getTriggerLevel(A3_SignalLevel &iLevel); + void setOutputSignal(A3_OutputSignal iSignal); + void getOutputSignal(A3_OutputSignal &oSignal) const; + void setAdcRate(A3_ReadOutRate iRate); // à exporter (avec le get) void getAdcRate(A3_ReadOutRate &oRate) const; void getAdcRateString(std::string &oRateString) const; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index 09b0436..5a120c4 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -41,6 +41,7 @@ namespace Andor3 enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; enum A3_SignalLevel {Normal=0, Inverted=1}; + enum A3_OutputSignal {FireRow1=0, FireRowN=1, FireAll=2, FireAny=3}; Camera(const std::string& bitflow_path, int camera_number=0); ~Camera(); @@ -99,6 +100,8 @@ namespace Andor3 void getGateLevel(A3_SignalLevel &iLevel /Out/ ); void setTriggerLevel(A3_SignalLevel iLevel /In/ ); void getTriggerLevel(A3_SignalLevel &iLevel /Out/ ); + void setOutputSignal(A3_OutputSignal iSignal /In/ ); + void getOutputSignal(A3_OutputSignal &oSignal /Out/ ) const; void setAdcGain(A3_Gain iGain /In/ ); void getAdcGain(A3_Gain &oGain /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 1157325..ed03706 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -94,6 +94,7 @@ namespace lima { static const AT_WC* IOSelector = L"IOSelector"; static const AT_WC* IOInvert = L"IOInvert"; + static const AT_WC* AuxiliaryOutSource = L"AuxiliaryOutSource"; // For future !! // static const AT_WC* AccumulateCount = L"AccumulateCount"; @@ -1486,6 +1487,32 @@ lima::Andor3::Camera::getTriggerLevel(A3_SignalLevel &iLevel) iLevel = Normal; } +void +lima::Andor3::Camera::setOutputSignal(A3_OutputSignal iSignal) +{ + DEB_MEMBER_FUNCT(); + if ( propImplemented(andor3::AuxiliaryOutSource) ) { + setEnumIndex(andor3::AuxiliaryOutSource, iSignal); + } + else { + DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; + } +} + +void +lima::Andor3::Camera::getOutputSignal(A3_OutputSignal &oSignal) const +{ + DEB_MEMBER_FUNCT(); + if ( propImplemented(andor3::AuxiliaryOutSource) ) { + int value; + getEnumIndex(andor3::AuxiliaryOutSource, &value); + oSignal = static_cast<A3_OutputSignal>(value); + } + else { + DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; + } +} + //----------------------------------------------------- // @brief set the temperature set-point // DONE // @param temperature in centigrade diff --git a/tango/Andor3.py b/tango/Andor3.py index e60c44a..854ad6f 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -98,6 +98,11 @@ class Andor3(PyTango.Device_4Impl): self.__TriggerLevel = { 'NORMAL': _Andor3Camera.Normal, 'INVERTED': _Andor3Camera.Inverted, } + self.__OutputSignal = { 'FIREROW1': _Andor3Camera.FireRow1, + 'FIREROWN': _Andor3Camera.FireRowN, + 'FIREALL': _Andor3Camera.FireAll, + 'FIREANY': _Andor3Camera.FireAny, + } self.__Attribute2FunctionBase = {'adc_gain': 'SimpleGain', 'adc_rate': 'AdcRate', @@ -115,6 +120,7 @@ class Andor3(PyTango.Device_4Impl): 'serial_number': 'SerialNumber', 'gate_level': 'GateLevel', 'trigger_level': 'TriggerLevel', + 'output_signal': 'OutputSignal', } self.init_device() @@ -384,6 +390,16 @@ class Andor3Class(PyTango.DeviceClass): 'format': '', 'description': 'NORMAl or INVERTED' }], + 'output_signal': + [[PyTango.DevString, + PyTango.SCALAR, + PyTango.READ_WRITE], + { + 'label':'Output signal selection', + 'unit': 'N/A', + 'format': '', + 'description': 'FireRow1, FireRowN, FireAny, FireAll', + }], } #------------------------------------------------------------------ -- GitLab From b103df0db909658eecd56de096940df6e640fde2 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Tue, 12 Jan 2021 15:16:22 +0100 Subject: [PATCH 04/24] update server properties --- tango/Andor3.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tango/Andor3.py b/tango/Andor3.py index 854ad6f..9895f22 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -143,16 +143,19 @@ class Andor3(PyTango.Device_4Impl): # Apply properties if any if self.adc_gain: - _Andor3Interface.setAdcGain(self.__AdcGain[self.adc_gain]) + _Andor3Camera.setSimpleGain(self.__AdcGain[self.adc_gain]) if self.adc_rate: - _Andor3Interface.setAdcRate(self.__AdcRate[self.adc_rate]) + _Andor3Camera.setAdcRate(self.__AdcRate[self.adc_rate]) if self.temperature_sp: _Andor3Camera.setTemperatureSP(self.temperature_sp) if self.cooler: _Andor3Camera.setCooler(self.__Cooler[self.cooler]) + + if self.overlap: + _Andor3Camera.setOverlap(self.__Overlap[self.overlap]) #================================================================== @@ -217,6 +220,9 @@ class Andor3Class(PyTango.DeviceClass): 'cooler': [PyTango.DevString, 'Start or stop the cooler ("ON"/"OFF")', []], + 'overlap': + [PyTango.DevString, + 'Overlap mode', []], } -- GitLab From 6efb02281312b6c4eb7cf00ac8a42012acdd9683 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 23 Mar 2022 14:07:01 +0100 Subject: [PATCH 05/24] Rework temperature control so it can work also for Marana detector. This detector has a predefined set of set-point values while other detector can set temperature to any value. --- include/Andor3Camera.h | 6 +- src/Andor3Camera.cpp | 123 ++++++++++++++++++++++++++++------------- 2 files changed, 90 insertions(+), 39 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index d6379cf..cc1d0a5 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -28,6 +28,7 @@ #include <stdlib.h> #include <limits> #include <ostream> +#include <vector> // Camera SDK headers : #include <atcore.h> @@ -234,6 +235,7 @@ namespace lima private: void initTrigMode(); + void initTemperature(); // -- andor3 Lower level functions int printInfoForProp(const AT_WC * iPropName, A3_TypeInfo iPropType) const; @@ -311,7 +313,9 @@ namespace lima A3_BitDepth m_bit_depth; bool m_cooler; double m_temperature_sp; - bool m_temperature_control_available; + bool m_has_temperature_sp; + bool m_has_temperature_control; + std::vector<float> m_temperature_control_values; TrigMode m_trig_mode; // A3_TriggerMode m_trig_mode; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index ed03706..4341b8a 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -115,7 +115,7 @@ namespace lima { // static const AT_WC* RowNExposureEndEvent = L"RowNExposureEndEvent"; // static const AT_WC* RowNExposureStartEvent = L"RowNExposureStartEvent"; // static const AT_WC* SoftwareVersion = L"SoftwareVersion"; - // static const AT_WC* TemperatureControl = L"TemperatureControl"; + static const AT_WC* TemperatureControl = L"TemperatureControl"; // static const AT_WC* TimestampClock = L"TimestampClock"; // static const AT_WC* TimestampClockFrequency = L"TimestampClockFrequency"; // static const AT_WC* TimestampClockReset = L"TimestampClockReset"; @@ -176,8 +176,9 @@ m_electronic_shutter_mode(Rolling), m_bit_depth(b16), m_trig_mode(IntTrig), m_cooler(true), -m_temperature_sp(5.0), -m_temperature_control_available(true), +m_temperature_sp(999.99), +m_has_temperature_sp(false), +m_has_temperature_control(false), m_maximage_size_cb_active(false) { DEB_CONSTRUCTOR(); @@ -310,6 +311,8 @@ m_maximage_size_cb_active(false) // printInfoForProp(andor3::SimplePreAmpGainControl, Enum); // printInfoForProp(andor3::FanSpeed, Enum); // printInfoForProp(andor3::BitDepth, Enum); +// printInfoForProp(andor3::TemperatureControl, Enum); +// printInfoForProp(andor3::AuxiliaryOutSource, Enum); // --- Initialise deeper parameters of the controller initialiseController(); @@ -326,7 +329,7 @@ lima::Andor3::Camera::~Camera() m_acq_thread = NULL; // Close camera - if (m_cooler && m_temperature_control_available) { + if (m_cooler && m_has_temperature_sp) { DEB_ERROR() <<"Please stop the cooling before shuting dowm the camera\n" << "brutale heating could damage the sensor.\n" << "And wait until temperature rises above 5 deg, before shuting down."; @@ -1197,7 +1200,7 @@ lima::Andor3::Camera::initialiseController() setAdcRate(the_rate); setBitDepth(the_bd); setCooler(m_cooler); - setTemperatureSP(m_temperature_sp); + initTemperature(); setExpTime(m_exp_time); setSpuriousNoiseFilter(false); @@ -1513,6 +1516,36 @@ lima::Andor3::Camera::getOutputSignal(A3_OutputSignal &oSignal) const } } +//----------------------------------------------------- +// @brief retrieve temperature capabilities +//----------------------------------------------------- +void +lima::Andor3::Camera::initTemperature() +{ + DEB_MEMBER_FUNCT(); + if ( propImplemented(andor3::TargetSensorTemperature) && m_detector_model.find("ZYLA5.5")==std::string::npos ) { + m_has_temperature_sp = true; + getFloat(andor3::TargetSensorTemperature, &m_temperature_sp); + } + else if ( propImplemented(andor3::TemperatureControl) ) { + int ntemp, current_idx; + AT_WC at_string[256]; + float value; + + m_has_temperature_control = true; + DEB_ALWAYS() << "Camera has temperature setpoints pre-defined"; + getEnumCount(m_camera_handle, andor3::TemperatureControl, &ntemp); + for (int idx=0; idx != ntemp; ++idx) { + AT_GetEnumStringByIndex(m_camera_handle, andor3::TemperatureControl, idx, at_string, 255); + value = std::stof(WStringToString(at_string)); + m_temperature_control_values.push_back(value); + DEB_ALWAYS() << "Index " << idx << " Setpoint " << value; + } + getEnumIndex(andor3::TemperatureControl, ¤t_idx); + m_temperature_sp = m_temperature_control_values[current_idx]; + } +} + //----------------------------------------------------- // @brief set the temperature set-point // DONE // @param temperature in centigrade @@ -1522,8 +1555,8 @@ void lima::Andor3::Camera::setTemperatureSP(double temp) { DEB_MEMBER_FUNCT(); - // Zyla-5.5 camera is supposed to not have this feature, but propImplemented returned True !!! - if ( propImplemented(andor3::TargetSensorTemperature) && m_detector_model.find("ZYLA5.5")==std::string::npos ) { + + if (m_has_temperature_sp) { setFloat(andor3::TargetSensorTemperature, temp); getFloat(andor3::TargetSensorTemperature, &m_temperature_sp); if ( abs(m_temperature_sp - temp) > 0.1) { @@ -1533,9 +1566,23 @@ lima::Andor3::Camera::setTemperatureSP(double temp) THROW_HW_ERROR(Error) << "Failed on setting temperature set-point"; } } + else if (m_has_temperature_control) { + float temp_idx = 0; + int size = m_temperature_control_values.size(); + int current_idx; + for (int idx=size-1; idx>= 0; --idx) { + if (temp <= m_temperature_control_values[idx]) { + temp_idx = idx; + break; + } + } + setEnumIndex(andor3::TemperatureControl, temp_idx); + getEnumIndex(andor3::TemperatureControl, ¤t_idx); + m_temperature_sp = m_temperature_control_values[current_idx]; + } else { - DEB_ALWAYS() << "This camera has no temperature set-point control !"; - m_temperature_control_available = false; + DEB_ERROR() << "Camera has no temperature set-point control"; + THROW_HW_ERROR(Error) << "Camera has no temperature set-point control"; } } @@ -2108,41 +2155,41 @@ lima::Andor3::Camera::printInfoForProp(const AT_WC * iPropName, A3_TypeInfo iPro AT_BOOL b_writable; AT_BOOL b_readable; - DEB_ALWAYS() << "Retrieving information on property named \"" << WStringToString(iPropName) << "\".\n"; + std::cout << "\nRetrieving information on property named \"" << WStringToString(iPropName) << "\".\n"; int ret_code; // Implemented if ( AT_SUCCESS != (ret_code = AT_IsImplemented(m_camera_handle, iPropName, &b_exists)) ) { - DEB_ALWAYS() << "Error in printInfoForProp : " << error_code(ret_code); + std::cout << "Error in printInfoForProp : " << error_code(ret_code); return i_err; } - DEB_ALWAYS() << "\tIsImplemented = " << atBoolToString(b_exists); + std::cout << "\tIsImplemented = " << atBoolToString(b_exists); if ( ! b_exists ) { - DEB_ALWAYS() << "No more information to query, since the feature does not \"exists\" for this camera/driver/SDK."; + std::cout << "No more information to query, since the feature does not \"exists\" for this camera/driver/SDK."; return i_err; } // ReadOnly AT_IsReadOnly(m_camera_handle, iPropName, &b_readonly); - DEB_ALWAYS() << "\tIsReadOnly = " << atBoolToString(b_readonly); + std::cout << "\tIsReadOnly = " << atBoolToString(b_readonly); // Writable AT_IsWritable(m_camera_handle, iPropName, &b_writable); - DEB_ALWAYS() << "\tIsWritable = " << atBoolToString(b_writable); + std::cout << "\tIsWritable = " << atBoolToString(b_writable); // Readable AT_IsReadable(m_camera_handle, iPropName, &b_readable); - DEB_ALWAYS() << "\tIsReadable = " << atBoolToString(b_readable); + std::cout << "\tIsReadable = " << atBoolToString(b_readable); if ( ! b_readable ) { - DEB_ALWAYS() << "Since the property is not readable at this time, we will stop here."; + std::cout << "Since the property is not readable at this time, we will stop here."; return i_err; } // Now getting the value itself : we absolutely need now to know the type of the feature : if ( Camera::Unknown == iPropType ) { - DEB_ALWAYS() << "Could not retrieve information on a property of unknown type !!\n" + std::cout << "Could not retrieve information on a property of unknown type !!\n" << "Returning error code!!"; return -1; } @@ -2200,47 +2247,47 @@ lima::Andor3::Camera::printInfoForProp(const AT_WC * iPropName, A3_TypeInfo iPro break; case Camera::Enum: - DEB_ALWAYS() << "\tFeature of type ENUM"; + std::cout << "\n\tFeature of type ENUM"; if ( AT_SUCCESS == (ret_code = AT_GetEnumIndex(m_camera_handle, iPropName, &enum_Value)) ) { - DEB_ALWAYS() << "\tValue = (" << enum_Value << ")"; + std::cout << "\n\tValue = (" << enum_Value << ")"; if ( AT_SUCCESS == (ret_code = AT_GetEnumStringByIndex(m_camera_handle, iPropName, enum_Value, s_Value, 1024)) ) - DEB_ALWAYS() << " \"" << WStringToString(s_Value) << "\""; + std::cout << " \"" << WStringToString(s_Value) << "\""; else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + std::cout << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexImplemented(m_camera_handle, iPropName, enum_Value, &b_Value)) ) - DEB_ALWAYS() << "; implemented = " << atBoolToString(b_Value); + std::cout << "; implemented = " << atBoolToString(b_Value); else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + std::cout << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexAvailable(m_camera_handle, iPropName, enum_Value, &b_Value)) ) - DEB_ALWAYS() << "; available = " << atBoolToString(b_Value); + std::cout << "; available = " << atBoolToString(b_Value); else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); - DEB_ALWAYS() << "."; + std::cout << "\tError message : " << error_code(ret_code); + std::cout << "."; } else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + std::cout << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_GetEnumCount(m_camera_handle, iPropName, &enum_Count)) ) { - DEB_ALWAYS() << "\tAvailable choices are (" << enum_Count << ") :"; + std::cout << "\n\tAvailable choices are (" << enum_Count << ") :"; for ( int i=0; enum_Count != i; ++i ) { - DEB_ALWAYS() << "\t\t(" << i << ")"; + std::cout << "\n\t\t(" << i << ")"; if ( AT_SUCCESS == (ret_code = AT_GetEnumStringByIndex(m_camera_handle, iPropName, i, s_Value, 1024)) ) - DEB_ALWAYS() << " \"" << WStringToString(s_Value) << "\""; + std::cout << " \"" << WStringToString(s_Value) << "\""; else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + std::cout << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexImplemented(m_camera_handle, iPropName, i, &b_Value)) ) - DEB_ALWAYS() << "; implemented = " << atBoolToString(b_Value); + std::cout << "; implemented = " << atBoolToString(b_Value); else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + std::cout << "\tError message : " << error_code(ret_code); if ( AT_SUCCESS == (ret_code = AT_IsEnumIndexAvailable(m_camera_handle, iPropName, i, &b_Value)) ) - DEB_ALWAYS() << "; available = " << atBoolToString(b_Value); + std::cout << "; available = " << atBoolToString(b_Value); else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); - DEB_ALWAYS() << "."; + std::cout << "\tError message : " << error_code(ret_code); + std::cout << "."; } } else - DEB_ALWAYS() << "\tError message : " << error_code(ret_code); + std::cout << "\tError message : " << error_code(ret_code); break; -- GitLab From 325f3bb1cdcb8bcfd4663703548087220147f8e4 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 23 Mar 2022 16:08:04 +0100 Subject: [PATCH 06/24] Change fan speed set/get to work with strings. The list of possible values are camera-dependant and can be retrieved by getFanSpeedList. Removed the previous fixed enum. --- include/Andor3Camera.h | 10 +++++----- sip/Andor3Camera.sip | 9 +++++---- src/Andor3Camera.cpp | 41 +++++++++++++++++++---------------------- tango/Andor3.py | 16 ++++++++++++---- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index cc1d0a5..7113e03 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -75,8 +75,6 @@ namespace lima // The binning system of andor3 : enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; - // The fan speed - enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; // trigger / gate level @@ -193,9 +191,11 @@ namespace lima void setBufferOverflow(bool i_overflow); void getBufferOverflow(bool &o_overflow) const; - void setFanSpeed(A3_FanSpeed iFS); - void getFanSpeed(A3_FanSpeed &oFS) const; - void getFanSpeedString(std::string &oFSString) const; + + void setFanSpeed(std::string fan_speed); + void getFanSpeed(std::string &fan_speed) const; + void getFanSpeedList(std::vector<std::string> &fan_speed_list) const; + void setOverlap(bool i_overlap); void getOverlap(bool &o_overlap) const; void setSimpleGain(A3_SimpleGain i_gain); diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index 5a120c4..97d8b5a 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -38,7 +38,6 @@ namespace Andor3 enum A3_BitDepth { b11 = 0, b16= 1 }; // enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; - enum A3_FanSpeed { Off=0, Low=1, On=2}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; enum A3_SignalLevel {Normal=0, Inverted=1}; enum A3_OutputSignal {FireRow1=0, FireRowN=1, FireAll=2, FireAny=3}; @@ -128,9 +127,11 @@ namespace Andor3 void setBufferOverflow(bool i_overflow /In/ ); void getBufferOverflow(bool &o_overflow /Out/ ) const; - void setFanSpeed(A3_FanSpeed iFS /In/ ); - void getFanSpeed(A3_FanSpeed &oFS /Out/ ) const; - void getFanSpeedString(std::string &oFSString /Out/ ) const; + + void setFanSpeed(std::string fan_speed /In/ ); + void getFanSpeed(std::string &fan_speed /Out/ ) const; + void getFanSpeedList(std::vector<std::string> &fs_list /Out/ ) const; + void setOverlap(bool i_overlap /In/ ); void getOverlap(bool &o_overlap /Out/ ) const; void setSimpleGain(A3_SimpleGain i_gain /In/ ); diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 4341b8a..467dd17 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -107,8 +107,6 @@ namespace lima { // static const AT_WC* MetadataFrame = L"MetadataFrame"; // static const AT_WC* MetadataTimestamp = L"MetadataTimestamp"; // static const AT_WC* PixelCorrection = L"PixelCorrection"; - // static const AT_WC* PixelHeight = L"PixelHeight"; - // static const AT_WC* PixelWidth = L"PixelWidth"; // static const AT_WC* PreAmpGain = L"PreAmpGain"; // Deprecated // static const AT_WC* PreAmpGainChannel = L"PreAmpGainChannel"; // Deprecated // static const AT_WC* PreAmpGainSelector = L"PreAmpGainSelector"; // Deprecated @@ -1681,48 +1679,47 @@ lima::Andor3::Camera::getBufferOverflow(bool &o_overflow) const void -lima::Andor3::Camera::setFanSpeed(A3_FanSpeed iFS) +lima::Andor3::Camera::getFanSpeedList(std::vector<std::string> &fan_speed_list) const { - DEB_MEMBER_FUNCT(); - if ( propImplemented(andor3::FanSpeed) ) { - setEnumIndex(andor3::FanSpeed, iFS); - } - else { - DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; + int enum_count; + AT_WC s_value[1024]; + + AT_GetEnumCount(m_camera_handle, andor3::FanSpeed, &enum_count); + + for (int idx=0; enum_count != idx; ++idx) { + AT_GetEnumStringByIndex(m_camera_handle, andor3::FanSpeed, idx, s_value, 1024); + fan_speed_list.push_back(WStringToString(s_value)); } } void -lima::Andor3::Camera::getFanSpeed(A3_FanSpeed &oFS) const +lima::Andor3::Camera::setFanSpeed(std::string fan_speed) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::FanSpeed) ) { - int the_fs; - getEnumIndex(andor3::FanSpeed, &the_fs); - oFS = static_cast<A3_FanSpeed>(the_fs); + const std::wstring fan_set = StringToWString(fan_speed); + setEnumString(andor3::FanSpeed, fan_set.c_str()); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; - } + } } - void -lima::Andor3::Camera::getFanSpeedString(std::string &oFSString) const +lima::Andor3::Camera::getFanSpeed(std::string &fan_speed) const { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::FanSpeed) ) { - AT_WC the_string[256]; - getEnumString(andor3::FanSpeed, the_string, 255); - oFSString = WStringToString(std::wstring(the_string)); + AT_WC fan_string[256]; + getEnumString(andor3::FanSpeed, fan_string, 255); + fan_speed = WStringToString(fan_string); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; - oFSString = "not implemented"; - } + fan_speed = "not implemented"; + } } - void lima::Andor3::Camera::setOverlap(bool i_overlap) { diff --git a/tango/Andor3.py b/tango/Andor3.py index 9895f22..95b4ce5 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -48,6 +48,15 @@ from Lima import Andor3 as Andor3Module # and Lima interfaces. from Lima.Server import AttrHelper +def andor_list2dict(alist): + adict = dict() + for name in alist: + newname = name.upper().strip() + newname = newname.replace("(", "").replace(")", "").replace("-", "_").replace(" ", "_") + adict[newname] = name + return adict + + class Andor3(PyTango.Device_4Impl): Core.DEB_CLASS(Core.DebModApplication, 'LimaCCDs') @@ -81,10 +90,6 @@ class Andor3(PyTango.Device_4Impl): } self.__Cooler = {'ON': True, 'OFF': False} - self.__FanSpeed = {'OFF': _Andor3Camera.Off, - 'LOW': _Andor3Camera.Low, - 'HIGH': _Andor3Camera.On, - } self.__ElectronicShutterMode = {'ROLLING': _Andor3Camera.Rolling, 'GLOBAL': _Andor3Camera.Global, } @@ -103,6 +108,7 @@ class Andor3(PyTango.Device_4Impl): 'FIREALL': _Andor3Camera.FireAll, 'FIREANY': _Andor3Camera.FireAny, } + self.__FanSpeed = andor_list2dict(_Andor3Camera.getFanSpeedList()) self.__Attribute2FunctionBase = {'adc_gain': 'SimpleGain', 'adc_rate': 'AdcRate', @@ -122,6 +128,8 @@ class Andor3(PyTango.Device_4Impl): 'trigger_level': 'TriggerLevel', 'output_signal': 'OutputSignal', } + + self.init_device() #------------------------------------------------------------------ -- GitLab From 2ab026faa89f1436d557e146cff60a4c4a78f0e2 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Thu, 24 Mar 2022 11:00:28 +0100 Subject: [PATCH 07/24] Change private methods to use std::string instead of AT_WC* when setting/getting string andor parameters --- include/Andor3Camera.h | 13 ++-- src/Andor3Camera.cpp | 152 +++++++++++++++++++---------------------- 2 files changed, 78 insertions(+), 87 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 7113e03..31ed347 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -258,17 +258,18 @@ namespace lima int getBool(const AT_WC* Feature, bool* Value) const; int setEnumIndex(const AT_WC* Feature, int Value); - int setEnumString(const AT_WC* Feature, const AT_WC* String); int getEnumIndex(const AT_WC* Feature, int* Value) const; - int getEnumString(const AT_WC* Feature, AT_WC* String, int StringLength) const; + int setEnumString(const AT_WC* Feature, std::string Value); + int getEnumString(const AT_WC* Feature, std::string& Value) const; int getEnumCount(AT_H Hndl,const AT_WC* Feature, int* Count) const; int isEnumIndexAvailable(const AT_WC* Feature, int Index, bool* Available) const; int isEnumIndexImplemented(const AT_WC* Feature, int Index, bool* Implemented) const; - int getEnumStringByIndex(const AT_WC* Feature, int Index, AT_WC* String, int StringLength) const; - int getEnumIndexByString(const AT_WC* Feature, AT_WC* String, int *Index) const; + + int getEnumStringByIndex(const AT_WC* Feature, int Index, std::string& Value) const; + int getEnumIndexByString(const AT_WC* Feature, std::string Value, int *Index) const; - int setString(const AT_WC* Feature, const AT_WC* String); - int getString(const AT_WC* Feature, AT_WC* String, int StringLength) const; + int setString(const AT_WC* Feature, std::string Value); + int getString(const AT_WC* Feature, std::string& Value) const; int sendCommand(const AT_WC* Feature); diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 467dd17..13096cc 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -233,12 +233,9 @@ m_maximage_size_cb_active(false) } // --- Get Camera model (and all other parameters which are not changing during camera setup and usage ) - AT_WC model[1024]; - THROW_IF_NOT_SUCCESS(getString(andor3::CameraModel, model, 1024), + THROW_IF_NOT_SUCCESS(getString(andor3::CameraModel, m_detector_model), "Cannot get camera model"); - m_detector_model = WStringToString(std::wstring(model)); - // Adding some extra information on the model (more human readable) : // DC-152 -> Neo if ( ! m_detector_model.compare(0, 6, "DC-152 ")) { @@ -282,12 +279,9 @@ m_maximage_size_cb_active(false) } // --- Get Camera Serial number - AT_WC serial[1024]; - THROW_IF_NOT_SUCCESS(getString(andor3::SerialNumber, serial, 1024), + THROW_IF_NOT_SUCCESS(getString(andor3::SerialNumber, m_detector_serial), "Cannot get camera serial number"); - m_detector_serial = WStringToString(std::wstring(serial)); - // --- Get Camera maximum image size AT_64 xmax, ymax; // --- Get the max image size of the detector @@ -476,16 +470,16 @@ lima::Andor3::Camera::prepareAcq() DEB_TRACE()<< "Software trigger ON, set CycleMode to Fixed mode"; AT_64 nb_frames = static_cast<AT_64>(m_nb_frames_to_collect); setInt(andor3::FrameCount, nb_frames); - setEnumString(andor3::CycleMode, L"Fixed"); + setEnumString(andor3::CycleMode, "Fixed"); } else { - setEnumString(andor3::CycleMode, L"Continuous"); + setEnumString(andor3::CycleMode, "Continuous"); } - AT_WC the_string[256]; - getEnumString(andor3::CycleMode, the_string, 255); - DEB_TRACE() << "At the end of prepareAcq, the CycleMode is " << WStringToString(std::wstring(the_string)); + std::string cycle_mode; + getEnumString(andor3::CycleMode, cycle_mode); + DEB_TRACE() << "At the end of prepareAcq, the CycleMode is " << cycle_mode; } @@ -713,7 +707,7 @@ lima::Andor3::Camera::setTrigMode(TrigMode mode) } } else { - setEnumString(andor3::TriggerMode, L"Advanced"); + setEnumString(andor3::TriggerMode, "Advanced"); DEB_TRACE() << "SIMCAM - forcing trigger mode to Advanced"; m_trig_mode = mode; } @@ -1278,9 +1272,7 @@ lima::Andor3::Camera::getAdcGain(A3_Gain &oGain) const void lima::Andor3::Camera::getAdcGainString(std::string &oGainString) const { - AT_WC the_string[256]; - getEnumString(andor3::PreAmpGainControl, the_string, 255); - oGainString = WStringToString(std::wstring(the_string)); + getEnumString(andor3::PreAmpGainControl, oGainString); } @@ -1321,9 +1313,7 @@ lima::Andor3::Camera::getAdcRate(A3_ReadOutRate &oRate) const void lima::Andor3::Camera::getAdcRateString(std::string &oRateString) const { - AT_WC the_string[256]; - getEnumString(andor3::PixelReadoutRate, the_string, 255); - oRateString = WStringToString(std::wstring(the_string)); + getEnumString(andor3::PixelReadoutRate, oRateString); } void @@ -1361,9 +1351,7 @@ lima::Andor3::Camera::getElectronicShutterMode(A3_ShutterMode &oMode) const void lima::Andor3::Camera::getElectronicShutterModeString(std::string &oModeString) const { - AT_WC the_string[256]; - getEnumStringByIndex(andor3::ElectronicShutteringMode, m_electronic_shutter_mode, the_string, 255); - oModeString = WStringToString(std::wstring(the_string)); + getEnumStringByIndex(andor3::ElectronicShutteringMode, m_electronic_shutter_mode, oModeString); } void @@ -1383,10 +1371,10 @@ lima::Andor3::Camera::setBitDepth(A3_BitDepth iMode) // Making sure that the pixel encoding is a predictable one, depending on the bit-depth. switch (m_bit_depth) { case b11: - setEnumString(andor3::PixelEncoding, L"Mono12"); + setEnumString(andor3::PixelEncoding, "Mono12"); break; case b16: - setEnumString(andor3::PixelEncoding, L"Mono16"); + setEnumString(andor3::PixelEncoding, "Mono16"); break; default: break; @@ -1403,17 +1391,13 @@ lima::Andor3::Camera::getBitDepth(A3_BitDepth &oMode) const void lima::Andor3::Camera::getBitDepthString(std::string &oDepthString) const { - AT_WC the_string[256]; - getEnumStringByIndex(andor3::BitDepth, m_bit_depth, the_string, 255); - oDepthString = WStringToString(std::wstring(the_string)); + getEnumStringByIndex(andor3::BitDepth, m_bit_depth, oDepthString); } void lima::Andor3::Camera::getPxEncodingString(std::string &oPxEncodingString) const { - AT_WC the_string[256]; - getEnumString(andor3::PixelEncoding, the_string, 255); - oPxEncodingString = WStringToString(std::wstring(the_string)); + getEnumString(andor3::PixelEncoding, oPxEncodingString); } void @@ -1428,12 +1412,9 @@ lima::Andor3::Camera::getPxEncoding(A3_PixelEncoding &oPxEncoding) const void lima::Andor3::Camera::getTriggerModeString(std::string &oModeString) const { - AT_WC the_string[256]; - int i_trig; if (m_real_camera) { - i_trig = m_trig_mode_map.at(m_trig_mode); - getEnumStringByIndex(andor3::TriggerMode, m_trig_mode, the_string, 255); - oModeString = WStringToString(std::wstring(the_string)); + int i_trig = m_trig_mode_map.at(m_trig_mode); + getEnumStringByIndex(andor3::TriggerMode, i_trig, oModeString); } else { oModeString = "Advanced"; @@ -1447,7 +1428,7 @@ lima::Andor3::Camera::setGateLevel(A3_SignalLevel iLevel) bool flag; if (iLevel == Inverted) flag= true; else flag= false; - setEnumString(andor3::IOSelector, L"External Exposure"); + setEnumString(andor3::IOSelector, "External Exposure"); setBool(andor3::IOInvert, flag); } @@ -1456,7 +1437,7 @@ lima::Andor3::Camera::getGateLevel(A3_SignalLevel &iLevel) { DEB_MEMBER_FUNCT(); bool flag; - setEnumString(andor3::IOSelector, L"External Exposure"); + setEnumString(andor3::IOSelector, "External Exposure"); getBool(andor3::IOInvert, &flag); if (flag) iLevel = Inverted; @@ -1471,7 +1452,7 @@ lima::Andor3::Camera::setTriggerLevel(A3_SignalLevel iLevel) bool flag; if (iLevel == Inverted) flag= true; else flag= false; - setEnumString(andor3::IOSelector, L"External Trigger"); + setEnumString(andor3::IOSelector, "External Trigger"); setBool(andor3::IOInvert, flag); } @@ -1480,7 +1461,7 @@ lima::Andor3::Camera::getTriggerLevel(A3_SignalLevel &iLevel) { DEB_MEMBER_FUNCT(); bool flag; - setEnumString(andor3::IOSelector, L"External Trigger"); + setEnumString(andor3::IOSelector, "External Trigger"); getBool(andor3::IOInvert, &flag); if (flag) iLevel = Inverted; @@ -1648,12 +1629,11 @@ lima::Andor3::Camera::getCoolingStatus(std::string& status) const { DEB_MEMBER_FUNCT(); if ( m_real_camera ) { - wchar_t wcs_status_string[32]; - getEnumString(andor3::TemperatureStatus, wcs_status_string, 31); - status = WStringToString(wcs_status_string); + getEnumString(andor3::TemperatureStatus, status); } else { DEB_TRACE() << "This has no signification on SIMCAM"; + status = "unknown"; } } @@ -1697,8 +1677,7 @@ lima::Andor3::Camera::setFanSpeed(std::string fan_speed) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::FanSpeed) ) { - const std::wstring fan_set = StringToWString(fan_speed); - setEnumString(andor3::FanSpeed, fan_set.c_str()); + setEnumString(andor3::FanSpeed, fan_speed); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; @@ -1710,9 +1689,7 @@ lima::Andor3::Camera::getFanSpeed(std::string &fan_speed) const { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::FanSpeed) ) { - AT_WC fan_string[256]; - getEnumString(andor3::FanSpeed, fan_string, 255); - fan_speed = WStringToString(fan_string); + getEnumString(andor3::FanSpeed, fan_speed); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; @@ -1853,9 +1830,7 @@ lima::Andor3::Camera::getSimpleGainString(std::string &o_gainString) const { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::SimplePreAmpGainControl) ) { - AT_WC the_string[256]; - getEnumString(andor3::SimplePreAmpGainControl, the_string, 255); - o_gainString = WStringToString(std::wstring(the_string)); + getEnumString(andor3::SimplePreAmpGainControl, o_gainString); } else { DEB_TRACE() << "The camera has no simple gain control setting... Do nothing !"; @@ -1916,9 +1891,7 @@ void lima::Andor3::Camera::getFirmwareVersion(std::string &o_fwv) const { DEB_MEMBER_FUNCT(); - AT_WC the_fwv[1024]; - getString(andor3::FirmwareVersion, the_fwv, 1024); - o_fwv = WStringToString(the_fwv); + getString(andor3::FirmwareVersion, o_fwv); } @@ -1998,9 +1971,7 @@ void lima::Andor3::Camera::getSerialNumber(std::string &o_sn) const { DEB_MEMBER_FUNCT(); - AT_WC the_sn[1024]; - getString(andor3::SerialNumber, the_sn, 1024); - o_sn = WStringToString(the_sn); + getString(andor3::SerialNumber, o_sn); } @@ -2428,28 +2399,37 @@ lima::Andor3::Camera::setEnumIndex(const AT_WC* Feature, int Value) } int -lima::Andor3::Camera::setEnumString(const AT_WC* Feature, const AT_WC* String) +lima::Andor3::Camera::getEnumIndex(const AT_WC* Feature, int* Value) const { DEB_MEMBER_FUNCT(); - return AT_SetEnumString(m_camera_handle, Feature, String); + return AT_GetEnumIndex(m_camera_handle, Feature, Value); } int -lima::Andor3::Camera::getEnumIndex(const AT_WC* Feature, int* Value) const +lima::Andor3::Camera::setEnumString(const AT_WC* Feature, std::string Value) { DEB_MEMBER_FUNCT(); - return AT_GetEnumIndex(m_camera_handle, Feature, Value); + const std::wstring value_set = StringToWString(Value); + return AT_SetEnumString(m_camera_handle, Feature, value_set.c_str()); } int -lima::Andor3::Camera::getEnumString(const AT_WC* Feature, AT_WC* String, int StringLength) const +lima::Andor3::Camera::getEnumString(const AT_WC* Feature, std::string& Value) const { DEB_MEMBER_FUNCT(); - int Value; - int i_Err = AT_GetEnumIndex(m_camera_handle, Feature, &Value); - if ( AT_SUCCESS != i_Err ) - return i_Err; - return AT_GetEnumStringByIndex(m_camera_handle, Feature, Value, String, StringLength); + int value_idx, ierr; + + ierr = AT_GetEnumIndex(m_camera_handle, Feature, &value_idx); + if (AT_SUCCESS != ierr) + return ierr; + + AT_WC value_str[256]; + ierr = AT_GetEnumStringByIndex(m_camera_handle, Feature, value_idx, value_str, 255); + if (AT_SUCCESS != ierr) + return ierr; + + Value = WStringToString(value_str); + return ierr; } int @@ -2468,6 +2448,7 @@ lima::Andor3::Camera::isEnumIndexAvailable(const AT_WC* Feature, int Index, bool *Available = isAvailable; return i_Err; } + int lima::Andor3::Camera::isEnumIndexImplemented(const AT_WC* Feature, int Index, bool* Implemented) const { @@ -2479,38 +2460,40 @@ lima::Andor3::Camera::isEnumIndexImplemented(const AT_WC* Feature, int Index, bo } int -lima::Andor3::Camera::getEnumStringByIndex(const AT_WC* Feature, int Index, AT_WC* String, int StringLength) const +lima::Andor3::Camera::getEnumStringByIndex(const AT_WC* Feature, int Index, std::string& Value) const { DEB_MEMBER_FUNCT(); - return AT_GetEnumStringByIndex(m_camera_handle, Feature, Index, String, StringLength); + AT_WC the_string[256]; + int ierr = AT_GetEnumStringByIndex(m_camera_handle, Feature, Index, the_string, 255); + Value = WStringToString(std::wstring(the_string)); + return ierr; } int -lima::Andor3::Camera::getEnumIndexByString(const AT_WC* Feature, AT_WC* String, int *Index) const +lima::Andor3::Camera::getEnumIndexByString(const AT_WC* Feature, std::string Value, int *Index) const { DEB_MEMBER_FUNCT(); - int i_Err; - int i_enumCount; + int i_Err; + int i_enumCount; int i_enumIndex; - const int i_maxStringLen = 1024; - AT_WC wcs_enumString[i_maxStringLen + 5]; + std::string s_enumString; if ( AT_SUCCESS != (i_Err = getEnumCount(m_camera_handle, Feature, &i_enumCount)) ) { DEB_ERROR() << "Failed to get Enum Count" << " : error code = " << error_code(i_Err); return i_Err; } for (i_enumIndex = 0; i_enumCount != i_enumIndex; ++i_enumIndex) { - if ( AT_SUCCESS != getEnumStringByIndex(Feature, i_enumIndex, wcs_enumString, i_maxStringLen) ) { + if ( AT_SUCCESS != getEnumStringByIndex(Feature, i_enumIndex, s_enumString) ) { DEB_ERROR() << "Failed to get Enum String" << " : error code = " << error_code(i_Err); return i_Err; } - if ( ! wcscmp(wcs_enumString, String) ) { + if ( s_enumString == Value) { break; } } if ( i_enumCount == i_enumIndex ) { - DEB_ERROR() << "Unable to find index of enum string '" << WStringToString(String) << "' in '" << WStringToString(Feature) << "' : no such choice."; + DEB_ERROR() << "Unable to find index of enum string '" << Value << "' in '" << WStringToString(Feature) << "' : no such choice."; *Index = -1; i_Err = AT_ERR_INDEXNOTAVAILABLE; } @@ -2522,17 +2505,24 @@ lima::Andor3::Camera::getEnumIndexByString(const AT_WC* Feature, AT_WC* String, } int -lima::Andor3::Camera::setString(const AT_WC* Feature, const AT_WC* String) +lima::Andor3::Camera::setString(const AT_WC* Feature, std::string Value) { DEB_MEMBER_FUNCT(); - return AT_SetString(m_camera_handle, Feature, String); + const std::wstring value_set = StringToWString(Value); + return AT_SetString(m_camera_handle, Feature, value_set.c_str()); } int -lima::Andor3::Camera::getString(const AT_WC* Feature, AT_WC* String, int StringLength) const +lima::Andor3::Camera::getString(const AT_WC* Feature, std::string &Value) const { DEB_MEMBER_FUNCT(); - return AT_GetString(m_camera_handle, Feature, String, StringLength); + AT_WC value_str[1024]; + int ierr = AT_GetString(m_camera_handle, Feature, value_str, 1023); + if (AT_SUCCESS != ierr) + return ierr; + + Value = WStringToString(value_str); + return ierr; } int -- GitLab From 85223d11c0e130b9aa8cb67b132334b038e1835f Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Thu, 24 Mar 2022 12:04:14 +0100 Subject: [PATCH 08/24] Change output signal methods to use string/bool instead of enums --- include/Andor3Camera.h | 16 ++++++------ sip/Andor3Camera.sip | 18 ++++++------- src/Andor3Camera.cpp | 57 ++++++++++++++++++++---------------------- tango/Andor3.py | 39 +++++++++++------------------ 4 files changed, 56 insertions(+), 74 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 31ed347..6e971d8 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -80,9 +80,6 @@ namespace lima // trigger / gate level enum A3_SignalLevel { Normal=0, Inverted=1}; - // output signal - enum A3_OutputSignal { FireRow1=0, FireRowN=1, FireAll=2, FireAny=3 }; - struct SdkFrameDim { AT_64 width; AT_64 height; @@ -162,13 +159,14 @@ namespace lima void getAdcGain(A3_Gain &oGain) const; void getAdcGainString(std::string &oGainString) const; - void setGateLevel(A3_SignalLevel iLevel); - void getGateLevel(A3_SignalLevel &iLevel); - void setTriggerLevel(A3_SignalLevel iLevel); - void getTriggerLevel(A3_SignalLevel &iLevel); + void setGateInverted(bool inverted); + void getGateInverted(bool& inverted); + void setTriggerInverted(bool inverted); + void getTriggerInverted(bool& inverted); - void setOutputSignal(A3_OutputSignal iSignal); - void getOutputSignal(A3_OutputSignal &oSignal) const; + void setOutputSignal(std::string signal); + void getOutputSignal(std::string &signal) const; + void getOutputSignalList(std::vector<std::string> &signal_list) const; void setAdcRate(A3_ReadOutRate iRate); // à exporter (avec le get) void getAdcRate(A3_ReadOutRate &oRate) const; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index 97d8b5a..c2aa10e 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -39,8 +39,6 @@ namespace Andor3 // enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; - enum A3_SignalLevel {Normal=0, Inverted=1}; - enum A3_OutputSignal {FireRow1=0, FireRowN=1, FireAll=2, FireAny=3}; Camera(const std::string& bitflow_path, int camera_number=0); ~Camera(); @@ -95,12 +93,14 @@ namespace Andor3 // -- andor3 specific, LIMA don't worry about it ! void initialiseController(); - void setGateLevel(A3_SignalLevel iLevel /In/ ); - void getGateLevel(A3_SignalLevel &iLevel /Out/ ); - void setTriggerLevel(A3_SignalLevel iLevel /In/ ); - void getTriggerLevel(A3_SignalLevel &iLevel /Out/ ); - void setOutputSignal(A3_OutputSignal iSignal /In/ ); - void getOutputSignal(A3_OutputSignal &oSignal /Out/ ) const; + void setGateInverted(bool inverted /In/ ); + void getGateInverted(bool &inverted /Out/ ); + void setTriggerInverted(bool inverted /In/ ); + void getTriggerInverted(bool &inverted /Out/ ); + + void setOutputSignal(std::string signal /In/ ); + void getOutputSignal(std::string &signal /Out/ ) const; + void getOutputSignalList(std::vector<std::string> &signal_list /Out/ ) const; void setAdcGain(A3_Gain iGain /In/ ); void getAdcGain(A3_Gain &oGain /Out/ ) const; @@ -115,8 +115,6 @@ namespace Andor3 void getBitDepth(A3_BitDepth &oMode /Out/ ) const; void getBitDepthString(std::string &oDepthString /Out/ ) const; void getPxEncodingString(std::string &oPxEncoding /Out/ ) const; -// void setTriggerMode(A3_TriggerMode iMode /In/ ); -// void getTriggerMode(A3_TriggerMode &oMode /Out/ ) const; void getTriggerModeString(std::string &oModeString /Out/ ) const; void setTemperatureSP(double temp /In/ ); void getTemperatureSP(double& temp /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 13096cc..47a37b7 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -1422,59 +1422,43 @@ lima::Andor3::Camera::getTriggerModeString(std::string &oModeString) const } void -lima::Andor3::Camera::setGateLevel(A3_SignalLevel iLevel) +lima::Andor3::Camera::setGateInverted(bool inverted) { DEB_MEMBER_FUNCT(); - bool flag; - if (iLevel == Inverted) flag= true; - else flag= false; setEnumString(andor3::IOSelector, "External Exposure"); - setBool(andor3::IOInvert, flag); + setBool(andor3::IOInvert, inverted); } void -lima::Andor3::Camera::getGateLevel(A3_SignalLevel &iLevel) +lima::Andor3::Camera::getGateInverted(bool& inverted) { DEB_MEMBER_FUNCT(); - bool flag; setEnumString(andor3::IOSelector, "External Exposure"); - getBool(andor3::IOInvert, &flag); - if (flag) - iLevel = Inverted; - else - iLevel = Normal; + getBool(andor3::IOInvert, &inverted); } void -lima::Andor3::Camera::setTriggerLevel(A3_SignalLevel iLevel) +lima::Andor3::Camera::setTriggerInverted(bool inverted) { DEB_MEMBER_FUNCT(); - bool flag; - if (iLevel == Inverted) flag= true; - else flag= false; setEnumString(andor3::IOSelector, "External Trigger"); - setBool(andor3::IOInvert, flag); + setBool(andor3::IOInvert, inverted); } void -lima::Andor3::Camera::getTriggerLevel(A3_SignalLevel &iLevel) +lima::Andor3::Camera::getTriggerInverted(bool& inverted) { DEB_MEMBER_FUNCT(); - bool flag; setEnumString(andor3::IOSelector, "External Trigger"); - getBool(andor3::IOInvert, &flag); - if (flag) - iLevel = Inverted; - else - iLevel = Normal; + getBool(andor3::IOInvert, &inverted); } void -lima::Andor3::Camera::setOutputSignal(A3_OutputSignal iSignal) +lima::Andor3::Camera::setOutputSignal(std::string iSignal) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::AuxiliaryOutSource) ) { - setEnumIndex(andor3::AuxiliaryOutSource, iSignal); + setEnumString(andor3::AuxiliaryOutSource, iSignal); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; @@ -1482,19 +1466,32 @@ lima::Andor3::Camera::setOutputSignal(A3_OutputSignal iSignal) } void -lima::Andor3::Camera::getOutputSignal(A3_OutputSignal &oSignal) const +lima::Andor3::Camera::getOutputSignal(std::string &oSignal) const { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::AuxiliaryOutSource) ) { - int value; - getEnumIndex(andor3::AuxiliaryOutSource, &value); - oSignal = static_cast<A3_OutputSignal>(value); + getEnumString(andor3::AuxiliaryOutSource, oSignal); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; + oSignal = "not implemented"; } } +void +lima::Andor3::Camera::getOutputSignalList(std::vector<std::string> &signal_list) const +{ + int enum_count; + std::string s_value; + + AT_GetEnumCount(m_camera_handle, andor3::AuxiliaryOutSource, &enum_count); + + for (int idx=0; enum_count != idx; ++idx) { + getEnumStringByIndex(andor3::AuxiliaryOutSource, idx, s_value); + signal_list.push_back(s_value); + } +} + //----------------------------------------------------- // @brief retrieve temperature capabilities //----------------------------------------------------- diff --git a/tango/Andor3.py b/tango/Andor3.py index 95b4ce5..6c3b3a7 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -88,26 +88,15 @@ class Andor3(PyTango.Device_4Impl): 'MHZ200': _Andor3Camera.MHz200, 'MHZ280': _Andor3Camera.MHz280, } - self.__Cooler = {'ON': True, - 'OFF': False} + self.__Cooler = {'ON': True, 'OFF': False} self.__ElectronicShutterMode = {'ROLLING': _Andor3Camera.Rolling, 'GLOBAL': _Andor3Camera.Global, } - self.__Overlap = {'ON': True, - 'OFF': False} - self.__SpuriousNoiseFilter = {'ON': True, - 'OFF': False} - self.__GateLevel = { 'NORMAL': _Andor3Camera.Normal, - 'INVERTED': _Andor3Camera.Inverted, - } - self.__TriggerLevel = { 'NORMAL': _Andor3Camera.Normal, - 'INVERTED': _Andor3Camera.Inverted, - } - self.__OutputSignal = { 'FIREROW1': _Andor3Camera.FireRow1, - 'FIREROWN': _Andor3Camera.FireRowN, - 'FIREALL': _Andor3Camera.FireAll, - 'FIREANY': _Andor3Camera.FireAny, - } + self.__Overlap = {'ON': True, 'OFF': False} + self.__SpuriousNoiseFilter = {'ON': True, 'OFF': False} + self.__GateInverted = { 'YES': True, 'NO': False } + self.__TriggerInverted = { 'YES': True, 'NO': False } + self.__OutputSignal = andor_list2dict(_Andor3Camera.getOutputSignalList()) self.__FanSpeed = andor_list2dict(_Andor3Camera.getFanSpeedList()) self.__Attribute2FunctionBase = {'adc_gain': 'SimpleGain', @@ -124,8 +113,8 @@ class Andor3(PyTango.Device_4Impl): 'overlap': 'Overlap', 'spurious_noise_filter': 'SpuriousNoiseFilter', 'serial_number': 'SerialNumber', - 'gate_level': 'GateLevel', - 'trigger_level': 'TriggerLevel', + 'gate_inverted': 'GateInverted', + 'trigger_inverted': 'TriggerInverted', 'output_signal': 'OutputSignal', } @@ -384,25 +373,25 @@ class Andor3Class(PyTango.DeviceClass): 'format': '', 'description': 'camera serial number', }], - 'trigger_level': + 'trigger_inverted': [[PyTango.DevString, PyTango.SCALAR, PyTango.READ_WRITE], { - 'label':'External trigger level', + 'label':'trigger signal inverted', 'unit': 'N/A', 'format': '', - 'description': 'NORMAl or INVERTED' + 'description': 'YES or NO' }], - 'gate_level': + 'gate_inverted': [[PyTango.DevString, PyTango.SCALAR, PyTango.READ_WRITE], { - 'label':'External gate level', + 'label':'gate signal inverted', 'unit': 'N/A', 'format': '', - 'description': 'NORMAl or INVERTED' + 'description': 'YES or NO' }], 'output_signal': [[PyTango.DevString, -- GitLab From 95ee37914423b20f70d15236edb8478dbdee3af7 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Thu, 24 Mar 2022 17:17:05 +0100 Subject: [PATCH 09/24] Rework SimpleGain to work with strings. Possible gain are camera-dependant and are read from the sdk --- include/Andor3Camera.h | 15 +++--- include/Andor3Interface.h | 6 +-- sip/Andor3Camera.sip | 9 ++-- sip/Andor3Interface.sip | 6 +-- src/Andor3Camera.cpp | 104 +++++++++++++++++++------------------- src/Andor3Interface.cpp | 8 +-- tango/Andor3.py | 5 +- 7 files changed, 76 insertions(+), 77 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 6e971d8..ce37d60 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -63,7 +63,10 @@ namespace lima // In the same order/index as "PreAmpGainControl" enum A3_Gain { Gain1 = 0, Gain2 = 1, Gain3 = 2, Gain4 = 3, Gain1_Gain3 = 4, Gain1_Gain4 = 5, Gain2_Gain3 = 6, Gain2_Gain4 = 7 }; // The "simple" version : - enum A3_SimpleGain { b11_hi_gain=0, b11_low_gain=1, b16_lh_gain=2, none=31}; + // enum A3_SimpleGain { b11_hi_gain=0, b11_low_gain=1, b16_lh_gain=2, none=31}; + + const std::vector<std::string> A3_SimpleGainString = {"b11_hi_gain", "b11_low_gain", "b16_lh_gain"}; + // In the same order/index as "ElectronicShutteringMode" enum A3_ShutterMode { Rolling = 0, Global = 1 }; // In the same order/index as "PixelReadoutRate" @@ -196,9 +199,11 @@ namespace lima void setOverlap(bool i_overlap); void getOverlap(bool &o_overlap) const; - void setSimpleGain(A3_SimpleGain i_gain); - void getSimpleGain(A3_SimpleGain &o_gain) const; - void getSimpleGainString(std::string &o_gainString) const; + + void setSimpleGain(std::string i_gain); + void getSimpleGain(std::string &o_gain) const; + void getSimpleGainList(std::vector<std::string> &gain_list) const; + void setSpuriousNoiseFilter(bool i_filter); void getSpuriousNoiseFilter(bool &o_filter) const; void setSyncTriggering(bool i_sync); @@ -306,7 +311,6 @@ namespace lima int m_camera_number; AT_H m_camera_handle; A3_Gain m_adc_gain; - A3_SimpleGain m_simple_gain; A3_ReadOutRate m_adc_rate; A3_ShutterMode m_electronic_shutter_mode; A3_BitDepth m_bit_depth; @@ -317,7 +321,6 @@ namespace lima std::vector<float> m_temperature_control_values; TrigMode m_trig_mode; - // A3_TriggerMode m_trig_mode; std::map<TrigMode, int> m_trig_mode_map; static int sAndorSDK3InittedCounter; diff --git a/include/Andor3Interface.h b/include/Andor3Interface.h index efa9cfe..047983c 100644 --- a/include/Andor3Interface.h +++ b/include/Andor3Interface.h @@ -71,9 +71,9 @@ namespace lima virtual void setAdcGain(Camera::A3_Gain iGain); virtual void getAdcGain(Camera::A3_Gain &oGain) const; virtual void getAdcGainString(std::string &oGainString) const; - virtual void setSimpleGain(Camera::A3_SimpleGain iGain); - virtual void getSimpleGain(Camera::A3_SimpleGain &oGain) const; - virtual void getSimpleGainString(std::string &oGainString) const; + virtual void setSimpleGain(std::string iGain); + virtual void getSimpleGain(std::string &oGain) const; + virtual void getSimpleGainList(std::vector<std::string> &gain_list) const; virtual void setAdcRate(Camera::A3_ReadOutRate iRate); virtual void getAdcRate(Camera::A3_ReadOutRate &oRate) const; virtual void getAdcRateString(std::string &oRateString) const; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index c2aa10e..af9e834 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -32,7 +32,6 @@ namespace Andor3 enum A3_TypeInfo { Unknown, Int, Float, Bool, Enum, String }; enum A3_Gain { Gain1 = 0, Gain2 = 1, Gain3 = 2, Gain4 = 3, Gain1_Gain3 = 4, Gain1_Gain4 = 5, Gain2_Gain3 = 6, Gain2_Gain4 = 7 }; - enum A3_SimpleGain { b11_hi_gain=0, b11_low_gain=1, b16_lh_gain=2, none=31}; enum A3_ShutterMode { Rolling = 0, Global = 1 }; enum A3_ReadOutRate { MHz10 = 0, MHz100 = 1, MHz200 = 2, MHz280 = 3 }; enum A3_BitDepth { b11 = 0, b16= 1 }; @@ -132,9 +131,11 @@ namespace Andor3 void setOverlap(bool i_overlap /In/ ); void getOverlap(bool &o_overlap /Out/ ) const; - void setSimpleGain(A3_SimpleGain i_gain /In/ ); - void getSimpleGain(A3_SimpleGain &o_gain /Out/ ) const; - void getSimpleGainString(std::string &o_gainString /Out/ ) const; + + void setSimpleGain(std::string i_gain /In/ ); + void getSimpleGain(std::string &o_gain /Out/ ) const; + void getSimpleGainList(std::vector<std::string> &gain_list /Out/ ) const; + void setSpuriousNoiseFilter(bool i_filter /In/ ); void getSpuriousNoiseFilter(bool &o_filter /Out/ ) const; void setSyncTriggering(bool i_sync /In/ ); diff --git a/sip/Andor3Interface.sip b/sip/Andor3Interface.sip index a0e57f7..270616b 100644 --- a/sip/Andor3Interface.sip +++ b/sip/Andor3Interface.sip @@ -50,9 +50,9 @@ namespace Andor3 virtual void setAdcGain(Andor3::Camera::A3_Gain iGain /In/ ); virtual void getAdcGain(Andor3::Camera::A3_Gain &oGain /Out/ ) const; virtual void getAdcGainString(std::string &oGainString /Out/ ) const; - virtual void setSimpleGain(Andor3::Camera::A3_SimpleGain iGain /In/ ); - virtual void getSimpleGain(Andor3::Camera::A3_SimpleGain &oGain /Out/ ) const; - virtual void getSimpleGainString(std::string &oGainString /Out/ ) const; + virtual void setSimpleGain(std::string iGain /In/ ); + virtual void getSimpleGain(std::string &oGain /Out/ ) const; + virtual void getSimpleGainList(std::vector<std::string> &gain_list /Out/ ) const; virtual void setAdcRate(Andor3::Camera::A3_ReadOutRate iRate /In/ ); virtual void getAdcRate(Andor3::Camera::A3_ReadOutRate &oRate /Out/ ) const; virtual void getAdcRateString(std::string &oRateString /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 47a37b7..8e2a887 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -168,7 +168,6 @@ m_bitflow_path(bitflow_path), m_camera_number(camera_number), m_camera_handle(AT_HANDLE_UNINITIALISED), m_adc_gain(Gain1_Gain4), -m_simple_gain(b16_lh_gain), m_adc_rate(MHz100), m_electronic_shutter_mode(Rolling), m_bit_depth(b16), @@ -1182,13 +1181,12 @@ lima::Andor3::Camera::initialiseController() { DEB_MEMBER_FUNCT(); A3_BitDepth the_bd = m_bit_depth; - A3_SimpleGain the_simple_gain = m_simple_gain; A3_ReadOutRate the_rate = m_adc_rate; // Carefully crafting the order, since some are affecting others... setElectronicShutterMode(m_electronic_shutter_mode); setTrigMode(m_trig_mode); - setSimpleGain(the_simple_gain); + //setSimpleGain(the_simple_gain); setAdcRate(the_rate); setBitDepth(the_bd); setCooler(m_cooler); @@ -1330,11 +1328,12 @@ lima::Andor3::Camera::setElectronicShutterMode(A3_ShutterMode iMode) << "\n\twhile requesting " << iMode; } // Setting the trigger mode might change the ADCGain and ADCRate : - int the_gain, the_rate; - - getEnumIndex(andor3::SimplePreAmpGainControl, &the_gain); + int the_rate; + std::string the_gain; + + getSimpleGain(the_gain); getEnumIndex(andor3::PixelReadoutRate, &the_rate); - setSimpleGain(static_cast<A3_SimpleGain>(the_gain)); + setSimpleGain(the_gain); setAdcRate(static_cast<A3_ReadOutRate>(the_rate)); } @@ -1715,50 +1714,42 @@ lima::Andor3::Camera::getOverlap(bool &o_overlap) const } void -lima::Andor3::Camera::setSimpleGain(A3_SimpleGain i_gain) +lima::Andor3::Camera::setSimpleGain(std::string i_gain) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::SimplePreAmpGainControl) ) { - int the_err_code = setEnumIndex(andor3::SimplePreAmpGainControl, i_gain); - if ( AT_SUCCESS != the_err_code ) { - DEB_ERROR() << "Cannot set SimplePreAmpGainControl to " << i_gain - << " - " << DEB_VAR1(error_code(the_err_code)); - } + THROW_IF_NOT_SUCCESS(setEnumString(andor3::SimplePreAmpGainControl, i_gain), \ + "failed to set simple gain"); } else { DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; A3_ShutterMode the_shutter; getElectronicShutterMode(the_shutter); - - switch (i_gain) { - case b11_low_gain: - setAdcGain(Gain1); - break; - - case b11_hi_gain: - if ( Rolling == the_shutter ) - setAdcGain(Gain4); - else - setAdcGain(Gain3); - break; - - case b16_lh_gain: - if ( Rolling == the_shutter ) - setAdcGain(Gain1_Gain4); - else - setAdcGain(Gain1_Gain3); - break; - - default: - DEB_TRACE() << "Not performing any settings since you provided an unavailable value"; - break; + + if (i_gain == "b11_low_gain") { + setAdcGain(Gain1); + } + else if (i_gain == "b11_hi_gain") { + if ( Rolling == the_shutter ) + setAdcGain(Gain4); + else + setAdcGain(Gain3); + } + else if (i_gain == "b16_lh_gain") { + if ( Rolling == the_shutter ) + setAdcGain(Gain1_Gain4); + else + setAdcGain(Gain1_Gain3); + } + else { + THROW_HW_ERROR(Error)<<"Invalid emulated simple gain"; } } } void -lima::Andor3::Camera::getSimpleGain(A3_SimpleGain &o_gain) const +lima::Andor3::Camera::getSimpleGain(std::string &o_gain) const { DEB_MEMBER_FUNCT(); @@ -1771,14 +1762,12 @@ lima::Andor3::Camera::getSimpleGain(A3_SimpleGain &o_gain) const // (6) "Gain 2 Gain 3 (16 bit)"; implemented = true; available = true. // (7) "Gain 2 Gain 4 (16 bit)"; implemented = true; available = true. if ( propImplemented(andor3::SimplePreAmpGainControl) ) { - int the_gain; - getEnumIndex(andor3::SimplePreAmpGainControl, &the_gain); - o_gain = static_cast<A3_SimpleGain>(the_gain); + getEnumString(andor3::SimplePreAmpGainControl, o_gain); } else { DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; - A3_Gain the_gain; + A3_Gain the_gain; A3_ShutterMode the_shutter; getAdcGain(the_gain); @@ -1787,34 +1776,34 @@ lima::Andor3::Camera::getSimpleGain(A3_SimpleGain &o_gain) const if ( Rolling == the_shutter ) { switch (the_gain) { case Gain1: - o_gain = b11_low_gain; + o_gain = "b11_low_gain"; break; case Gain4: - o_gain = b11_hi_gain; + o_gain = "b11_hi_gain"; break; case Gain1_Gain4: - o_gain = b16_lh_gain; + o_gain = "b16_lh_gain"; break; default: - o_gain = none; + o_gain = "none"; break; } } else { switch (the_gain) { case Gain1: - o_gain = b11_low_gain; + o_gain = "b11_low_gain"; break; case Gain3: - o_gain = b11_hi_gain; + o_gain = "b11_hi_gain"; break; case Gain1_Gain3: - o_gain = b16_lh_gain; + o_gain = "b16_lh_gain"; break; default: - o_gain = none; + o_gain = "none"; break; } } @@ -1823,15 +1812,24 @@ lima::Andor3::Camera::getSimpleGain(A3_SimpleGain &o_gain) const void -lima::Andor3::Camera::getSimpleGainString(std::string &o_gainString) const +lima::Andor3::Camera::getSimpleGainList(std::vector<std::string> &gain_list) const { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::SimplePreAmpGainControl) ) { - getEnumString(andor3::SimplePreAmpGainControl, o_gainString); + int enum_count; + std::string s_value; + AT_GetEnumCount(m_camera_handle, andor3::SimplePreAmpGainControl, &enum_count); + + for (int idx=0; enum_count != idx; ++idx) { + getEnumStringByIndex(andor3::SimplePreAmpGainControl, idx, s_value); + gain_list.push_back(s_value); + } } else { - DEB_TRACE() << "The camera has no simple gain control setting... Do nothing !"; - o_gainString = "not implemented"; + DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; + gain_list.push_back("b11_low_gain"); + gain_list.push_back("b11_hi_gain"); + gain_list.push_back("b16_lh_gain"); } } diff --git a/src/Andor3Interface.cpp b/src/Andor3Interface.cpp index 15dc541..59b6d1c 100644 --- a/src/Andor3Interface.cpp +++ b/src/Andor3Interface.cpp @@ -190,7 +190,7 @@ lima::Andor3::Interface::getAdcGainString(std::string &oGainString) const } void -lima::Andor3::Interface::setSimpleGain(Camera::A3_SimpleGain iGain) +lima::Andor3::Interface::setSimpleGain(std::string iGain) { DEB_MEMBER_FUNCT(); m_cam.setSimpleGain(iGain); @@ -198,17 +198,17 @@ lima::Andor3::Interface::setSimpleGain(Camera::A3_SimpleGain iGain) } void -lima::Andor3::Interface::getSimpleGain(Camera::A3_SimpleGain &oGain) const +lima::Andor3::Interface::getSimpleGain(std::string &oGain) const { DEB_MEMBER_FUNCT(); m_cam.getSimpleGain(oGain); } void -lima::Andor3::Interface::getSimpleGainString(std::string &oGainString) const +lima::Andor3::Interface::getSimpleGainList(std::vector<std::string> &gain_list) const { DEB_MEMBER_FUNCT(); - m_cam.getSimpleGainString(oGainString); + m_cam.getSimpleGainList(gain_list); } diff --git a/tango/Andor3.py b/tango/Andor3.py index 6c3b3a7..f1b7c98 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -79,10 +79,7 @@ class Andor3(PyTango.Device_4Impl): def __init__(self,cl, name): PyTango.Device_4Impl.__init__(self,cl,name) # dictionnaries to be used with AttrHelper.get_attr_4u - self.__AdcGain = {'B11_HI_GAIN': _Andor3Camera.b11_hi_gain, - 'B11_LOW_GAIN': _Andor3Camera.b11_low_gain, - 'B16_LH_GAIN': _Andor3Camera.b16_lh_gain, - } + self.__AdcGain = andor_list2dict(_Andor3Camera.getSimpleGainList()) self.__AdcRate = {'MHZ10': _Andor3Camera.MHz10, 'MHZ100': _Andor3Camera.MHz100, 'MHZ200': _Andor3Camera.MHz200, -- GitLab From 7051bb1a4285c3059a090f75cafa701926f1075d Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 30 Mar 2022 09:33:26 +0200 Subject: [PATCH 10/24] add make to conda recipe --- conda/camera/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conda/camera/meta.yaml b/conda/camera/meta.yaml index 826785f..c8f6329 100644 --- a/conda/camera/meta.yaml +++ b/conda/camera/meta.yaml @@ -23,7 +23,7 @@ requirements: - lima-core - andor3-sdk build: - - git + - make - cmake - {{ compiler('cxx') }} run: -- GitLab From 232b4a52f4728ffe34115079d70c6826716db913 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 30 Mar 2022 09:34:34 +0200 Subject: [PATCH 11/24] add make to conda tango recipe --- conda/tango/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conda/tango/meta.yaml b/conda/tango/meta.yaml index 081eb89..c35b1c3 100644 --- a/conda/tango/meta.yaml +++ b/conda/tango/meta.yaml @@ -19,7 +19,7 @@ build: requirements: build: - cmake - - git + - make - lima-core run: - lima-tango-server -- GitLab From 76c973566fa19c1e045a0244014152d2be6a3c51 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 30 Mar 2022 09:53:12 +0200 Subject: [PATCH 12/24] conda build on python 3.7 oonly --- conda/camera/conda_build_config.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/conda/camera/conda_build_config.yaml b/conda/camera/conda_build_config.yaml index 37b36eb..2479ceb 100644 --- a/conda/camera/conda_build_config.yaml +++ b/conda/camera/conda_build_config.yaml @@ -5,8 +5,6 @@ c_compiler: cxx_compiler: - vs2017 # [win] python: - - 2.7 # [linux] - - 3.6 - 3.7 # This differs from target_platform in that it determines what subdir the compiler # will target, not what subdir the compiler package will be itself. -- GitLab From bcb95ee47a35d9ca676fdae808b60c0d8fe1d2ce Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 30 Mar 2022 09:57:49 +0200 Subject: [PATCH 13/24] convert pixel size in meters --- include/Andor3Camera.h | 2 -- src/Andor3Camera.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index ce37d60..e89981e 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -62,8 +62,6 @@ namespace lima //! @TODO : later on should do a map (string to int and vice-versa) from parsed enum info for the next 3 : // In the same order/index as "PreAmpGainControl" enum A3_Gain { Gain1 = 0, Gain2 = 1, Gain3 = 2, Gain4 = 3, Gain1_Gain3 = 4, Gain1_Gain4 = 5, Gain2_Gain3 = 6, Gain2_Gain4 = 7 }; - // The "simple" version : - // enum A3_SimpleGain { b11_hi_gain=0, b11_low_gain=1, b16_lh_gain=2, none=31}; const std::vector<std::string> A3_SimpleGainString = {"b11_hi_gain", "b11_low_gain", "b16_lh_gain"}; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 8e2a887..95abf5e 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -1142,6 +1142,8 @@ lima::Andor3::Camera::getPixelSize(double& sizex, double& sizey) DEB_MEMBER_FUNCT(); getFloat(andor3::PixelWidth, &sizex); getFloat(andor3::PixelHeight, &sizey); + sizex *= 1e-6; + sizey *= 1e-6; } void -- GitLab From 40840ee769c1d34abb407551bd6a008f04b28f17 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Wed, 30 Mar 2022 10:03:03 +0200 Subject: [PATCH 14/24] remove numpy from conda meta pin andor3-sdk version to 3.14 (3.15 does not work on USB3 cameras) --- conda/camera/meta.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/conda/camera/meta.yaml b/conda/camera/meta.yaml index c8f6329..7d82904 100644 --- a/conda/camera/meta.yaml +++ b/conda/camera/meta.yaml @@ -18,19 +18,18 @@ build: requirements: host: - python {{ python }} - - numpy - sip 4.19.8 # For compatibility with pyqt 5.9.2 - lima-core - - andor3-sdk + - andor3-sdk 3.14 build: - - make - cmake + - make - {{ compiler('cxx') }} run: - python {{ python }} - sip >=4.19.4, <=4.19.8 # For compatibility with pyqt 5.9.2 - {{ pin_compatible('lima-core', max_pin='x.x') }} - - andor3-sdk + - andor3-sdk 3.14 test: requires: -- GitLab From da149dd402f8283ec3bf2204df3b3c94b2783d42 Mon Sep 17 00:00:00 2001 From: Laurent Claustre <claustre@esrf.fr> Date: Wed, 30 Mar 2022 11:19:14 +0200 Subject: [PATCH 15/24] add conda-forge as first channel otherwise conda get lz4-c from bcu-ci an mpi version made by Sam --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8a1c81..39a044c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ stages: build-linux: <<: *build-conda script: - - conda build ./conda/camera --prefix-length=80 --output-folder=dist/ --channel=http://bcu-ci.esrf.fr/stable + - conda build ./conda/camera --prefix-length=80 --output-folder=dist/ -c conda-forge --channel=http://bcu-ci.esrf.fr/stable tags: - linux -- GitLab From e286e943865f16c4d598ae0e6ffa9167df01afb8 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 1 Apr 2022 15:13:21 +0200 Subject: [PATCH 16/24] Convert adc rate fixed enum to strings --- include/Andor3Camera.h | 25 ++++++++++--------- include/Andor3Interface.h | 6 ++--- sip/Andor3Camera.sip | 11 ++++++--- sip/Andor3Interface.sip | 6 ++--- src/Andor3Camera.cpp | 51 ++++++++++++++------------------------- src/Andor3Interface.cpp | 8 +++--- tango/Andor3.py | 6 +---- 7 files changed, 49 insertions(+), 64 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index e89981e..7b771b7 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -61,26 +61,27 @@ namespace lima //! @TODO : later on should do a map (string to int and vice-versa) from parsed enum info for the next 3 : // In the same order/index as "PreAmpGainControl" - enum A3_Gain { Gain1 = 0, Gain2 = 1, Gain3 = 2, Gain4 = 3, Gain1_Gain3 = 4, Gain1_Gain4 = 5, Gain2_Gain3 = 6, Gain2_Gain4 = 7 }; + enum A3_Gain { Gain1 = 0, + Gain2 = 1, + Gain3 = 2, + Gain4 = 3, + Gain1_Gain3 = 4, + Gain1_Gain4 = 5, + Gain2_Gain3 = 6, + Gain2_Gain4 = 7, + }; const std::vector<std::string> A3_SimpleGainString = {"b11_hi_gain", "b11_low_gain", "b16_lh_gain"}; // In the same order/index as "ElectronicShutteringMode" enum A3_ShutterMode { Rolling = 0, Global = 1 }; - // In the same order/index as "PixelReadoutRate" - enum A3_ReadOutRate { MHz10 = 0, MHz100 = 1, MHz200 = 2, MHz280 = 3 }; // In the same order/index as 'BitDepth' enum A3_BitDepth { b11 = 0, b16= 1 }; - // Gain Mode for Marana detector - enum A3_GainMode { FastFrameRate=0, HighDynamicRange=1 }; // The binning system of andor3 : enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; - // trigger / gate level - enum A3_SignalLevel { Normal=0, Inverted=1}; - struct SdkFrameDim { AT_64 width; AT_64 height; @@ -169,9 +170,10 @@ namespace lima void getOutputSignal(std::string &signal) const; void getOutputSignalList(std::vector<std::string> &signal_list) const; - void setAdcRate(A3_ReadOutRate iRate); // à exporter (avec le get) - void getAdcRate(A3_ReadOutRate &oRate) const; - void getAdcRateString(std::string &oRateString) const; + void setAdcRate(std::string adc_rate); + void getAdcRate(std::string &adc_rate) const; + void getAdcRateList(std::vector<std::string> &adc_rate_list) const; + void setElectronicShutterMode(A3_ShutterMode iMode); // à exporter (avec le get) void getElectronicShutterMode(A3_ShutterMode &oMode) const; void getElectronicShutterModeString(std::string &oModeString) const; @@ -309,7 +311,6 @@ namespace lima int m_camera_number; AT_H m_camera_handle; A3_Gain m_adc_gain; - A3_ReadOutRate m_adc_rate; A3_ShutterMode m_electronic_shutter_mode; A3_BitDepth m_bit_depth; bool m_cooler; diff --git a/include/Andor3Interface.h b/include/Andor3Interface.h index 047983c..c4624f0 100644 --- a/include/Andor3Interface.h +++ b/include/Andor3Interface.h @@ -74,9 +74,9 @@ namespace lima virtual void setSimpleGain(std::string iGain); virtual void getSimpleGain(std::string &oGain) const; virtual void getSimpleGainList(std::vector<std::string> &gain_list) const; - virtual void setAdcRate(Camera::A3_ReadOutRate iRate); - virtual void getAdcRate(Camera::A3_ReadOutRate &oRate) const; - virtual void getAdcRateString(std::string &oRateString) const; + virtual void setAdcRate(std::string iRate); + virtual void getAdcRate(std::string &oRate) const; + virtual void getAdcRateList(std::vector<std::string> &oRateList) const; virtual void setElectronicShutterMode(Camera::A3_ShutterMode iMode); virtual void getElectronicShutterMode(Camera::A3_ShutterMode &oMode) const; virtual void getElectronicShutterModeString(std::string &oModeString) const; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index af9e834..4117dea 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -33,7 +33,6 @@ namespace Andor3 enum A3_Gain { Gain1 = 0, Gain2 = 1, Gain3 = 2, Gain4 = 3, Gain1_Gain3 = 4, Gain1_Gain4 = 5, Gain2_Gain3 = 6, Gain2_Gain4 = 7 }; enum A3_ShutterMode { Rolling = 0, Global = 1 }; - enum A3_ReadOutRate { MHz10 = 0, MHz100 = 1, MHz200 = 2, MHz280 = 3 }; enum A3_BitDepth { b11 = 0, b16= 1 }; // enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; @@ -104,17 +103,21 @@ namespace Andor3 void setAdcGain(A3_Gain iGain /In/ ); void getAdcGain(A3_Gain &oGain /Out/ ) const; void getAdcGainString(std::string &oGainString /Out/ ) const; - void setAdcRate(A3_ReadOutRate iRate /In/ ); - void getAdcRate(A3_ReadOutRate &oRate /Out/ ) const; - void getAdcRateString(std::string &oRateString /Out/ ) const; + + void setAdcRate(std::string adc_rate /In/ ); + void getAdcRate(std::string &adc_rate /Out/ ) const; + void getAdcRateList(std::vector<std::string> &adc_rate_list /Out/ ) const; + void setElectronicShutterMode(A3_ShutterMode iMode /In/ ); void getElectronicShutterMode(A3_ShutterMode &oMode /Out/ ) const; void getElectronicShutterModeString(std::string &oModeString /Out/) const; + void setBitDepth(A3_BitDepth iMode /In/ ); void getBitDepth(A3_BitDepth &oMode /Out/ ) const; void getBitDepthString(std::string &oDepthString /Out/ ) const; void getPxEncodingString(std::string &oPxEncoding /Out/ ) const; void getTriggerModeString(std::string &oModeString /Out/ ) const; + void setTemperatureSP(double temp /In/ ); void getTemperatureSP(double& temp /Out/ ) const; void getTemperature(double& temp /Out/ ) const; diff --git a/sip/Andor3Interface.sip b/sip/Andor3Interface.sip index 270616b..194cd4e 100644 --- a/sip/Andor3Interface.sip +++ b/sip/Andor3Interface.sip @@ -53,9 +53,9 @@ namespace Andor3 virtual void setSimpleGain(std::string iGain /In/ ); virtual void getSimpleGain(std::string &oGain /Out/ ) const; virtual void getSimpleGainList(std::vector<std::string> &gain_list /Out/ ) const; - virtual void setAdcRate(Andor3::Camera::A3_ReadOutRate iRate /In/ ); - virtual void getAdcRate(Andor3::Camera::A3_ReadOutRate &oRate /Out/ ) const; - virtual void getAdcRateString(std::string &oRateString /Out/ ) const; + virtual void setAdcRate(std::string iRate /In/ ); + virtual void getAdcRate(std::string &oRate /Out/ ) const; + virtual void getAdcRateList(std::vector<std::string> &oRateList /Out/ ) const; virtual void setElectronicShutterMode(Andor3::Camera::A3_ShutterMode iMode /In/ ); virtual void getElectronicShutterMode(Andor3::Camera::A3_ShutterMode &oMode /Out/ ) const; virtual void getElectronicShutterModeString(std::string &oModeString /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 95abf5e..3a3a7b9 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -168,7 +168,6 @@ m_bitflow_path(bitflow_path), m_camera_number(camera_number), m_camera_handle(AT_HANDLE_UNINITIALISED), m_adc_gain(Gain1_Gain4), -m_adc_rate(MHz100), m_electronic_shutter_mode(Rolling), m_bit_depth(b16), m_trig_mode(IntTrig), @@ -1183,13 +1182,10 @@ lima::Andor3::Camera::initialiseController() { DEB_MEMBER_FUNCT(); A3_BitDepth the_bd = m_bit_depth; - A3_ReadOutRate the_rate = m_adc_rate; // Carefully crafting the order, since some are affecting others... setElectronicShutterMode(m_electronic_shutter_mode); setTrigMode(m_trig_mode); - //setSimpleGain(the_simple_gain); - setAdcRate(the_rate); setBitDepth(the_bd); setCooler(m_cooler); initTemperature(); @@ -1277,43 +1273,32 @@ lima::Andor3::Camera::getAdcGainString(std::string &oGainString) const void -lima::Andor3::Camera::setAdcRate(A3_ReadOutRate iRate) +lima::Andor3::Camera::setAdcRate(std::string adc_rate) { DEB_MEMBER_FUNCT(); - if ( m_real_camera ) { - int the_rate; - setEnumIndex(andor3::PixelReadoutRate, iRate); - getEnumIndex(andor3::PixelReadoutRate, &the_rate); - m_adc_rate = static_cast<A3_ReadOutRate>(the_rate); - if ( m_adc_rate != iRate ) { - DEB_ERROR() << "Proof-reading the ADC readout rate :" - << "\n\tGot " << m_adc_rate << " back," - << "\n\twhile requesting " << iRate; - } - } - else { - int the_rate; - setEnumIndex(andor3::PixelReadoutRate, 0); - getEnumIndex(andor3::PixelReadoutRate, &the_rate); - m_adc_rate = static_cast<A3_ReadOutRate>(the_rate); - DEB_TRACE() << "The SIMCAM has only one rate setting (550MHz), making sure that's what we are doing now"; - } + THROW_IF_NOT_SUCCESS(setEnumString(andor3::PixelReadoutRate, adc_rate), + "Failed to set ADC Pixel Rate") } void -lima::Andor3::Camera::getAdcRate(A3_ReadOutRate &oRate) const +lima::Andor3::Camera::getAdcRate(std::string &adc_rate) const { DEB_MEMBER_FUNCT(); -// int the_rate; -// getEnumIndex(andor3::PixelReadoutRate, &the_rate); -// oRate = static_cast<A3_ReadOutRate>(the_rate); - oRate = m_adc_rate; + getEnumString(andor3::PixelReadoutRate, adc_rate); } void -lima::Andor3::Camera::getAdcRateString(std::string &oRateString) const +lima::Andor3::Camera::getAdcRateList(std::vector<std::string> &adc_rate_list) const { - getEnumString(andor3::PixelReadoutRate, oRateString); + int enum_count; + AT_WC s_value[1024]; + + AT_GetEnumCount(m_camera_handle, andor3::PixelReadoutRate, &enum_count); + + for (int idx=0; enum_count != idx; ++idx) { + AT_GetEnumStringByIndex(m_camera_handle, andor3::PixelReadoutRate, idx, s_value, 1024); + adc_rate_list.push_back(WStringToString(s_value)); + } } void @@ -1330,13 +1315,13 @@ lima::Andor3::Camera::setElectronicShutterMode(A3_ShutterMode iMode) << "\n\twhile requesting " << iMode; } // Setting the trigger mode might change the ADCGain and ADCRate : - int the_rate; + std::string the_rate; std::string the_gain; getSimpleGain(the_gain); - getEnumIndex(andor3::PixelReadoutRate, &the_rate); + getAdcRate(the_rate); setSimpleGain(the_gain); - setAdcRate(static_cast<A3_ReadOutRate>(the_rate)); + setAdcRate(the_rate); } void diff --git a/src/Andor3Interface.cpp b/src/Andor3Interface.cpp index 59b6d1c..98e6274 100644 --- a/src/Andor3Interface.cpp +++ b/src/Andor3Interface.cpp @@ -214,7 +214,7 @@ lima::Andor3::Interface::getSimpleGainList(std::vector<std::string> &gain_list) void -lima::Andor3::Interface::setAdcRate(Camera::A3_ReadOutRate iRate) +lima::Andor3::Interface::setAdcRate(std::string iRate) { DEB_MEMBER_FUNCT(); m_cam.setAdcRate(iRate); @@ -222,17 +222,17 @@ lima::Andor3::Interface::setAdcRate(Camera::A3_ReadOutRate iRate) } void -lima::Andor3::Interface::getAdcRate(Camera::A3_ReadOutRate &oRate) const +lima::Andor3::Interface::getAdcRate(std::string &oRate) const { DEB_MEMBER_FUNCT(); m_cam.getAdcRate(oRate); } void -lima::Andor3::Interface::getAdcRateString(std::string &oRateString) const +lima::Andor3::Interface::getAdcRateList(std::vector<std::string> &oRateList) const { DEB_MEMBER_FUNCT(); - m_cam.getAdcRateString(oRateString); + m_cam.getAdcRateList(oRateList); } void diff --git a/tango/Andor3.py b/tango/Andor3.py index f1b7c98..4eb4ba8 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -80,11 +80,7 @@ class Andor3(PyTango.Device_4Impl): PyTango.Device_4Impl.__init__(self,cl,name) # dictionnaries to be used with AttrHelper.get_attr_4u self.__AdcGain = andor_list2dict(_Andor3Camera.getSimpleGainList()) - self.__AdcRate = {'MHZ10': _Andor3Camera.MHz10, - 'MHZ100': _Andor3Camera.MHz100, - 'MHZ200': _Andor3Camera.MHz200, - 'MHZ280': _Andor3Camera.MHz280, - } + self.__AdcRate = andor_list2dict(_Andor3Camera.getAdcRateList()) self.__Cooler = {'ON': True, 'OFF': False} self.__ElectronicShutterMode = {'ROLLING': _Andor3Camera.Rolling, 'GLOBAL': _Andor3Camera.Global, -- GitLab From 31cecb739b73079cfb8a272a7e1dc9732aa62e70 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 1 Apr 2022 15:35:12 +0200 Subject: [PATCH 17/24] throw error if setting fan_speed/output_signal fails --- src/Andor3Camera.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 3a3a7b9..1e71356 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -1444,7 +1444,8 @@ lima::Andor3::Camera::setOutputSignal(std::string iSignal) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::AuxiliaryOutSource) ) { - setEnumString(andor3::AuxiliaryOutSource, iSignal); + THROW_IF_NOT_SUCCESS(setEnumString(andor3::AuxiliaryOutSource, iSignal), + "Failed to set output signal"); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; @@ -1660,7 +1661,8 @@ lima::Andor3::Camera::setFanSpeed(std::string fan_speed) { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::FanSpeed) ) { - setEnumString(andor3::FanSpeed, fan_speed); + THROW_IF_NOT_SUCCESS(setEnumString(andor3::FanSpeed, fan_speed), + "Failed to set fan speed"); } else { DEB_TRACE() << "The camera has no fan speed setting... Do nothing !"; -- GitLab From f153b0130f950596867143a4603f5f707abf4567 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 1 Apr 2022 16:22:22 +0200 Subject: [PATCH 18/24] Convert electronic shutter mode to string list intead of enum. Some cameras have only Rolling while others also have Global --- include/Andor3Camera.h | 21 ++++++++--------- include/Andor3Interface.h | 6 ++--- sip/Andor3Camera.sip | 8 +++---- sip/Andor3Interface.sip | 6 ++--- src/Andor3Camera.cpp | 47 +++++++++++++++++++++------------------ src/Andor3Interface.cpp | 8 +++---- tango/Andor3.py | 10 ++++----- 7 files changed, 53 insertions(+), 53 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 7b771b7..2d6c1bf 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -73,8 +73,9 @@ namespace lima const std::vector<std::string> A3_SimpleGainString = {"b11_hi_gain", "b11_low_gain", "b16_lh_gain"}; - // In the same order/index as "ElectronicShutteringMode" - enum A3_ShutterMode { Rolling = 0, Global = 1 }; + // Rolling Shutter mode + const std::string RollingShutterMode = "Rolling"; + // In the same order/index as 'BitDepth' enum A3_BitDepth { b11 = 0, b16= 1 }; @@ -174,21 +175,22 @@ namespace lima void getAdcRate(std::string &adc_rate) const; void getAdcRateList(std::vector<std::string> &adc_rate_list) const; - void setElectronicShutterMode(A3_ShutterMode iMode); // à exporter (avec le get) - void getElectronicShutterMode(A3_ShutterMode &oMode) const; - void getElectronicShutterModeString(std::string &oModeString) const; + void setElectronicShutterMode(std::string shut_mode); + void getElectronicShutterMode(std::string &shut_mode) const; + void getElectronicShutterModeList(std::vector<std::string> &shut_mode_list) const; + void setBitDepth(A3_BitDepth iMode); void getBitDepth(A3_BitDepth &oMode) const; void getBitDepthString(std::string &oDepthString) const; void getPxEncoding(A3_PixelEncoding &oPxEncoding) const; void getPxEncodingString(std::string &oPxEncoding) const; void getTriggerModeString(std::string &oModeString) const; - void setTemperatureSP(double temp); // à exporter (avec le get) + void setTemperatureSP(double temp); void getTemperatureSP(double& temp) const; - void getTemperature(double& temp) const; // à exporter (read-only) - void setCooler(bool flag); // à exporter (avec le get) + void getTemperature(double& temp) const; + void setCooler(bool flag); void getCooler(bool& flag) const; - void getCoolingStatus(std::string& status) const; // à exporter (read-only) + void getCoolingStatus(std::string& status) const; void setBufferOverflow(bool i_overflow); void getBufferOverflow(bool &o_overflow) const; @@ -311,7 +313,6 @@ namespace lima int m_camera_number; AT_H m_camera_handle; A3_Gain m_adc_gain; - A3_ShutterMode m_electronic_shutter_mode; A3_BitDepth m_bit_depth; bool m_cooler; double m_temperature_sp; diff --git a/include/Andor3Interface.h b/include/Andor3Interface.h index c4624f0..0a1be8f 100644 --- a/include/Andor3Interface.h +++ b/include/Andor3Interface.h @@ -77,9 +77,9 @@ namespace lima virtual void setAdcRate(std::string iRate); virtual void getAdcRate(std::string &oRate) const; virtual void getAdcRateList(std::vector<std::string> &oRateList) const; - virtual void setElectronicShutterMode(Camera::A3_ShutterMode iMode); - virtual void getElectronicShutterMode(Camera::A3_ShutterMode &oMode) const; - virtual void getElectronicShutterModeString(std::string &oModeString) const; + virtual void setElectronicShutterMode(std::string iMode); + virtual void getElectronicShutterMode(std::string &oMode) const; + virtual void getElectronicShutterModeList(std::vector<std::string> &oModeList) const; virtual void setOverlap(bool i_overlap); virtual void getOverlap(bool &o_overlap) const; diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index 4117dea..7520178 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -32,9 +32,7 @@ namespace Andor3 enum A3_TypeInfo { Unknown, Int, Float, Bool, Enum, String }; enum A3_Gain { Gain1 = 0, Gain2 = 1, Gain3 = 2, Gain4 = 3, Gain1_Gain3 = 4, Gain1_Gain4 = 5, Gain2_Gain3 = 6, Gain2_Gain4 = 7 }; - enum A3_ShutterMode { Rolling = 0, Global = 1 }; enum A3_BitDepth { b11 = 0, b16= 1 }; -// enum A3_TriggerMode { Internal = 0, ExternalLevelTransition = 1, ExternalStart = 2, ExternalExposure = 3, Software = 4, Advanced = 5, External = 6 }; enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; @@ -108,9 +106,9 @@ namespace Andor3 void getAdcRate(std::string &adc_rate /Out/ ) const; void getAdcRateList(std::vector<std::string> &adc_rate_list /Out/ ) const; - void setElectronicShutterMode(A3_ShutterMode iMode /In/ ); - void getElectronicShutterMode(A3_ShutterMode &oMode /Out/ ) const; - void getElectronicShutterModeString(std::string &oModeString /Out/) const; + void setElectronicShutterMode(std::string iMode /In/ ); + void getElectronicShutterMode(std::string &oMode /Out/ ) const; + void getElectronicShutterModeList(std::vector<std::string> &oModeList /Out/) const; void setBitDepth(A3_BitDepth iMode /In/ ); void getBitDepth(A3_BitDepth &oMode /Out/ ) const; diff --git a/sip/Andor3Interface.sip b/sip/Andor3Interface.sip index 194cd4e..610cd4b 100644 --- a/sip/Andor3Interface.sip +++ b/sip/Andor3Interface.sip @@ -56,9 +56,9 @@ namespace Andor3 virtual void setAdcRate(std::string iRate /In/ ); virtual void getAdcRate(std::string &oRate /Out/ ) const; virtual void getAdcRateList(std::vector<std::string> &oRateList /Out/ ) const; - virtual void setElectronicShutterMode(Andor3::Camera::A3_ShutterMode iMode /In/ ); - virtual void getElectronicShutterMode(Andor3::Camera::A3_ShutterMode &oMode /Out/ ) const; - virtual void getElectronicShutterModeString(std::string &oModeString /Out/ ) const; + virtual void setElectronicShutterMode(std::string iMode /In/ ); + virtual void getElectronicShutterMode(std::string &oMode /Out/ ) const; + virtual void getElectronicShutterModeList(std::vector<std::string> &oModeList /Out/ ) const; virtual void setOverlap(bool i_overlap /In/ ); virtual void getOverlap(bool &o_overlap /Out/ ) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 1e71356..9091923 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -168,7 +168,6 @@ m_bitflow_path(bitflow_path), m_camera_number(camera_number), m_camera_handle(AT_HANDLE_UNINITIALISED), m_adc_gain(Gain1_Gain4), -m_electronic_shutter_mode(Rolling), m_bit_depth(b16), m_trig_mode(IntTrig), m_cooler(true), @@ -1184,7 +1183,7 @@ lima::Andor3::Camera::initialiseController() A3_BitDepth the_bd = m_bit_depth; // Carefully crafting the order, since some are affecting others... - setElectronicShutterMode(m_electronic_shutter_mode); + setElectronicShutterMode(RollingShutterMode); setTrigMode(m_trig_mode); setBitDepth(the_bd); setCooler(m_cooler); @@ -1302,17 +1301,16 @@ lima::Andor3::Camera::getAdcRateList(std::vector<std::string> &adc_rate_list) co } void -lima::Andor3::Camera::setElectronicShutterMode(A3_ShutterMode iMode) +lima::Andor3::Camera::setElectronicShutterMode(std::string shut_mode) { DEB_MEMBER_FUNCT(); - int the_mode; - setEnumIndex(andor3::ElectronicShutteringMode, iMode); - getEnumIndex(andor3::ElectronicShutteringMode, &the_mode); - m_electronic_shutter_mode = static_cast<A3_ShutterMode>(the_mode); - if ( m_electronic_shutter_mode != iMode ) { + std::string set_mode; + setEnumString(andor3::ElectronicShutteringMode, shut_mode); + getEnumString(andor3::ElectronicShutteringMode, set_mode); + if ( set_mode != shut_mode ) { DEB_ERROR() << "Proof-reading the electronic shutter mode :" - << "\n\tGot " << m_electronic_shutter_mode << " back," - << "\n\twhile requesting " << iMode; + << "\n\tGot " << set_mode << " back," + << "\n\twhile requesting " << shut_mode; } // Setting the trigger mode might change the ADCGain and ADCRate : std::string the_rate; @@ -1325,19 +1323,24 @@ lima::Andor3::Camera::setElectronicShutterMode(A3_ShutterMode iMode) } void -lima::Andor3::Camera::getElectronicShutterMode(A3_ShutterMode &oMode) const +lima::Andor3::Camera::getElectronicShutterMode(std::string &shut_mode) const { DEB_MEMBER_FUNCT(); -// int the_mode; -// getEnumIndex(andor3::ElectronicShutteringMode, &the_mode); -// oMode = static_cast<A3_ShutterMode>(the_mode); - oMode = m_electronic_shutter_mode; + getEnumString(andor3::ElectronicShutteringMode, shut_mode); } void -lima::Andor3::Camera::getElectronicShutterModeString(std::string &oModeString) const +lima::Andor3::Camera::getElectronicShutterModeList(std::vector<std::string> &shut_mode_list) const { - getEnumStringByIndex(andor3::ElectronicShutteringMode, m_electronic_shutter_mode, oModeString); + int enum_count; + AT_WC s_value[1024]; + + AT_GetEnumCount(m_camera_handle, andor3::ElectronicShutteringMode, &enum_count); + + for (int idx=0; enum_count != idx; ++idx) { + AT_GetEnumStringByIndex(m_camera_handle, andor3::ElectronicShutteringMode, idx, s_value, 1024); + shut_mode_list.push_back(WStringToString(s_value)); + } } void @@ -1712,7 +1715,7 @@ lima::Andor3::Camera::setSimpleGain(std::string i_gain) } else { DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; - A3_ShutterMode the_shutter; + std::string the_shutter; getElectronicShutterMode(the_shutter); @@ -1720,13 +1723,13 @@ lima::Andor3::Camera::setSimpleGain(std::string i_gain) setAdcGain(Gain1); } else if (i_gain == "b11_hi_gain") { - if ( Rolling == the_shutter ) + if ( RollingShutterMode == the_shutter ) setAdcGain(Gain4); else setAdcGain(Gain3); } else if (i_gain == "b16_lh_gain") { - if ( Rolling == the_shutter ) + if ( RollingShutterMode == the_shutter ) setAdcGain(Gain1_Gain4); else setAdcGain(Gain1_Gain3); @@ -1757,12 +1760,12 @@ lima::Andor3::Camera::getSimpleGain(std::string &o_gain) const DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; A3_Gain the_gain; - A3_ShutterMode the_shutter; + std::string the_shutter; getAdcGain(the_gain); getElectronicShutterMode(the_shutter); - if ( Rolling == the_shutter ) { + if ( RollingShutterMode == the_shutter ) { switch (the_gain) { case Gain1: o_gain = "b11_low_gain"; diff --git a/src/Andor3Interface.cpp b/src/Andor3Interface.cpp index 98e6274..b37e450 100644 --- a/src/Andor3Interface.cpp +++ b/src/Andor3Interface.cpp @@ -236,7 +236,7 @@ lima::Andor3::Interface::getAdcRateList(std::vector<std::string> &oRateList) con } void -lima::Andor3::Interface::setElectronicShutterMode(Camera::A3_ShutterMode iMode) +lima::Andor3::Interface::setElectronicShutterMode(std::string iMode) { DEB_MEMBER_FUNCT(); m_cam.setElectronicShutterMode(iMode); @@ -244,17 +244,17 @@ lima::Andor3::Interface::setElectronicShutterMode(Camera::A3_ShutterMode iMode) } void -lima::Andor3::Interface::getElectronicShutterMode(Camera::A3_ShutterMode &oMode) const +lima::Andor3::Interface::getElectronicShutterMode(std::string &oMode) const { DEB_MEMBER_FUNCT(); m_cam.getElectronicShutterMode(oMode); } void -lima::Andor3::Interface::getElectronicShutterModeString(std::string &oModeString) const +lima::Andor3::Interface::getElectronicShutterModeList(std::vector<std::string> &oModeList) const { DEB_MEMBER_FUNCT(); - m_cam.getElectronicShutterModeString(oModeString); + m_cam.getElectronicShutterModeList(oModeList); } void diff --git a/tango/Andor3.py b/tango/Andor3.py index 4eb4ba8..e8fe3e4 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -81,10 +81,8 @@ class Andor3(PyTango.Device_4Impl): # dictionnaries to be used with AttrHelper.get_attr_4u self.__AdcGain = andor_list2dict(_Andor3Camera.getSimpleGainList()) self.__AdcRate = andor_list2dict(_Andor3Camera.getAdcRateList()) + self.__ElectronicShutterMode = andor_list2dict(_Andor3Camera.getElectronicShutterModeList()) self.__Cooler = {'ON': True, 'OFF': False} - self.__ElectronicShutterMode = {'ROLLING': _Andor3Camera.Rolling, - 'GLOBAL': _Andor3Camera.Global, - } self.__Overlap = {'ON': True, 'OFF': False} self.__SpuriousNoiseFilter = {'ON': True, 'OFF': False} self.__GateInverted = { 'YES': True, 'NO': False } @@ -261,10 +259,10 @@ class Andor3Class(PyTango.DeviceClass): PyTango.SCALAR, PyTango.READ], { - 'label':'Fast trigger mode, see manual for usage', + 'label':'Cooling status', 'unit': 'N/A', 'format': '', - 'description': '0-OFF / 1-ON', + 'description': 'Cooling status', }], 'adc_gain': [[PyTango.DevString, @@ -304,7 +302,7 @@ class Andor3Class(PyTango.DeviceClass): 'label':'Fan speed', 'unit': 'N/A', 'format': '', - 'description': 'Fan speed, off, low or High', + 'description': 'Fan speed setting', }], 'frame_rate': [[PyTango.DevDouble, -- GitLab From e46c2f3ecb70b90eba8c75f88cda6ae74416f3bf Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 1 Apr 2022 16:37:59 +0200 Subject: [PATCH 19/24] Introduce getEnumStringList to get the list of possible string values for a given andor feature. --- include/Andor3Camera.h | 1 + src/Andor3Camera.cpp | 71 ++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 44 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index 2d6c1bf..bf6971d 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -266,6 +266,7 @@ namespace lima int getEnumIndex(const AT_WC* Feature, int* Value) const; int setEnumString(const AT_WC* Feature, std::string Value); int getEnumString(const AT_WC* Feature, std::string& Value) const; + int getEnumStringList(const AT_WC* Feature, std::vector<std::string> &ValueList) const; int getEnumCount(AT_H Hndl,const AT_WC* Feature, int* Count) const; int isEnumIndexAvailable(const AT_WC* Feature, int Index, bool* Available) const; int isEnumIndexImplemented(const AT_WC* Feature, int Index, bool* Implemented) const; diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index 9091923..ebea63a 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -1289,15 +1289,8 @@ lima::Andor3::Camera::getAdcRate(std::string &adc_rate) const void lima::Andor3::Camera::getAdcRateList(std::vector<std::string> &adc_rate_list) const { - int enum_count; - AT_WC s_value[1024]; - - AT_GetEnumCount(m_camera_handle, andor3::PixelReadoutRate, &enum_count); - - for (int idx=0; enum_count != idx; ++idx) { - AT_GetEnumStringByIndex(m_camera_handle, andor3::PixelReadoutRate, idx, s_value, 1024); - adc_rate_list.push_back(WStringToString(s_value)); - } + DEB_MEMBER_FUNCT(); + getEnumStringList(andor3::PixelReadoutRate, adc_rate_list); } void @@ -1332,15 +1325,8 @@ lima::Andor3::Camera::getElectronicShutterMode(std::string &shut_mode) const void lima::Andor3::Camera::getElectronicShutterModeList(std::vector<std::string> &shut_mode_list) const { - int enum_count; - AT_WC s_value[1024]; - - AT_GetEnumCount(m_camera_handle, andor3::ElectronicShutteringMode, &enum_count); - - for (int idx=0; enum_count != idx; ++idx) { - AT_GetEnumStringByIndex(m_camera_handle, andor3::ElectronicShutteringMode, idx, s_value, 1024); - shut_mode_list.push_back(WStringToString(s_value)); - } + DEB_MEMBER_FUNCT(); + getEnumStringList(andor3::ElectronicShutteringMode, shut_mode_list); } void @@ -1471,15 +1457,8 @@ lima::Andor3::Camera::getOutputSignal(std::string &oSignal) const void lima::Andor3::Camera::getOutputSignalList(std::vector<std::string> &signal_list) const { - int enum_count; - std::string s_value; - - AT_GetEnumCount(m_camera_handle, andor3::AuxiliaryOutSource, &enum_count); - - for (int idx=0; enum_count != idx; ++idx) { - getEnumStringByIndex(andor3::AuxiliaryOutSource, idx, s_value); - signal_list.push_back(s_value); - } + DEB_MEMBER_FUNCT(); + getEnumStringList(andor3::AuxiliaryOutSource, signal_list); } //----------------------------------------------------- @@ -1648,15 +1627,8 @@ lima::Andor3::Camera::getBufferOverflow(bool &o_overflow) const void lima::Andor3::Camera::getFanSpeedList(std::vector<std::string> &fan_speed_list) const { - int enum_count; - AT_WC s_value[1024]; - - AT_GetEnumCount(m_camera_handle, andor3::FanSpeed, &enum_count); - - for (int idx=0; enum_count != idx; ++idx) { - AT_GetEnumStringByIndex(m_camera_handle, andor3::FanSpeed, idx, s_value, 1024); - fan_speed_list.push_back(WStringToString(s_value)); - } + DEB_MEMBER_FUNCT(); + getEnumStringList(andor3::FanSpeed, fan_speed_list); } void @@ -1808,14 +1780,7 @@ lima::Andor3::Camera::getSimpleGainList(std::vector<std::string> &gain_list) con { DEB_MEMBER_FUNCT(); if ( propImplemented(andor3::SimplePreAmpGainControl) ) { - int enum_count; - std::string s_value; - AT_GetEnumCount(m_camera_handle, andor3::SimplePreAmpGainControl, &enum_count); - - for (int idx=0; enum_count != idx; ++idx) { - getEnumStringByIndex(andor3::SimplePreAmpGainControl, idx, s_value); - gain_list.push_back(s_value); - } + getEnumStringList(andor3::SimplePreAmpGainControl, gain_list); } else { DEB_TRACE() << "SimplePreAmpGainControl not implemented, emulating it in software"; @@ -2419,6 +2384,24 @@ lima::Andor3::Camera::getEnumString(const AT_WC* Feature, std::string& Value) co return ierr; } +int +lima::Andor3::Camera::getEnumStringList(const AT_WC* Feature, std::vector<std::string> &value_list) const +{ + int ierr, enum_count; + AT_WC s_value[1024]; + + ierr = AT_GetEnumCount(m_camera_handle, Feature, &enum_count); + if (AT_SUCCESS != ierr) + return ierr; + + for (int idx=0; enum_count != idx; ++idx) { + ierr = AT_GetEnumStringByIndex(m_camera_handle, Feature, idx, s_value, 1024); + if (AT_SUCCESS != ierr) + return ierr; + value_list.push_back(WStringToString(s_value)); + } +} + int lima::Andor3::Camera::getEnumCount(AT_H m_camera_handle,const AT_WC* Feature, int* Count) const { -- GitLab From d00fdba11af7c354ff67187448c5c568ba9b935a Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Mon, 4 Apr 2022 16:57:53 +0200 Subject: [PATCH 20/24] add a serial_number to camera initialisation: if serial_number is set, try to find camera with the correct serial number if serial_number not set, use the first real camera connected if serial_number set to "SIMULATION", use a simulated camera this allow to have 2 servers on the same PC, specifying the serial_number for each camera. --- include/Andor3Camera.h | 2 +- sip/Andor3Camera.sip | 2 +- src/Andor3Camera.cpp | 77 ++++++++++++++++++++++++++++-------------- tango/Andor3.py | 10 +++--- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/include/Andor3Camera.h b/include/Andor3Camera.h index bf6971d..f708ec2 100644 --- a/include/Andor3Camera.h +++ b/include/Andor3Camera.h @@ -98,7 +98,7 @@ namespace lima int getHwBitDepth(int *bit_depth); - Camera(const std::string& bitflow_path, int camera_number=0); + Camera(const std::string& bitflow_path, std::string serial_number=""); ~Camera(); // Preparing the camera's SDK to acquire frames diff --git a/sip/Andor3Camera.sip b/sip/Andor3Camera.sip index 7520178..ed1bf76 100644 --- a/sip/Andor3Camera.sip +++ b/sip/Andor3Camera.sip @@ -36,7 +36,7 @@ namespace Andor3 enum A3_Binning { B1x1=0, B2x2=1, B3x3=2, B4x4=3, B8x8=4}; enum A3_PixelEncoding {Mono12=0, Mono12Packed = 1, Mono16=2, Mono32=3}; - Camera(const std::string& bitflow_path, int camera_number=0); + Camera(const std::string& bitflow_path, std::string serial_number=""); ~Camera(); void prepareAcq(); diff --git a/src/Andor3Camera.cpp b/src/Andor3Camera.cpp index ebea63a..db3b331 100644 --- a/src/Andor3Camera.cpp +++ b/src/Andor3Camera.cpp @@ -148,7 +148,7 @@ namespace lima { } -lima::Andor3::Camera::Camera(const std::string& bitflow_path, int camera_number) : +lima::Andor3::Camera::Camera(const std::string& bitflow_path, std::string serial_number) : m_acq_thread(NULL), m_cond(), m_acq_thread_waiting(true), @@ -165,7 +165,7 @@ m_detector_serial("un-inited"), m_detector_size(1,1), m_exp_time(1.0), m_bitflow_path(bitflow_path), -m_camera_number(camera_number), +m_camera_number(-1), m_camera_handle(AT_HANDLE_UNINITIALISED), m_adc_gain(Gain1_Gain4), m_bit_depth(b16), @@ -209,30 +209,58 @@ m_maximage_size_cb_active(false) } pthread_mutex_unlock(&sdkInitMutex); - // --- Get available cameras and select the choosen one. + // --- Get available cameras and found the serial_number asked + // --- if serial_number == "SIMULATION", use a simulation camera + // --- if serial_number == "", use first real camera AT_64 numCameras; + int iErr; DEB_TRACE() << "Get all attached cameras"; THROW_IF_NOT_SUCCESS(getIntSystem(andor3::DeviceCount, &numCameras), "No camera present!"); DEB_TRACE() << "Found "<< numCameras << " camera" << ((numCameras>1)? "s": ""); - DEB_TRACE() << "Try to set current camera to number " << m_camera_number; - - if ( m_camera_number < numCameras && m_camera_number >=0 ) { - // Getting the m_camera_handle WITH some error checking : - THROW_IF_NOT_SUCCESS(AT_Open(m_camera_number, &m_camera_handle), - "Cannot get camera handle"); - } - else { - THROW_HW_ERROR(InvalidValue) << "Invalid camera number " - << m_camera_number << ", there is " - << numCameras << " available"; + if (serial_number.length() > 0) { + DEB_ALWAYS() << "Looking for camera with serial number " << serial_number; + } + for (int iCam = 0; iCam < numCameras; iCam++) { + iErr = AT_Open(iCam, &m_camera_handle); + if (iErr != AT_SUCCESS) { + DEB_ALWAYS() << "Camera " << iCam << " : Cannot open camera"; + continue; + } + + iErr = getString(andor3::CameraModel, m_detector_model); + if (iErr != AT_SUCCESS) { + DEB_ALWAYS() << "Camera " << iCam << " : Cannot get camera model"; + m_detector_model = "unknown"; + } + + iErr = getString(andor3::SerialNumber, m_detector_serial); + if (iErr != AT_SUCCESS) { + DEB_ALWAYS() << "Camera " << iCam << " : Cannot get camera serial"; + m_detector_serial = "unknown"; + } + + DEB_ALWAYS() << "Camera " << iCam << " : Model " << m_detector_model << " SerialNumber " << m_detector_serial; + + if ((m_detector_serial == serial_number) || + ((serial_number.compare(0, 4, "SIMU")==0) && (m_detector_model.compare(0, 6, "SIMCAM")==0)) || + ((serial_number.length()==0) && (m_detector_model.compare(0, 5, "SIMCAM")!=0))) { + DEB_ALWAYS() << "Found camera asked " << serial_number; + m_camera_number = iCam; + break; + } + + iErr = AT_Close(m_camera_handle); + if (iErr != AT_SUCCESS) { + DEB_ALWAYS() << "Camera " << iCam << " : Cannot close connection"; + } } - - // --- Get Camera model (and all other parameters which are not changing during camera setup and usage ) - THROW_IF_NOT_SUCCESS(getString(andor3::CameraModel, m_detector_model), - "Cannot get camera model"); + if (m_camera_number == -1) { + THROW_HW_ERROR(Error) << "Cannot find asked camera serial " << serial_number; + } + // Adding some extra information on the model (more human readable) : // DC-152 -> Neo if ( ! m_detector_model.compare(0, 6, "DC-152 ")) { @@ -258,12 +286,11 @@ m_maximage_size_cb_active(false) } if ( m_detector_model != "SIMCAM CMOS" ) { - std::string the_serial, the_fw; + std::string the_fw; - getSerialNumber(the_serial); getFirmwareVersion(the_fw); m_real_camera = true; - m_detector_model += " (SN : " + the_serial + ", firmware " + the_fw + ")"; + m_detector_model += " (SN : " + m_detector_serial + ", firmware " + the_fw + ")"; DEB_ALWAYS() << "Camera is ready: type " << m_detector_type << ", model "<< m_detector_model; } @@ -276,8 +303,8 @@ m_maximage_size_cb_active(false) } // --- Get Camera Serial number - THROW_IF_NOT_SUCCESS(getString(andor3::SerialNumber, m_detector_serial), - "Cannot get camera serial number"); +// THROW_IF_NOT_SUCCESS(getString(andor3::SerialNumber, m_detector_serial), +// "Cannot get camera serial number"); // --- Get Camera maximum image size AT_64 xmax, ymax; @@ -1478,13 +1505,13 @@ lima::Andor3::Camera::initTemperature() float value; m_has_temperature_control = true; - DEB_ALWAYS() << "Camera has temperature setpoints pre-defined"; + DEB_ALWAYS() << "Camera has temperature setpoints pre-defined :"; getEnumCount(m_camera_handle, andor3::TemperatureControl, &ntemp); for (int idx=0; idx != ntemp; ++idx) { AT_GetEnumStringByIndex(m_camera_handle, andor3::TemperatureControl, idx, at_string, 255); value = std::stof(WStringToString(at_string)); m_temperature_control_values.push_back(value); - DEB_ALWAYS() << "Index " << idx << " Setpoint " << value; + DEB_ALWAYS() << " - Setpoint = " << value; } getEnumIndex(andor3::TemperatureControl, ¤t_idx); m_temperature_sp = m_temperature_control_values[current_idx]; diff --git a/tango/Andor3.py b/tango/Andor3.py index e8fe3e4..4726d36 100644 --- a/tango/Andor3.py +++ b/tango/Andor3.py @@ -193,8 +193,8 @@ class Andor3Class(PyTango.DeviceClass): 'config_path': [PyTango.DevString, 'configuration path directory', []], - 'camera_number': - [PyTango.DevShort, + 'serial_number': + [PyTango.DevString, 'Camera number', []], 'adc_gain': [PyTango.DevString, @@ -412,15 +412,15 @@ from Lima import Andor3 as Andor3Acq _Andor3Camera = None _Andor3Interface = None -def get_control(config_path='/users/blissadm/local/Andor3/andor/bitflow', camera_number = '0', **keys) : +def get_control(config_path='/users/blissadm/local/Andor3/andor/bitflow', serial_number = '', **keys) : #properties are passed here as string global _Andor3Camera global _Andor3Interface if _Andor3Camera is None: print ('\n\nStarting and configuring the Andor3 camera ...') - _Andor3Camera = Andor3Acq.Camera(config_path, int(camera_number)) + _Andor3Camera = Andor3Acq.Camera(config_path, serial_number) _Andor3Interface = Andor3Acq.Interface(_Andor3Camera) - print ('\n\nAndor3 Camera #%s (%s:%s) is started'%(camera_number,_Andor3Camera.getDetectorType(),_Andor3Camera.getDetectorModel())) + print ('\n\nAndor3 Camera (%s:%s) is started'%(_Andor3Camera.getDetectorType(),_Andor3Camera.getDetectorModel())) return Core.CtControl(_Andor3Interface) -- GitLab From 6a090c796423199552cb2cc6f216efa1509145e2 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Mon, 4 Apr 2022 17:38:13 +0200 Subject: [PATCH 21/24] use mambabuild in conda --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 39a044c..bb631e7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ stages: build-linux: <<: *build-conda script: - - conda build ./conda/camera --prefix-length=80 --output-folder=dist/ -c conda-forge --channel=http://bcu-ci.esrf.fr/stable + - conda mambabuild ./conda/camera --prefix-length=80 --output-folder=dist/ --channel=http://bcu-ci.esrf.fr/stable tags: - linux @@ -22,7 +22,7 @@ build-noarch: <<: *build-conda stage: build-noarch script: - - conda build ./conda/tango --prefix-length=80 --output-folder=dist/ -c tango-controls --channel=http://bcu-ci.esrf.fr/stable + - conda mambabuild ./conda/tango --prefix-length=80 --output-folder=dist/ --channel=http://bcu-ci.esrf.fr/stable dependencies: - build-linux -- GitLab From 39580c77c2a7911f7577f016bec207b221f30dec Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 8 Apr 2022 09:48:24 +0200 Subject: [PATCH 22/24] add python 3.* in conda packages --- conda/camera/conda_build_config.yaml | 2 ++ conda/camera/meta.yaml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/conda/camera/conda_build_config.yaml b/conda/camera/conda_build_config.yaml index 2479ceb..2188672 100644 --- a/conda/camera/conda_build_config.yaml +++ b/conda/camera/conda_build_config.yaml @@ -6,6 +6,8 @@ cxx_compiler: - vs2017 # [win] python: - 3.7 + - 3.8 + - 3.9 # This differs from target_platform in that it determines what subdir the compiler # will target, not what subdir the compiler package will be itself. # For example, we need a win-64 vs2008_win-32 package, so that we compile win-32 diff --git a/conda/camera/meta.yaml b/conda/camera/meta.yaml index 7d82904..b68c7dc 100644 --- a/conda/camera/meta.yaml +++ b/conda/camera/meta.yaml @@ -18,7 +18,7 @@ build: requirements: host: - python {{ python }} - - sip 4.19.8 # For compatibility with pyqt 5.9.2 + - sip 4.19* - lima-core - andor3-sdk 3.14 build: @@ -27,7 +27,7 @@ requirements: - {{ compiler('cxx') }} run: - python {{ python }} - - sip >=4.19.4, <=4.19.8 # For compatibility with pyqt 5.9.2 + - {{ pin_compatible('sip', min_pin='x.x.x', max_pin='x') }} - {{ pin_compatible('lima-core', max_pin='x.x') }} - andor3-sdk 3.14 -- GitLab From ccab0463a9783042a9256cf23e13ff27b5e63734 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 8 Apr 2022 09:57:56 +0200 Subject: [PATCH 23/24] add copy-constrcutor in sip --- sip/Andor3Interface.sip | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sip/Andor3Interface.sip b/sip/Andor3Interface.sip index 610cd4b..a5330e8 100644 --- a/sip/Andor3Interface.sip +++ b/sip/Andor3Interface.sip @@ -64,5 +64,8 @@ namespace Andor3 virtual void getOverlap(bool &o_overlap /Out/ ) const; virtual void setSyncTriggering(bool i_sync /In/ ); virtual void getSyncTriggering(bool &o_sync /Out/ ) const; + + private: + Interface(const Andor3::Camera&); }; }; -- GitLab From dfccfafcd311ac2a29850a2acd7568a1f823ae63 Mon Sep 17 00:00:00 2001 From: Emmanuel Papillon <papillon@esrf.fr> Date: Fri, 8 Apr 2022 10:12:17 +0200 Subject: [PATCH 24/24] bug in sip --- sip/Andor3Interface.sip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sip/Andor3Interface.sip b/sip/Andor3Interface.sip index a5330e8..795f608 100644 --- a/sip/Andor3Interface.sip +++ b/sip/Andor3Interface.sip @@ -66,6 +66,6 @@ namespace Andor3 virtual void getSyncTriggering(bool &o_sync /Out/ ) const; private: - Interface(const Andor3::Camera&); + Interface(const Andor3::Interface&); }; }; -- GitLab