diff --git a/DeviceAdapters/ASIFW1000/ASIFW1000Hub.cpp b/DeviceAdapters/ASIFW1000/ASIFW1000Hub.cpp index 727a5e77ec..5328d4eb5f 100644 --- a/DeviceAdapters/ASIFW1000/ASIFW1000Hub.cpp +++ b/DeviceAdapters/ASIFW1000/ASIFW1000Hub.cpp @@ -33,6 +33,7 @@ #include "assert.h" #include +#include #include #include #include diff --git a/DeviceAdapters/DemoStreamingCamera/NoiseProcessor.cpp b/DeviceAdapters/DemoStreamingCamera/NoiseProcessor.cpp index 0a3ac88a49..b4622232c5 100644 --- a/DeviceAdapters/DemoStreamingCamera/NoiseProcessor.cpp +++ b/DeviceAdapters/DemoStreamingCamera/NoiseProcessor.cpp @@ -58,7 +58,7 @@ DemoNoiseProcessor::DemoNoiseProcessor() : InitializeDefaultErrorMessages(); /* Generate a new random seed from system time - do this once in your constructor */ - std::srand((unsigned int)GetClockTicksUs()); + srand((unsigned int)GetClockTicksUs()); } DemoNoiseProcessor::~DemoNoiseProcessor() diff --git a/DeviceAdapters/Hamamatsu/Hamamatsu.cpp b/DeviceAdapters/Hamamatsu/Hamamatsu.cpp index 57df687cba..d7a2e0c234 100644 --- a/DeviceAdapters/Hamamatsu/Hamamatsu.cpp +++ b/DeviceAdapters/Hamamatsu/Hamamatsu.cpp @@ -50,6 +50,7 @@ #endif #include #include +#include #include #include @@ -154,6 +155,7 @@ CHamamatsu::CHamamatsu() : SetErrorText(ERR_BUSY_ACQUIRING, "Busy acquiring an image"); SetErrorText(ERR_BUFFER_ALLOCATION_FAILED, "Buffer allocation failed"); SetErrorText(ERR_INCOMPLETE_SNAP_IMAGE_CYCLE, "Incomplete snap image cycle"); + SetErrorText(ERR_NO_CAMERA_FOUND, "No camera found"); } CHamamatsu::~CHamamatsu() @@ -190,7 +192,7 @@ int CHamamatsu::OnBinning(MM::PropertyBase* pProp, MM::ActionType eAct) if (nRet != DEVICE_OK) return nRet; if (!dcam_setbinning(m_hDCAM, lnBin_)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_setbinning: "); nRet = ResizeImageBuffer(); if (nRet != DEVICE_OK) return nRet; @@ -198,7 +200,7 @@ int CHamamatsu::OnBinning(MM::PropertyBase* pProp, MM::ActionType eAct) else if (eAct == MM::BeforeGet) { if (!dcam_getbinning(m_hDCAM, &lnBin_)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getbinning: "); pProp->Set(lnBin_); } return DEVICE_OK; @@ -218,7 +220,7 @@ int CHamamatsu::OnTrigPolarity(MM::PropertyBase* pProp, MM::ActionType eAct) if (triggerPolarity == g_TrigPolarity_Negative) pol = DCAM_TRIGPOL_NEGATIVE; if (!dcam_settriggerpolarity(m_hDCAM, pol)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_settriggerpolarity: "); nRet = ResizeImageBuffer(); if (nRet != DEVICE_OK) return nRet; @@ -227,7 +229,7 @@ int CHamamatsu::OnTrigPolarity(MM::PropertyBase* pProp, MM::ActionType eAct) { long pol; if (!dcam_gettriggerpolarity(m_hDCAM, &pol)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_gettriggerpolarity: "); if (pol == DCAM_TRIGPOL_NEGATIVE) pProp->Set(g_TrigPolarity_Negative); else @@ -273,7 +275,7 @@ int CHamamatsu::OnTrigMode(MM::PropertyBase* pProp, MM::ActionType eAct) LogMessage(os.str().c_str(), true); if (!dcam_settriggermode(m_hDCAM, mode)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_settriggermode: "); triggerMode_ = triggerMode; nRet = ResizeImageBuffer(); @@ -284,7 +286,7 @@ int CHamamatsu::OnTrigMode(MM::PropertyBase* pProp, MM::ActionType eAct) { long mode; if (!dcam_gettriggermode(m_hDCAM, &mode)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_gettriggermode: "); ostringstream os; os << "Triggermode found: " << mode; LogMessage(os.str().c_str(), true); @@ -313,7 +315,7 @@ int CHamamatsu::OnExposure(MM::PropertyBase* pProp, MM::ActionType eAct) { double dExp; if (!dcam_getexposuretime(m_hDCAM, &dExp)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getexposuretime: "); pProp->Set(dExp * 1000.0); } else if (eAct == MM::AfterSet) @@ -321,7 +323,7 @@ int CHamamatsu::OnExposure(MM::PropertyBase* pProp, MM::ActionType eAct) double dExp; pProp->Get(dExp); if (!dcam_setexposuretime(m_hDCAM, dExp / 1000.0)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_setexposuretime: "); } return DEVICE_OK; } @@ -333,7 +335,7 @@ int CHamamatsu::OnPixelType(MM::PropertyBase* pProp, MM::ActionType eAct) if (eAct == MM::BeforeGet) { if (!dcam_getdatatype(m_hDCAM, &ccDataType)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getdatatype: "); if (ccDataType == ccDatatype_uint8 || ccDataType == ccDatatype_int8) { @@ -367,7 +369,7 @@ int CHamamatsu::OnPixelType(MM::PropertyBase* pProp, MM::ActionType eAct) return nRet; if (!dcam_setdatatype(m_hDCAM, ccDataType)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_setdatatype: "); nRet = ResizeImageBuffer(); if (nRet != DEVICE_OK) @@ -393,7 +395,7 @@ int CHamamatsu::OnScanMode(MM::PropertyBase* pProp, MM::ActionType eAct) if (ret != DEVICE_OK) return ret; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&ScanMode, sizeof(DCAM_PARAM_SCANMODE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (scanmode): "); ret = ResizeImageBuffer(); if (ret != DEVICE_OK) @@ -402,7 +404,7 @@ int CHamamatsu::OnScanMode(MM::PropertyBase* pProp, MM::ActionType eAct) // Reset allowedValues for binning and gain DWORD cap; if(!dcam_getcapability(m_hDCAM, &cap, DCAM_QUERYCAPABILITY_FUNCTIONS)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getcapability: "); ret = SetAllowedBinValues(cap); if (ret != DEVICE_OK) return ret; @@ -421,7 +423,7 @@ int CHamamatsu::OnScanMode(MM::PropertyBase* pProp, MM::ActionType eAct) else if (eAct == MM::BeforeGet) { if (!dcam_extended(m_hDCAM,DCAM_IDMSG_GETPARAM, (LPVOID)&ScanMode, sizeof(DCAM_PARAM_SCANMODE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (ScanMode): "); pProp->Set(ScanMode.speed); } return DEVICE_OK; @@ -438,7 +440,7 @@ int CHamamatsu::OnCCDMode(MM::PropertyBase* pProp, MM::ActionType eAct) if (ret != DEVICE_OK) return ret; if (!dcam_setpropertyvalue(m_hDCAM, DCAM_IDPROP_CCDMODE, ccdMode)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_Setpropertyvalue (ccdMode): "); ret = ResizeImageBuffer(); if (ret != DEVICE_OK) @@ -447,7 +449,7 @@ int CHamamatsu::OnCCDMode(MM::PropertyBase* pProp, MM::ActionType eAct) // Reset allowedValues for binning and gain DWORD cap; if(!dcam_getcapability(m_hDCAM, &cap, DCAM_QUERYCAPABILITY_FUNCTIONS)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getcapability: "); ret = SetAllowedBinValues(cap); if (ret != DEVICE_OK) return ret; @@ -467,7 +469,7 @@ int CHamamatsu::OnCCDMode(MM::PropertyBase* pProp, MM::ActionType eAct) { double ccdMode; if (!dcam_getpropertyvalue(m_hDCAM, DCAM_IDPROP_CCDMODE, &ccdMode)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getpropertyvalue (ccdMode): "); //if (!dcam_querypropertyvalue(m_hDCAM, DCAM_IDPROP_CCDMODE, &ccdMode, DCAMPROP_OPTION_NONE)) // return dcam_getlasterror(m_hDCAM, NULL, 0); @@ -487,7 +489,7 @@ int CHamamatsu::OnPhotonImagingMode(MM::PropertyBase* pProp, MM::ActionType eAct if (ret != DEVICE_OK) return ret; if (!dcam_setpropertyvalue(m_hDCAM, DCAM_IDPROP_PHOTONIMAGINGMODE, mode)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_setpropertyvalue (photonimagingMode): "); ret = ResizeImageBuffer(); if (ret != DEVICE_OK) @@ -496,7 +498,7 @@ int CHamamatsu::OnPhotonImagingMode(MM::PropertyBase* pProp, MM::ActionType eAct // Reset allowedValues for binning and gain DWORD cap; if(!dcam_getcapability(m_hDCAM, &cap, DCAM_QUERYCAPABILITY_FUNCTIONS)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getcapability: "); ret = SetAllowedBinValues(cap); if (ret != DEVICE_OK) return ret; @@ -516,12 +518,40 @@ int CHamamatsu::OnPhotonImagingMode(MM::PropertyBase* pProp, MM::ActionType eAct { double photonMode; if (!dcam_getpropertyvalue(m_hDCAM, DCAM_IDPROP_PHOTONIMAGINGMODE, &photonMode)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getpropertyvalue (photonimagingmode): "); pProp->Set(photonMode); } return DEVICE_OK; } +// Output Trigger Polarity +int CHamamatsu::OnOutputTriggerPolarity(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::AfterSet) + { + double mode; + pProp->Get(mode); + // Not sure if we need to shut down the image buffer + int ret = ShutdownImageBuffer(); + if (ret != DEVICE_OK) + return ret; + if (!dcam_setpropertyvalue(m_hDCAM, DCAM_IDPROP_OUTPUTTRIGGER_POLARITY, mode)) + return ReportError("Error in dcam_setpropertyvalue (outputtriggerpolarity): "); + + ret = ResizeImageBuffer(); + if (ret != DEVICE_OK) + return ret; + } + else if (eAct == MM::BeforeGet) + { + double polarity; + if (!dcam_getpropertyvalue(m_hDCAM, DCAM_IDPROP_OUTPUTTRIGGER_POLARITY, &polarity)) + return ReportError("Error in dcam_getpropertyvalue (outputtriggerpolarity): "); + pProp->Set(polarity); + } + return DEVICE_OK; +} + // ReadoutTime int CHamamatsu::OnReadoutTime(MM::PropertyBase* pProp, MM::ActionType eAct) { @@ -533,7 +563,7 @@ int CHamamatsu::OnReadoutTime(MM::PropertyBase* pProp, MM::ActionType eAct) if (eAct == MM::BeforeGet) { if (!dcam_extended(m_hDCAM,DCAM_IDMSG_GETPARAM, (LPVOID)&readoutTime, sizeof(DCAM_PARAM_FRAME_READOUT_TIME_INQ))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (frame_readout_time_inq): "); pProp->Set(readoutTime.framereadouttime * 1000.0); } @@ -553,7 +583,7 @@ int CHamamatsu::OnActualIntervalMs(MM::PropertyBase* pProp, MM::ActionType eAct) readoutTime = atof(rT); double dExp; if (!dcam_getexposuretime(m_hDCAM, &dExp)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_exposuretime: "); double interval = max(readoutTime, dExp * 1000); pProp->Set(interval); } @@ -576,12 +606,12 @@ int CHamamatsu::OnGain(MM::PropertyBase* pProp, MM::ActionType eAct) pProp->Get(lnGain); FeatureValue.featurevalue = (float)lnGain; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (set gain): "); } else if (eAct == MM::BeforeGet) { if (!dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (get gain): "); pProp->Set(FeatureValue.featurevalue); } return DEVICE_OK; @@ -602,12 +632,12 @@ int CHamamatsu::OnGamma(MM::PropertyBase* pProp, MM::ActionType eAct) pProp->Get(gamma); FeatureValue.featurevalue = (float)gamma; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (set gamma): "); } else if (eAct == MM::BeforeGet) { if (!dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (get gamma): "); pProp->Set((long)FeatureValue.featurevalue); } return DEVICE_OK; @@ -629,12 +659,12 @@ int CHamamatsu::OnOffset(MM::PropertyBase* pProp, MM::ActionType eAct) pProp->Get(lnOffset); FeatureValue.featurevalue = (float)lnOffset; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (set offset): "); } else if (eAct == MM::BeforeGet) { if (!dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (get offset): "); pProp->Set(FeatureValue.featurevalue); } return DEVICE_OK; @@ -655,12 +685,12 @@ int CHamamatsu::OnExtended(MM::PropertyBase* pProp, MM::ActionType eAct, long fe pProp->Get(value); FeatureValue.featurevalue = (float)value; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (set value): "); } else if (eAct == MM::BeforeGet) { if (!dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (get value): "); pProp->Set(FeatureValue.featurevalue); } return DEVICE_OK; @@ -681,7 +711,7 @@ int CHamamatsu::OnTemperature(MM::PropertyBase* pProp, MM::ActionType eAct) pProp->Get(dT); FeatureValue.featurevalue = (float)dT; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&FeatureValue, sizeof(DCAM_PARAM_FEATURE))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (set dT): "); } else if (eAct == MM::BeforeGet) { @@ -690,9 +720,12 @@ int CHamamatsu::OnTemperature(MM::PropertyBase* pProp, MM::ActionType eAct) unsigned int errCode = dcam_getlasterror(m_hDCAM, NULL, 0); // this function may not be supported in older cameras - if (errCode != DCAMERR_NOTSUPPORT) + if (errCode != DCAMERR_NOTSUPPORT) { + ostringstream os; + os << "Error in dcam_extended (get dT): " << errCode; + LogMessage(os.str().c_str()); return errCode; - else + } else FeatureValue.featurevalue = 0.0; // default to zero if function not supported } pProp->Set(FeatureValue.featurevalue); @@ -721,6 +754,14 @@ void CHamamatsu::GetName(char* name) const CDeviceUtils::CopyLimitedString(name, g_DeviceName); } +long CHamamatsu::ReportError(std::string message) { + long err = dcam_getlasterror(m_hDCAM, NULL, 0); + ostringstream os; + os << message << err; + LogMessage(os.str().c_str()); + return err; +} + /////////////////////////////////////////////////////////////////////////////// // Function name : CHamamatsu::Initialize // Description : Initialize the camera @@ -752,11 +793,33 @@ int CHamamatsu::Initialize() if (refCount_ == 0) { - if (!dcam_init(m_hDCAMModule, &lnCameras, NULL) || lnCameras < 1) - return DEVICE_NATIVE_MODULE_FAILED; + if (!dcam_init(m_hDCAMModule, &lnCameras, NULL) ) + return ERR_NO_CAMERA_FOUND; } refCount_++; + if (lnCameras < 1) { + LogMessage("No DCAM camera found"); + return ERR_NO_CAMERA_FOUND; + } + + // DCAM INFO + char moduleVersion [64] = "Unrecognized"; + if (!dcam_getmodelinfo(slot_, DCAM_IDSTR_MODULEVERSION, moduleVersion, sizeof(moduleVersion))) + LogMessage ("Error obtaining moduleVersion"); + else { + char msg[128] = "DCAM Module Version: "; + LogMessage (strcat(msg, moduleVersion)); + } + + // DCAM API INFO + char dcamAPIVersion [64] = "Unrecognized"; + if (!dcam_getmodelinfo(slot_, DCAM_IDSTR_MODULEVERSION, dcamAPIVersion, sizeof(dcamAPIVersion))) + LogMessage ("Error obtaining DCAMP API Version"); + else { + char msg[128] = "DCAM API Version: "; + LogMessage (strcat(msg, dcamAPIVersion)); + } // gather information about the equipment // ------------------------------------------ @@ -767,7 +830,7 @@ int CHamamatsu::Initialize() // verify buffer mode DWORD cap; if(!dcam_getcapability(m_hDCAM, &cap, DCAM_QUERYCAPABILITY_FUNCTIONS)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in getcapability: "); // We are currently not using user memory. Log it anyways if(!(cap & DCAM_CAPABILITY_USERMEMORY)) @@ -793,9 +856,13 @@ int CHamamatsu::Initialize() unsigned int errCode = dcam_getlasterror(m_hDCAM, NULL, 0); // this function may not be supported in older cameras - if (errCode != DCAMERR_NOTSUPPORT) + if (errCode != DCAMERR_NOTSUPPORT) { + LogMessage ("Error getting the Name of the camera"); return errCode; + } } + char msg[128] = "Camera Model: "; + LogMessage (strcat(msg, CameraName)); nRet = CreateProperty(MM::g_Keyword_CameraName, CameraName, MM::String, true); assert(nRet == DEVICE_OK); @@ -803,6 +870,8 @@ int CHamamatsu::Initialize() char CameraID[64]; if (!dcam_getstring(m_hDCAM, DCAM_IDSTR_CAMERAID, CameraID, sizeof(CameraID))) strcpy(CameraID, "Not available"); + strcpy (msg, "CameraID: "); + LogMessage (strcat(msg, CameraID)); nRet = CreateProperty(MM::g_Keyword_CameraID, CameraID, MM::String, true); assert(nRet == DEVICE_OK); @@ -810,6 +879,8 @@ int CHamamatsu::Initialize() char CameraVersion[64]; if (!dcam_getstring(m_hDCAM, DCAM_IDSTR_CAMERAVERSION, CameraVersion, sizeof(CameraVersion))) strcpy(CameraVersion, "Not available"); + strcpy (msg, "Camera Version: "); + LogMessage (strcat(msg, CameraVersion)); nRet = CreateProperty("Camera Version", CameraVersion, MM::String, true); assert(nRet == DEVICE_OK); @@ -817,6 +888,8 @@ int CHamamatsu::Initialize() char DriverVersion[64]; if (!dcam_getstring(m_hDCAM, DCAM_IDSTR_DRIVERVERSION, DriverVersion, sizeof(DriverVersion))) strcpy(DriverVersion, "Not available"); + strcpy (msg, "Driver version: "); + LogMessage (strcat(msg, DriverVersion)); nRet = CreateProperty("Driver Version", DriverVersion, MM::String, true); assert(nRet == DEVICE_OK); @@ -855,7 +928,7 @@ int CHamamatsu::Initialize() DWORD typeCap; if(!dcam_getcapability(m_hDCAM, &typeCap, DCAM_QUERYCAPABILITY_DATATYPE)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + ReportError("Error in getcapability QueryCapability_DataType"); vector pixelTypeValues; if(typeCap & ccDatatype_uint8) @@ -873,7 +946,7 @@ int CHamamatsu::Initialize() // scan mode int32_t maxSpeed; - if (IsScanModeSupported(maxSpeed)) + if (IsScanModeSupported(maxSpeed) && (maxSpeed > 1)) { pAct = new CPropertyAction (this, &CHamamatsu::OnScanMode); nRet = CreateProperty("ScanMode", "1", MM::Integer, false, pAct); @@ -884,8 +957,9 @@ int CHamamatsu::Initialize() os << (i+1); AddAllowedValue("ScanMode", os.str().c_str()); } - } else + } else { SetPropertyLimits("ScanMode", 1, maxSpeed); + } assert(nRet == DEVICE_OK); } @@ -1007,7 +1081,7 @@ int CHamamatsu::Initialize() if (nRet != DEVICE_OK) return nRet; - // We seen to need this on the Mac... + // We seem to need this on the Mac... SetProperty(MM::g_Keyword_Binning,"1"); m_bInitialized = true; @@ -1024,13 +1098,13 @@ int CHamamatsu::Shutdown() if (m_bInitialized) { if(!dcam_idle(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_idle: "); if (!dcam_freeframe(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_freeframe: "); if (!dcam_close(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_close: "); if (refCount_ > 0) { @@ -1038,7 +1112,7 @@ int CHamamatsu::Shutdown() if (refCount_== 0) { if (!dcam_uninit(m_hDCAMModule)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_uninit: "); } } else @@ -1160,7 +1234,7 @@ int CHamamatsu::SetROI(unsigned uX, unsigned uY, unsigned uXSize, unsigned uYSiz SubArrayInquiry.binning=lnBin_; if (!dcam_extended(m_hDCAM,DCAM_IDMSG_GETPARAM,(LPVOID)&SubArrayInquiry,sizeof(DCAM_PARAM_SUBARRAY_INQ))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (subarry_inq): "); DCAM_PARAM_SUBARRAY SubArrayValue; ZeroMemory((LPVOID)&SubArrayValue, sizeof(DCAM_PARAM_SUBARRAY)); @@ -1179,7 +1253,7 @@ int CHamamatsu::SetROI(unsigned uX, unsigned uY, unsigned uXSize, unsigned uYSiz SubArrayValue.vsize = newYSize; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_SETPARAM, (LPVOID)&SubArrayValue, sizeof(DCAM_PARAM_SUBARRAY))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (subarry): "); ret = ResizeImageBuffer(); if (ret != DEVICE_OK) @@ -1224,7 +1298,7 @@ int CHamamatsu::GetROI(unsigned& uX, unsigned& uY, unsigned& uXSize, unsigned& u SubArrayValue.hdr.id = (DWORD)DCAM_IDPARAM_SUBARRAY; if (!dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM,(LPVOID)&SubArrayValue, sizeof(DCAM_PARAM_SUBARRAY))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (subarry): "); uX = SubArrayValue.hpos; uY = SubArrayValue.vpos; @@ -1244,7 +1318,7 @@ int CHamamatsu::ClearROI() SubArrayInquiry.binning=lnBin_; if (!dcam_extended(m_hDCAM,DCAM_IDMSG_GETPARAM,(LPVOID)&SubArrayInquiry,sizeof(DCAM_PARAM_SUBARRAY_INQ))) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_extended (subarry_inq): "); // reset the frame int ret = SetROI(0, 0, SubArrayInquiry.hmax, SubArrayInquiry.vmax); @@ -1289,14 +1363,11 @@ int CHamamatsu::ResizeImageBuffer(long frameBufSize) // resize internal buffers SIZE imgSize; if (!dcam_getdatasize(m_hDCAM,&imgSize)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getdatasize: "); ccDatatype ccDataType; if (!dcam_getdatatype(m_hDCAM,&ccDataType)) - { - LogMessage("cam_getdatatype"); - return dcam_getlasterror(m_hDCAM, NULL, 0); - } + return ReportError("Error in dcam_getdatatype: "); #ifdef WIN32 // format the image buffer @@ -1332,48 +1403,33 @@ int CHamamatsu::ResizeImageBuffer(long frameBufSize) // setup the sequence capture mode if (!dcam_precapture(m_hDCAM, ccCapture_Sequence)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_precapture: "); // set a 3 frame sequence buffercapt //const long frameBufSize = 3; if (!dcam_freeframe(m_hDCAM)) - { - LogMessage("dcam_freeframe"); - return dcam_getlasterror(m_hDCAM, NULL, 0); - } + return ReportError("Error in dcam_freeframe: "); if (!dcam_allocframe(m_hDCAM, frameBufSize)) - { - LogMessage("dcam_allocframe"); - return dcam_getlasterror(m_hDCAM, NULL, 0); - } + return ReportError("Error in dcam_allocframe: "); long numFrames; if (!dcam_getframecount(m_hDCAM, &numFrames)) - { - LogMessage("dcam_getframecount"); - return dcam_getlasterror(m_hDCAM, NULL, 0); - } + return ReportError("Error in dcam_getframecount: "); if (numFrames != frameBufSize) return ERR_BUFFER_ALLOCATION_FAILED; DWORD dwDataBufferSize; if (!dcam_getdataframebytes(m_hDCAM, &dwDataBufferSize)) - { - LogMessage("dcam_getdataframebytes"); - return dcam_getlasterror(m_hDCAM, NULL, 0); - } + return ReportError("Error in dcam_getdataframebytes: "); if (img_.Height() * img_.Width() * img_.Depth() != dwDataBufferSize) return DEVICE_INTERNAL_INCONSISTENCY; // buffer sizes don't match ??? // start capture if (!dcam_capture(m_hDCAM)) - { - LogMessage("dcam_capture"); - return dcam_getlasterror(m_hDCAM, NULL, 0); - } + return ReportError("Error in dcam_capture: "); return DEVICE_OK; } @@ -1387,10 +1443,10 @@ int CHamamatsu::ShutdownImageBuffer() { // interrupt whatever the camera is currently doing if (!dcam_idle(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_idle: "); if (!dcam_freeframe(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_freeframe: "); return DEVICE_OK; } @@ -1418,7 +1474,13 @@ bool CHamamatsu::IsScanModeSupported(int32_t& maxSpeed) featureInquiry.hdr.iFlag = dcamparam_scanmodeinq_speedmax; featureInquiry.hdr.oFlag = 0; - if (dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM,(LPVOID)&featureInquiry, sizeof(DCAM_PARAM_SCANMODE_INQ)) == TRUE) { + // Kay Schink reported that dcam_extended failed with ScanMode whereas it worked with featureInquiry. Add the second test here to catch those issue (might hide the real problem though).. + DCAM_PARAM_SCANMODE ScanMode; + ZeroMemory((LPVOID)&ScanMode, sizeof(DCAM_PARAM_SCANMODE)); + ScanMode.hdr.cbSize = sizeof(DCAM_PARAM_SCANMODE); + ScanMode.hdr.id = (DWORD) DCAM_IDPARAM_SCANMODE; + + if (dcam_extended(m_hDCAM, DCAM_IDMSG_GETPARAM,(LPVOID)&featureInquiry, sizeof(DCAM_PARAM_SCANMODE_INQ)) == TRUE && dcam_extended(m_hDCAM,DCAM_IDMSG_GETPARAM, (LPVOID)&ScanMode, sizeof(DCAM_PARAM_SCANMODE)) == TRUE) { maxSpeed = featureInquiry.speedmax; return true; } @@ -1554,7 +1616,7 @@ int AcqSequenceThread::svc(void) double dExp; if (!dcam_getexposuretime(camera_->m_hDCAM, &dExp)) - return dcam_getlasterror(camera_->m_hDCAM, NULL, 0); + return dcam_getlasterror(camera_->m_hDCAM, NULL, 0); do { @@ -1642,8 +1704,8 @@ int CHamamatsu::StartSequenceAcquisition(long numImages, double interval_ms) ret = GetProperty(MM::g_Keyword_ReadoutTime, rT); readoutTime = atof(rT); double dExp; - if (!dcam_getexposuretime(m_hDCAM, &dExp)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + if (!dcam_getexposuretime(m_hDCAM, &dExp)) + return ReportError("Error in dcam_getexposuretime: "); os.clear(); double interval = max(readoutTime, dExp * 1000); os << interval; @@ -1681,10 +1743,10 @@ int CHamamatsu::StopSequenceAcquisition() { LogMessage("Stopped sequence acquisition"); if (!dcam_idle(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_idle: "); if (!dcam_freeframe(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_freeframe "); seqThread_->Stop(); acquiring_ = false; @@ -1720,12 +1782,12 @@ int CHamamatsu::PushImage() long lastImage; long frameCount; if (!dcam_gettransferinfo(m_hDCAM, &lastImage, &frameCount)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_gettransferinfo: "); if (frameCount <= frameCount_) { // there is no new frame, wait for a new one double dExp; if (!dcam_getexposuretime(m_hDCAM, &dExp)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_getexposuretime: "); long lnTimeOut = (long) ((dExp + 5.0) * 1000.0); DWORD dwEvent = DCAM_EVENT_FRAMEEND; if (!dcam_wait(m_hDCAM, &dwEvent, lnTimeOut, NULL)) @@ -1736,7 +1798,7 @@ int CHamamatsu::PushImage() //return lnLastErr; } if (!dcam_gettransferinfo(m_hDCAM, &lastImage, &frameCount)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_gettransferinfo: "); } if ( (frameCount - frameCount_) >= frameBufSize_) @@ -1759,7 +1821,7 @@ int CHamamatsu::PushImage() long sRow; //dcam_lockdata(m_hDCAM, &imgPtr, &sRow, frameCount_); if (!dcam_lockdata(m_hDCAM, &imgPtr, &sRow, lastImage)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_loackdata: "); // process image MM::ImageProcessor* ip = GetCoreCallback()->GetImageProcessor(this); @@ -1779,7 +1841,7 @@ int CHamamatsu::PushImage() return ret; if (!dcam_unlockdata(m_hDCAM)) - return dcam_getlasterror(m_hDCAM, NULL, 0); + return ReportError("Error in dcam_unlockdata: "); return DEVICE_OK; } diff --git a/DeviceAdapters/Hamamatsu/Hamamatsu.h b/DeviceAdapters/Hamamatsu/Hamamatsu.h index 53367f7d3d..82831828a2 100644 --- a/DeviceAdapters/Hamamatsu/Hamamatsu.h +++ b/DeviceAdapters/Hamamatsu/Hamamatsu.h @@ -59,6 +59,7 @@ typedef void* LPVOID; #define ERR_INCOMPLETE_SNAP_IMAGE_CYCLE 1002 #define ERR_BUSY_ACQUIRING 1003 #define ERR_INTERNAL_BUFFER_FULL 1004 +#define ERR_NO_CAMERA_FOUND 1005 // forward declaration class AcqSequenceThread; @@ -107,6 +108,7 @@ class CHamamatsu : public CCameraBase int OnBinning(MM::PropertyBase* pProp, MM::ActionType eAct); int OnTrigPolarity(MM::PropertyBase* pProp, MM::ActionType eAct); int OnTrigMode(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnOutTrigPolarity(MM::PropertyBase* pProp, MM::ActionType eAct); int OnExposure(MM::PropertyBase* pProp, MM::ActionType eAct); int OnExtended(MM::PropertyBase* pProp, MM::ActionType eAct, long featureId); int OnGain(MM::PropertyBase* pProp, MM::ActionType eAct); @@ -132,6 +134,7 @@ class CHamamatsu : public CCameraBase bool IsFeatureSupported(int featureId); bool IsScanModeSupported(int32_t& maxSpeed); bool IsPropertySupported(DCAM_PROPERTYATTR& propAttr, long property); + long ReportError(std::string message); int SetAvailableTriggerModes(DWORD cap); int SetAllowedBinValues(DWORD cap); int SetAllowedTrigModeValues(DWORD cap); diff --git a/DeviceAdapters/Hamamatsu/Makefile.am b/DeviceAdapters/Hamamatsu/Makefile.am index d30584779a..d65e05a1bc 100644 --- a/DeviceAdapters/Hamamatsu/Makefile.am +++ b/DeviceAdapters/Hamamatsu/Makefile.am @@ -9,5 +9,9 @@ Hamamatsu_la_LDFLAGS = -module $(DCAMFRAMEWORKS) install: cp .libs/Hamamatsu.so $(IJPATH)/$(MMPREFIX)Hamamatsu +install-strip: + cp .libs/Hamamatsu.so $(IJPATH)/$(MMPREFIX)Hamamatsu + strip -x $(IJPATH)/$(MMPREFIX)Hamamatsu + EXTRA_DIST = Hamamatsu.vcproj license.txt diff --git a/DeviceAdapters/Makefile.am b/DeviceAdapters/Makefile.am index 1939c0ddda..d7e5e22995 100644 --- a/DeviceAdapters/Makefile.am +++ b/DeviceAdapters/Makefile.am @@ -9,12 +9,12 @@ endif if BUILD_QCAM QCAM = QCam endif -##if BUILD_TE2000 -## TE2000 = NikonTE2000 -##endif -if BUILD_AZ100 - AZ100 = NikonAZ100 +if BUILD_TE2000 + TE2000 = NikonTE2000 endif +##if BUILD_AZ100 +## AZ100 = NikonAZ100 +##endif if BUILD_DC1394 DC1394 = dc1394 endif @@ -28,5 +28,5 @@ if BUILD_USBMANAGER USBMANAGER = USBManager endif -SUBDIRS = AOTF Andor ASIFW1000 ASIStage DAZStage DTOpenLayer DemoCamera DemoStreamingCamera SerialManager SerialManagerUNIX Ludl LudlLow PI PI_GCS Prior ParallelPort Pecon Sensicam ZeissCAN ZeissCAN29 Vincent Conix $(HAMAMATSU) $(PVCAM) $(QCAM) $(TE2000) $(AZ100) $(K8055) $(K8061) $(USBMANAGER) Nikon StanfordPhotonics SpectralLMM5 SutterLambda $(DC1394) Yokogawa +SUBDIRS = AOTF Andor ASIFW1000 ASIStage DAZStage DTOpenLayer DemoCamera DemoStreamingCamera SerialManager SerialManagerUNIX Ludl LudlLow PI PI_GCS Prior ParallelPort Pecon Sensicam ZeissCAN ZeissCAN29 Vincent Conix $(HAMAMATSU) $(PVCAM) $(QCAM) NikonTE2000 $(TE2000) $(AZ100) $(K8055) $(K8061) $(USBMANAGER) Nikon StanfordPhotonics SpectralLMM5 SutterLambda $(DC1394) Yokogawa diff --git a/DeviceAdapters/NikonTE2000/NikonTE2000.cpp b/DeviceAdapters/NikonTE2000/NikonTE2000.cpp index b9229cd547..97eb74e98e 100644 --- a/DeviceAdapters/NikonTE2000/NikonTE2000.cpp +++ b/DeviceAdapters/NikonTE2000/NikonTE2000.cpp @@ -42,6 +42,7 @@ const char* g_EpiShutterName = "Epi-Shutter"; const char* g_UniblitzShutterName = "Uniblitz-Shutter"; const char* g_FocusName = "Focus"; const char* g_AutoFocusName = "PerfectFocus"; +const char* g_PFSOffsetName = "PFS-Offset"; const char* g_HubName = "TE2000"; const char* g_Control = "Control"; const char* g_ControlMicroscope = "Microscope"; @@ -96,6 +97,7 @@ MODULE_API void InitializeModuleData() AddAvailableDeviceName(g_EpiShutterName, "Epi-fluorescence shutter"); AddAvailableDeviceName(g_UniblitzShutterName, "Uniblitz shutter"); AddAvailableDeviceName(g_AutoFocusName, "PFS autofocus device"); + AddAvailableDeviceName(g_PFSOffsetName, "PFS Offset Lens"); } MODULE_API MM::Device* CreateDevice(const char* deviceName) @@ -148,6 +150,10 @@ MODULE_API MM::Device* CreateDevice(const char* deviceName) { return new PerfectFocus; } + else if (strcmp(deviceName, g_PFSOffsetName) == 0) + { + return new PFSOffset; + } return 0; } @@ -780,11 +786,11 @@ int OpticalPath::Initialize() return ret; // set allowed states + AddAllowedValue(MM::g_Keyword_State, "0"); AddAllowedValue(MM::g_Keyword_State, "1"); AddAllowedValue(MM::g_Keyword_State, "2"); AddAllowedValue(MM::g_Keyword_State, "3"); AddAllowedValue(MM::g_Keyword_State, "4"); - AddAllowedValue(MM::g_Keyword_State, "5"); // Label @@ -795,11 +801,11 @@ int OpticalPath::Initialize() return ret; // create default positions and labels - SetPositionLabel(1, "Monitor(100)"); - SetPositionLabel(2, "Monitor(20)-Right(80)"); - SetPositionLabel(3, "Bottom(100)"); - SetPositionLabel(4, "Monitor(20)-Front(80)"); - SetPositionLabel(5, "Left(100)"); + SetPositionLabel(0, "Monitor(100)"); + SetPositionLabel(1, "Monitor(20)-Right(80)"); + SetPositionLabel(2, "Bottom(100)"); + SetPositionLabel(3, "Monitor(20)-Front(80)"); + SetPositionLabel(4, "Left(100)"); ret = UpdateStatus(); if (ret != DEVICE_OK) @@ -831,12 +837,13 @@ int OpticalPath::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) int ret = g_hub.GetOpticalPathPosition(*this, *GetCoreCallback(), pos); if (ret != DEVICE_OK) return ret; - pProp->Set((long)pos); + pProp->Set((long)pos - 1); } else if (eAct == MM::AfterSet) { long pos; pProp->Get(pos); + pos += 1; if (pos > (long)numPos_ || pos < 1) { // restore current position @@ -844,7 +851,7 @@ int OpticalPath::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) int ret = g_hub.GetOpticalPathPosition(*this, *GetCoreCallback(), oldPos); if (ret != DEVICE_OK) return ret; - pProp->Set((long)oldPos); // revert + pProp->Set((long)oldPos - 1); // revert return ERR_UNKNOWN_POSITION; } // apply the value @@ -1620,3 +1627,186 @@ int GetFocusScore(double& /*score*/) { return DEVICE_UNSUPPORTED_COMMAND; } + +/////////////////////////////////////////////////////////////////////////////// +// PFSOffset implementation +// ~~~~~~~~~~~~~~~~~~~~~~~~~ + +PFSOffset::PFSOffset() : + stepSize_nm_(0.5), + busy_(false), + initialized_(false), + lowerLimit_(-20000.0), + upperLimit_(20000.0) +{ + InitializeDefaultErrorMessages(); + SetErrorText(ERR_NOT_CONNECTED, "Not connected with the hardware"); + SetErrorText(ERR_PFS_NOT_CONNECTED, "No Perfect Focus found"); +} + +PFSOffset::~PFSOffset() +{ + Shutdown(); +} + +void PFSOffset::GetName(char* Name) const +{ + CDeviceUtils::CopyLimitedString(Name, g_PFSOffsetName); +} + +int PFSOffset::Initialize() +{ + // PFS Version (this also functions as a check that the PF is attached and switched ON + string version; + int ret = g_hub.GetPFocusVersion(*this, *GetCoreCallback(), version); + if (ret != DEVICE_OK) + return ERR_PFS_NOT_CONNECTED; + + // set property list + // ----------------- + + // Name + ret = CreateProperty(MM::g_Keyword_Name, g_PFSOffsetName, MM::String, true); + if (DEVICE_OK != ret) + return ret; + + // Description + ret = CreateProperty(MM::g_Keyword_Description, "Nikon TE2000 PFS Offset lens", MM::String, true); + if (DEVICE_OK != ret) + return ret; + + // Position + // -------- + CPropertyAction* pAct = new CPropertyAction (this, &PFSOffset::OnPosition); + ret = CreateProperty(MM::g_Keyword_Position, "0.0", MM::Float, false, pAct); + if (ret != DEVICE_OK) + return ret; + + // StepSize + // -------- + const char* stepSizeName = "PFSFocusStepSize_(nm)"; + pAct = new CPropertyAction (this, &PFSOffset::OnStepSize); + ret = CreateProperty(stepSizeName, "0.5", MM::Float, false, pAct, true); + if (ret != DEVICE_OK) + return ret; + + ret = SetPropertyLimits(stepSizeName, 0, 10); + + ret = UpdateStatus(); + if (ret != DEVICE_OK) + return ret; + + initialized_ = true; + + return DEVICE_OK; +} + +int PFSOffset::Shutdown() +{ + if (initialized_) + { + initialized_ = false; + } + return DEVICE_OK; +} + +bool PFSOffset::Busy() +{ + // All calls in TEHub for PFSOffset are blocking... + return false; +} + +int PFSOffset::SetPositionUm(double pos) +{ + return SetProperty(MM::g_Keyword_Position, CDeviceUtils::ConvertToString(pos)); +} + +int PFSOffset::GetPositionUm(double& pos) +{ + char buf[MM::MaxStrLength]; + int ret = GetProperty(MM::g_Keyword_Position, buf); + if (ret != DEVICE_OK) + return ret; + pos = atof(buf); + return DEVICE_OK; +} + +int PFSOffset::SetPositionSteps(long steps) +{ + int ret = g_hub.SetPFocusPosition(*this, *GetCoreCallback(), steps); + if (ret != 0) + return ret; +} + +int PFSOffset::GetPositionSteps(long& steps) +{ + return g_hub.GetPFocusPosition(*this, *GetCoreCallback(), (int&) steps); +} +/* + if (ret != 0) + return ret; + pProp->Set((double) (pos * ((double)stepSize_nm_ / 1000)) ); + if (stepSize_nm_ == 0.0) + return DEVICE_UNSUPPORTED_COMMAND; + double posUm; + int ret = GetPositionUm(posUm); + if (ret != DEVICE_OK) + return ret; + + steps = (long)(posUm / ((double)stepSize_nm_ / 1000) + 0.5); + return DEVICE_OK; +} +*/ + +int PFSOffset::SetOrigin() +{ + return DEVICE_UNSUPPORTED_COMMAND; +} + +/////////////////////////////////////////////////////////////////////////////// +// Action handlers +/////////////////////////////////////////////////////////////////////////////// + +int PFSOffset::OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::BeforeGet) + { + long pos; + int ret = GetPositionSteps(pos); + if (ret != DEVICE_OK) + return ret; + pProp->Set((double) (pos * ((double)stepSize_nm_ / 1000)) ); + } + else if (eAct == MM::AfterSet) + { + double pos; + pProp->Get(pos); + long focusPos = (long)(pos/((double)stepSize_nm_ / 1000.0) + 0.5); + return SetPositionSteps(focusPos); + } + + return DEVICE_OK; +} + + +/* + * + */ +int PFSOffset::OnStepSize(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::BeforeGet) + { + // There is no way to get a stepsize from the controller. + ostringstream os; + os << stepSize_nm_; + pProp->Set(os.str().c_str()); + } + else if (eAct == MM::AfterSet) + { + string stepSize; + pProp->Get(stepSize); + stepSize_nm_ = atof(stepSize.c_str()); + } + + return DEVICE_OK; +} diff --git a/DeviceAdapters/NikonTE2000/NikonTE2000.h b/DeviceAdapters/NikonTE2000/NikonTE2000.h index 3e4d9bcdc0..14b4e0ac42 100644 --- a/DeviceAdapters/NikonTE2000/NikonTE2000.h +++ b/DeviceAdapters/NikonTE2000/NikonTE2000.h @@ -356,4 +356,45 @@ class PerfectFocus : public CAutoFocusBase private: bool initialized_; }; + +class PFSOffset : public CStageBase +{ +public: + PFSOffset(); + ~PFSOffset(); + + bool Busy(); + void GetName(char* pszName) const; + + int Initialize(); + int Shutdown(); + + // Stage API + virtual int SetPositionUm(double pos); + virtual int GetPositionUm(double& pos); + virtual double GetStepSize() const {return (double)stepSize_nm_/1000;} + virtual int SetPositionSteps(long steps) ; + // virtual int SetRelativePositionUm(double pos) ; + virtual int GetPositionSteps(long& steps); + virtual int SetOrigin(); + virtual int GetLimits(double& lower, double& upper) + { + lower = lowerLimit_; + upper = upperLimit_; + return DEVICE_OK; + } + + // action interface + // ---------------- + int OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnStepSize(MM::PropertyBase* pProp, MM::ActionType eAct); + +private: + double stepSize_nm_; + bool busy_; + bool initialized_; + double lowerLimit_; + double upperLimit_; +}; + #endif //_NIKON_TE2000_H_ diff --git a/DeviceAdapters/NikonTE2000/TEHub.cpp b/DeviceAdapters/NikonTE2000/TEHub.cpp index e3a0c89129..0db0d04b78 100644 --- a/DeviceAdapters/NikonTE2000/TEHub.cpp +++ b/DeviceAdapters/NikonTE2000/TEHub.cpp @@ -580,6 +580,72 @@ int TEHub::GetPFocusVersion(MM::Device& device, MM::Core& core, std::string& ver return DEVICE_OK; } +/* + * Sets Absolute PFS Ofsset lens focus position in Steps + */ +int TEHub::SetPFocusPosition(MM::Device& device, MM::Core& core, int pos) +{ + ostringstream os; + os << "TRN1cOLA" << pos; + + // send command + int ret = ExecuteCommand(device, core, "c", os.str().c_str()); + if (ret != DEVICE_OK) + return ret; + + string value; + ret = ParseResponse(device, core, "TRN", value); + if (ret != DEVICE_OK) + return ret; + + return DEVICE_OK; +} + +/* + * Sets Relative PFS Ofsset lens focus position in Steps + */ +int TEHub::SetRelativePFocusPosition(MM::Device& device, MM::Core& core, int pos) +{ + ostringstream os; + os << "TRN1cOLB" << pos; + + // send command + int ret = ExecuteCommand(device, core, "c", os.str().c_str()); + if (ret != DEVICE_OK) + return ret; + + string value; + ret = ParseResponse(device, core, "TRN", value); + if (ret != DEVICE_OK) + return ret; + + return DEVICE_OK; +} + +/* + * Returns PFS Ofsset lens focus position in Steps + */ +int TEHub::GetPFocusPosition(MM::Device& device, MM::Core& core, int& pos) +{ + ostringstream os; + os << "TRN1rOLR"; + + // send command + int ret = ExecuteCommand(device, core, "c", os.str().c_str()); + if (ret != DEVICE_OK) + return ret; + + string value; + ret = ParseResponse(device, core, "TRN", value); + if (ret != DEVICE_OK) + return ret; + + pos = atoi(value.c_str()); + + return DEVICE_OK; +} + + /* * Epi-illumination Shutter */ diff --git a/DeviceAdapters/NikonTE2000/TEHub.h b/DeviceAdapters/NikonTE2000/TEHub.h index 233abbce3c..d3eedd2429 100644 --- a/DeviceAdapters/NikonTE2000/TEHub.h +++ b/DeviceAdapters/NikonTE2000/TEHub.h @@ -96,6 +96,10 @@ class TEHub int GetPFocusStatus(MM::Device& device, MM::Core& core, int& status); int GetPFocusVersion(MM::Device& device, MM::Core& core, std::string& version); + int SetPFocusPosition(MM::Device& device, MM::Core& core, int pos); + int SetRelativePFocusPosition(MM::Device& device, MM::Core& core, int pos); + int GetPFocusPosition(MM::Device& device, MM::Core& core, int& pos); + private: int ExecuteCommand(MM::Device& device, MM::Core& core, const char* type, const char* command); int ParseResponse(MM::Device& device, MM::Core& core, const char* cmdId, std::string& value); diff --git a/DeviceAdapters/SerialManager/SerialManager.cpp b/DeviceAdapters/SerialManager/SerialManager.cpp index 263dcbdd43..477d718728 100644 --- a/DeviceAdapters/SerialManager/SerialManager.cpp +++ b/DeviceAdapters/SerialManager/SerialManager.cpp @@ -60,6 +60,11 @@ const char* g_Handshaking_Off = "Off"; const char* g_Handshaking_Hardware = "Hardware"; const char* g_Handshaking_Software = "Software"; +const char* g_Parity_None = "None"; +const char* g_Parity_Odd = "Odd"; +const char* g_Parity_Even = "Even"; +const char* g_Parity_Mark = "Mark"; +const char* g_Parity_Space = "Space"; #ifdef WIN32 BOOL APIENTRY DllMain( HANDLE /*hModule*/, @@ -175,7 +180,8 @@ SerialPort::SerialPort() : portTimeoutMs_(2000.0), answerTimeoutMs_(500), transmitCharWaitMs_(0.0), - stopBits_(g_StopBits_1) + stopBits_(g_StopBits_1), + parity_(g_Parity_None) { port_ = new CSerial(); @@ -221,9 +227,16 @@ SerialPort::SerialPort() : AddAllowedValue(MM::g_Keyword_StopBits, g_StopBits_2, (long)CSerial::EStop2); // parity - ret = CreateProperty(MM::g_Keyword_Parity, "None", MM::String, true); + CPropertyAction* pActParity = new CPropertyAction (this, &SerialPort::OnParity); + ret = CreateProperty(MM::g_Keyword_Parity, g_Parity_None, MM::String, false, pActParity, true); assert(ret == DEVICE_OK); + AddAllowedValue(MM::g_Keyword_Parity, g_Parity_None, (long)CSerial::EParNone); + AddAllowedValue(MM::g_Keyword_Parity, g_Parity_Odd, (long)CSerial::EParOdd); + AddAllowedValue(MM::g_Keyword_Parity, g_Parity_Even, (long)CSerial::EParEven); + AddAllowedValue(MM::g_Keyword_Parity, g_Parity_Mark, (long)CSerial::EParMark); + AddAllowedValue(MM::g_Keyword_Parity, g_Parity_Space, (long)CSerial::EParSpace); + // handshaking CPropertyAction* pActHandshaking = new CPropertyAction (this, &SerialPort::OnHandshaking); ret = CreateProperty(MM::g_Keyword_Handshaking, "Off", MM::String, false, pActHandshaking, true); @@ -281,11 +294,14 @@ int SerialPort::Initialize() int ret = GetPropertyData(MM::g_Keyword_StopBits, stopBits_.c_str(), sb); assert(ret == DEVICE_OK); + long parity; + ret = GetPropertyData(MM::g_Keyword_Parity, parity_.c_str(), parity); + long baud; ret = GetCurrentPropertyData(MM::g_Keyword_BaudRate, baud); assert(ret == DEVICE_OK); - long lastError = port_->Setup((CSerial::EBaudrate)baud, CSerial::EData8, CSerial::EParNone, (CSerial::EStopBits)sb); + long lastError = port_->Setup((CSerial::EBaudrate)baud, CSerial::EData8, (CSerial::EParity)parity, (CSerial::EStopBits)sb); if (lastError != ERROR_SUCCESS) return ERR_SETUP_FAILED; @@ -551,6 +567,25 @@ int SerialPort::OnStopBits(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_OK; } +int SerialPort::OnParity(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::BeforeGet) + { + pProp->Set(parity_.c_str()); + } + else if (eAct == MM::AfterSet) + { + if (initialized_) + { + pProp->Set(parity_.c_str()); + return ERR_PORT_CHANGE_FORBIDDEN; + } + pProp->Get(parity_); + } + + return DEVICE_OK; +} + int SerialPort::OnBaud(MM::PropertyBase* /*pProp*/, MM::ActionType eAct) { if (eAct == MM::BeforeGet) diff --git a/DeviceAdapters/SerialManager/SerialManager.h b/DeviceAdapters/SerialManager/SerialManager.h index b7608fa94a..54748249ee 100644 --- a/DeviceAdapters/SerialManager/SerialManager.h +++ b/DeviceAdapters/SerialManager/SerialManager.h @@ -73,6 +73,7 @@ class SerialPort : public CSerialBase // action interface // ---------------- int OnStopBits(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnParity(MM::PropertyBase* pProp, MM::ActionType eAct); int OnHandshaking(MM::PropertyBase* pProp, MM::ActionType eAct); int OnBaud(MM::PropertyBase* pProp, MM::ActionType eAct); int OnTimeout(MM::PropertyBase* pProp, MM::ActionType eAct); @@ -96,6 +97,7 @@ class SerialPort : public CSerialBase std::map baudList_; std::string stopBits_; + std::string parity_; }; class SerialManager diff --git a/DeviceAdapters/SerialManagerUNIX/SerialManager.h b/DeviceAdapters/SerialManagerUNIX/SerialManager.h index 60b9a8df57..2f7fbc00b8 100644 --- a/DeviceAdapters/SerialManagerUNIX/SerialManager.h +++ b/DeviceAdapters/SerialManagerUNIX/SerialManager.h @@ -123,7 +123,7 @@ class MDSerialPort : public CSerialBase std::vector availablePorts_; SerialPortLister* portLister; - int MDSerialPort::HandleError(int errorCode); + int HandleError(int errorCode); }; diff --git a/DeviceAdapters/SerialManagerUNIX/SerialPort.cpp b/DeviceAdapters/SerialManagerUNIX/SerialPort.cpp index ec4547ccca..8c0d5bafa7 100644 --- a/DeviceAdapters/SerialManagerUNIX/SerialPort.cpp +++ b/DeviceAdapters/SerialManagerUNIX/SerialPort.cpp @@ -661,8 +661,11 @@ SerialPort::SerialPortImpl::Open() // Start assembling the new port settings. // termios port_settings ; + /* bzero( &port_settings, sizeof( port_settings ) ) ; + */ + memset(&port_settings, 0, sizeof(port_settings)); // // Enable the receiver (CREAD) and ignore modem control lines diff --git a/DeviceAdapters/SerialManagerUNIX/SerialPort.h b/DeviceAdapters/SerialManagerUNIX/SerialPort.h index e53dec87b3..b49a3ed19f 100644 --- a/DeviceAdapters/SerialManagerUNIX/SerialPort.h +++ b/DeviceAdapters/SerialManagerUNIX/SerialPort.h @@ -22,6 +22,8 @@ #include +#include +#include #include #include #include @@ -92,7 +94,7 @@ class SerialPort enum FlowControl { FLOW_CONTROL_HARD, - // FLOW_CONTROL_SOFT, + FLOW_CONTROL_SOFT, FLOW_CONTROL_NONE, FLOW_CONTROL_DEFAULT = FLOW_CONTROL_NONE } ; diff --git a/DeviceAdapters/configure.in b/DeviceAdapters/configure.in index 00de333119..5494321c40 100644 --- a/DeviceAdapters/configure.in +++ b/DeviceAdapters/configure.in @@ -58,8 +58,11 @@ then *-*-linux*) if test -r /usr/local/lib/libACE.la ; then LIBACE="/usr/local/lib/libACE.la" - else - AC_MSG_ERROR([not found, download from http://deuce.doc.wustl.edu/Download.html, build and install (cd ACE_wrappers \ mkdir build \ cd build \ ../configure \ make \ make install ) and rerun configure]) + if test -r /usr/lib/libACE.a ; then + LIBACE="/usr/lib/libACE.a" + else + AC_MSG_ERROR([not found, download from http://deuce.doc.wustl.edu/Download.html, build and install (cd ACE_wrappers \ mkdir build \ cd build \ ../configure \ make \ make install ) and rerun configure]) + fi fi ;; *-*-darwin*) @@ -148,13 +151,13 @@ AC_SUBST(LIBUSB) # Only build the Nikon TE2000 when the code is there AM_CONDITIONAL([BUILD_TE2000],[test -f "NikonTE2000/NikonTE2000.h"]) if test -f "NikonTE2000/NikonTE2000.h"; then - TE2000=NikonTE2000 + # TE2000=NikonTE2000 TE2000MAKEFILE="NikonTE2000/Makefile" else - TE2000= + # TE2000= TE2000MAKEFILE= fi -AC_SUBST(TE2000) +#AC_SUBST(TE2000) # Only build the Nikon AZ100 when the code is there AM_CONDITIONAL([BUILD_AZ100],[test -f "NikonAZ100/NikonAZ100.h"]) @@ -259,7 +262,5 @@ AC_SUBST(IJPATH) AC_HEADER_STDC AC_CHECK_FUNCS([memset]) - -# AC_CONFIG_FILES([Makefile]) -AC_CONFIG_FILES(Makefile NikonTE2000/Makefile NikonAZ100/Makefile AOTF/Makefile Andor/Makefile ASIFW1000/Makefile ASIStage/Makefile DAZStage/Makefile DTOpenLayer/Makefile DemoCamera/Makefile DemoStreamingCamera/Makefile SerialManager/Makefile SerialManagerUNIX/Makefile USBManager/Makefile Ludl/Makefile LudlLow/Makefile ZeissCAN/Makefile ZeissCAN29/Makefile Vincent/Makefile Conix/Makefile K8055/Makefile K8061/Makefile Hamamatsu/Makefile PVCAM/Makefile Nikon/Makefile $TE2000MAKEFILE $AZ100MAKEFILE ParallelPort/Makefile Pecon/Makefile Sensicam/Makefile StanfordPhotonics/Makefile SpectralLMM5/Makefile SutterLambda/Makefile Prior/Makefile PI/Makefile PI_GCS/Makefile dc1394/Makefile QCam/Makefile Yokogawa/Makefile $TESTMAKEFILE) +AC_CONFIG_FILES(Makefile AOTF/Makefile Andor/Makefile ASIFW1000/Makefile ASIStage/Makefile DAZStage/Makefile DTOpenLayer/Makefile DemoCamera/Makefile DemoStreamingCamera/Makefile SerialManager/Makefile SerialManagerUNIX/Makefile USBManager/Makefile Ludl/Makefile LudlLow/Makefile ZeissCAN/Makefile ZeissCAN29/Makefile Vincent/Makefile Conix/Makefile K8055/Makefile K8061/Makefile Hamamatsu/Makefile PVCAM/Makefile Nikon/Makefile NikonTE2000/Makefile $AZ100MAKEFILE ParallelPort/Makefile Pecon/Makefile Sensicam/Makefile StanfordPhotonics/Makefile SpectralLMM5/Makefile SutterLambda/Makefile Prior/Makefile PI/Makefile PI_GCS/Makefile dc1394/Makefile QCam/Makefile Yokogawa/Makefile $TESTMAKEFILE) AC_OUTPUT diff --git a/MMCore/Configuration.cpp b/MMCore/Configuration.cpp index 7db6203a08..14e7bfc010 100644 --- a/MMCore/Configuration.cpp +++ b/MMCore/Configuration.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include using namespace std; diff --git a/MMCore/MMCore.cpp b/MMCore/MMCore.cpp index c1a250ada7..a18c998c42 100644 --- a/MMCore/MMCore.cpp +++ b/MMCore/MMCore.cpp @@ -364,7 +364,7 @@ vector CMMCore::getAvailableDeviceDescriptions(const char* library) thro /** * Get type information for available devices from the specified library. */ -vector CMMCore::getAvailableDeviceTypes(const char* library) throw (CMMError) +vector CMMCore::getAvailableDeviceTypes(const char* library) throw (CMMError) { try { @@ -782,7 +782,7 @@ void CMMCore::initializeDevice(const char* label) throw (CMMError) void CMMCore::updateSystemStateCache() { stateCache_ = getSystemState(); - CORE_LOG("Syestem state cache updated.\n"); + CORE_LOG("System state cache updated.\n"); } /** diff --git a/MMCore/MMCore.h b/MMCore/MMCore.h index 51e1cc0f9e..5a76c9d825 100644 --- a/MMCore/MMCore.h +++ b/MMCore/MMCore.h @@ -56,6 +56,7 @@ #endif #include +#include #include #include #include @@ -131,7 +132,7 @@ friend class CoreCallback; */ std::vector getAvailableDevices(const char* library) throw (CMMError); std::vector getAvailableDeviceDescriptions(const char* library) throw (CMMError); - std::vector getAvailableDeviceTypes(const char* library) throw (CMMError); + std::vector getAvailableDeviceTypes(const char* library) throw (CMMError); /** @name Generic device interface * API guaranteed to work for all devices. @@ -303,17 +304,17 @@ friend class CoreCallback; * API for controlling X, Y and Z stages */ //@ { - void setPosition(const char* deviceName, double position) throw (CMMError); - double getPosition(const char* deviceName) const throw (CMMError); - void setRelativePosition(const char* deviceName, double d) throw (CMMError); - void setXYPosition(const char* deviceName, double x, double y) throw (CMMError); - void setRelativeXYPosition(const char* deviceName, double dx, double dy) throw (CMMError); - void getXYPosition(const char* deviceName, double &x, double &y) throw (CMMError); - double getXPosition(const char* deviceName) throw (CMMError); - double getYPosition(const char* deviceName) throw (CMMError); - void stop(const char* deviceName) throw (CMMError); - void home(const char* deviceName) throw (CMMError); - void setOriginXY(const char* deviceName) throw (CMMError); + void setPosition(const char* deviceLabel, double position) throw (CMMError); + double getPosition(const char* deviceLabel) const throw (CMMError); + void setRelativePosition(const char* deviceLabel, double d) throw (CMMError); + void setXYPosition(const char* deviceLabel, double x, double y) throw (CMMError); + void setRelativeXYPosition(const char* deviceLabel, double dx, double dy) throw (CMMError); + void getXYPosition(const char* deviceLabel, double &x, double &y) throw (CMMError); + double getXPosition(const char* deviceLabel) throw (CMMError); + double getYPosition(const char* deviceLabel) throw (CMMError); + void stop(const char* deviceLabel) throw (CMMError); + void home(const char* deviceLabel) throw (CMMError); + void setOriginXY(const char* deviceLabel) throw (CMMError); void setAdapterOriginXY(const char* deviceName, double x, double y) throw (CMMError); //@ } @@ -321,10 +322,10 @@ friend class CoreCallback; * API for serial ports */ //@ { - void setSerialPortCommand(const char* name, const char* command, const char* term) throw (CMMError); - std::string getSerialPortAnswer(const char* name, const char* term) throw (CMMError); - void writeToSerialPort(const char* name, const std::vector &data) throw (CMMError); - std::vector readFromSerialPort(const char* name) throw (CMMError); + void setSerialPortCommand(const char* deviceLabel, const char* command, const char* term) throw (CMMError); + std::string getSerialPortAnswer(const char* deviceLabel, const char* term) throw (CMMError); + void writeToSerialPort(const char* deviceLabel, const std::vector &data) throw (CMMError); + std::vector readFromSerialPort(const char* deviceLabel) throw (CMMError); //@ } /** @name " " diff --git a/MMCore/PluginManager.cpp b/MMCore/PluginManager.cpp index 694e13884a..dbc63a6db6 100644 --- a/MMCore/PluginManager.cpp +++ b/MMCore/PluginManager.cpp @@ -482,9 +482,9 @@ vector CPluginManager::GetAvailableDeviceDescriptions(const char* module /** * List all device types in the specified module. */ -vector CPluginManager::GetAvailableDeviceTypes(const char* moduleName) throw (CMMError) +vector CPluginManager::GetAvailableDeviceTypes(const char* moduleName) throw (CMMError) { - vector types; + vector types; HDEVMODULE hLib = LoadPluginLibrary(moduleName); CheckVersion(hLib); // verify that versions match @@ -512,17 +512,17 @@ vector CPluginManager::GetAvailableDeviceTypes(const char* moduleName) thro char deviceName[MM::MaxStrLength]; if (!hGetDeviceName(i, deviceName, MM::MaxStrLength)) { - types.push_back((int)MM::AnyType); + types.push_back((long)MM::AnyType); continue; } // instantiate the device MM::Device* pDevice = hCreateDeviceFunc(deviceName); if (pDevice == 0) - types.push_back((int)MM::AnyType); + types.push_back((long)MM::AnyType); else { - types.push_back((int)pDevice->GetType()); + types.push_back((long)pDevice->GetType()); // release device resources diff --git a/MMCore/PluginManager.h b/MMCore/PluginManager.h index 3947468bf7..98578b25fe 100644 --- a/MMCore/PluginManager.h +++ b/MMCore/PluginManager.h @@ -36,6 +36,7 @@ #endif #include +#include #include #include #include "../MMDevice/MMDeviceConstants.h" @@ -65,7 +66,7 @@ class CPluginManager static std::vector GetModules(const char* searchPath); static std::vector GetAvailableDevices(const char* moduleName) throw (CMMError); static std::vector GetAvailableDeviceDescriptions(const char* moduleName) throw (CMMError); - static std::vector GetAvailableDeviceTypes(const char* moduleName) throw (CMMError); + static std::vector GetAvailableDeviceTypes(const char* moduleName) throw (CMMError); // persistence std::string Serialize(); diff --git a/MMCoreJ_wrap/MMCoreJ.i b/MMCoreJ_wrap/MMCoreJ.i index 88fd1db416..cff61bced9 100644 --- a/MMCoreJ_wrap/MMCoreJ.i +++ b/MMCoreJ_wrap/MMCoreJ.i @@ -232,7 +232,6 @@ // intantiate STL mappings namespace std { %template(CharVector) vector; - %template(IntVector) vector; %template(LongVector) vector; %template(StrVector) vector; %template(pair_ss) pair; diff --git a/MMCoreJ_wrap/Makefile.am b/MMCoreJ_wrap/Makefile.am index ab7125b671..1fe783b7b9 100644 --- a/MMCoreJ_wrap/Makefile.am +++ b/MMCoreJ_wrap/Makefile.am @@ -54,6 +54,15 @@ install: EXTRA_DIST = license.txt MMCoreJ_wrap.vcproj +clean: + test -z "libMMCoreJ_wrap.la" || rm -f libMMCoreJ_wrap.la + rm -rf mmcorej/*.java mmcorej/*.class + rm -f MMCorej_wrap.cxx + rm -f "./so_locations" + rm -rf .libs _libs + rm -f *.o + rm -f *.lo + dist-hook: test -d $(distdir)/mmcorej || mkdir $(distdir)/mmcorej touch $(distdir)/mmcorej/empty.txt diff --git a/MMDevice/MMDevice.h b/MMDevice/MMDevice.h index 14d68f7806..c93da40410 100644 --- a/MMDevice/MMDevice.h +++ b/MMDevice/MMDevice.h @@ -42,6 +42,9 @@ #include "MMDeviceConstants.h" #include +#include +#include +#include #include diff --git a/MMDevice/Property.h b/MMDevice/Property.h index 2c8b3dc88e..a6f0289335 100644 --- a/MMDevice/Property.h +++ b/MMDevice/Property.h @@ -25,6 +25,8 @@ #include "MMDeviceConstants.h" #include +#include +#include #include #include diff --git a/Test_MMCore/Makefile.am b/Test_MMCore/Makefile.am index 2888111814..cabf025887 100644 --- a/Test_MMCore/Makefile.am +++ b/Test_MMCore/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = testCore -testCore_LDADD = ../MMCore/libMMCore.a ../MMDevice/.libs/libMMDevice.a $(LIBACE) +testCore_LDADD = ../MMCore/libMMCore.a ../MMDevice/.libs/libMMDevice.a $(LIBACE) $(LPTHREAD) testCore_SOURCES = Test_MMCore_Mac.cpp EXTRA_DIST = Test_MMCore.vcproj Test_MMCore.sln Test_MMCore.cpp diff --git a/Test_MMCore/Test_MMCore_Mac.cpp b/Test_MMCore/Test_MMCore_Mac.cpp index 527ab0e25f..44bc4532cc 100644 --- a/Test_MMCore/Test_MMCore_Mac.cpp +++ b/Test_MMCore/Test_MMCore_Mac.cpp @@ -38,7 +38,7 @@ void TestPCO(CMMCore& core); /** * Creates MMCore objects loads demo device and displays the status. */ -int main(int /* argc */, char* /*argv[]*/) +int main(int /* argc */, char** /*argv[]*/) { try { diff --git a/Test_Serial/Makefile.am b/Test_Serial/Makefile.am index 0d902fd7e8..97b95f9e12 100644 --- a/Test_Serial/Makefile.am +++ b/Test_Serial/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = testserial testserial_SOURCES = Test_Serial.cpp -testserial_LDADD = ../MMCore/libMMCore.a ../MMDevice/.libs/libMMDevice.a $(LIBACE) +testserial_LDADD = ../MMCore/libMMCore.a ../MMDevice/.libs/libMMDevice.a $(LIBACE) $(LPTHREAD) EXTRA_DIST = Test_Serial.vcproj Test_Serial.sln stdafx.cpp stdafx.h diff --git a/autofocus/AFOptionsDlgTB.java b/autofocus/AFOptionsDlgTB.java new file mode 100644 index 0000000000..d4561892cb --- /dev/null +++ b/autofocus/AFOptionsDlgTB.java @@ -0,0 +1,178 @@ +/**************************************************** + Thomas Boudier, MCU Université Paris 6, + UMR 7101 / IFR 83. Bat A 328, Jussieu. + Tel : 0144273578/2013 Fax : 01 44 27 25 08 +****************************************************/ +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JTextField; + +/** +* Description of the Class +* +*@author thomas +*@created 30 mai 2008 +*/ +public class AFOptionsDlgTB extends JDialog { + private final static long serialVersionUID = 0L; + + private JTextField sizeFirstField_; + private JTextField numFirstField_; + private JTextField sizeSecondField_; + private JTextField numSecondField_; + private JTextField cropSizeField_; + private JTextField thresField_; + private JTextField channelField1_; + private JTextField channelField2_; + + private AutofocusTB_ af_; + + + /** + * Create the dialog + * + *@param af Description of the Parameter + */ + public AFOptionsDlgTB(AutofocusTB_ af) { + //constructor + super(); + System.out.println("AF Dialog"); + setModal(true); + af_ = af; + getContentPane().setLayout(null); + setTitle("Autofocus Options"); + setBounds(100, 100, 353, 260); + + channelField1_ = new JTextField(); + channelField1_.setBounds(136, 9, 90, 20); + getContentPane().add(channelField1_); + + final JLabel autofocusChannel1Label = new JLabel(); + autofocusChannel1Label.setText("Auto-focus channel 1"); + autofocusChannel1Label.setBounds(10, 13, 108, 14); + getContentPane().add(autofocusChannel1Label); + + sizeFirstField_ = new JTextField(); + sizeFirstField_.setBounds(136, 36, 90, 20); + getContentPane().add(sizeFirstField_); + + final JLabel sizeFirstLabel = new JLabel(); + sizeFirstLabel.setText("1st step size [um]"); + sizeFirstLabel.setBounds(10, 40, 91, 14); + getContentPane().add(sizeFirstLabel); + + numFirstField_ = new JTextField(); + numFirstField_.setBounds(136, 63, 90, 20); + getContentPane().add(numFirstField_); + + final JLabel numFirstLabel = new JLabel(); + numFirstLabel.setText("1st step number"); + numFirstLabel.setBounds(10, 67, 91, 14); + getContentPane().add(numFirstLabel); + + final JLabel autofocusChannel2Label = new JLabel(); + autofocusChannel2Label.setText("Auto-focus channel 2"); + autofocusChannel2Label.setBounds(10, 94, 108, 14); + getContentPane().add(autofocusChannel2Label); + + channelField2_ = new JTextField(); + channelField2_.setBounds(136, 90, 90, 20); + getContentPane().add(channelField2_); + + sizeSecondField_ = new JTextField(); + sizeSecondField_.setBounds(136, 117, 90, 20); + getContentPane().add(sizeSecondField_); + + final JLabel sizeSecondLabel = new JLabel(); + sizeSecondLabel.setText("2nd step size[um]"); + sizeSecondLabel.setBounds(10, 121, 91, 14); + getContentPane().add(sizeSecondLabel); + + numSecondField_ = new JTextField(); + numSecondField_.setBounds(136, 144, 90, 20); + getContentPane().add(numSecondField_); + + final JLabel numSecondLabel = new JLabel(); + numSecondLabel.setText("2nd step number"); + numSecondLabel.setBounds(10, 148, 91, 14); + getContentPane().add(numSecondLabel); + + cropSizeField_ = new JTextField(); + cropSizeField_.setBounds(136, 171, 90, 20); + getContentPane().add(cropSizeField_); + + final JLabel cropSizeLabel = new JLabel(); + cropSizeLabel.setText("Crop ratio"); + cropSizeLabel.setBounds(10, 174, 91, 14); + getContentPane().add(cropSizeLabel); + + thresField_ = new JTextField(); + thresField_.setBounds(136, 197, 90, 20); + getContentPane().add(thresField_); + + final JLabel thresLabel = new JLabel(); + thresLabel.setText("Threshold"); + thresLabel.setBounds(10, 200, 91, 14); + getContentPane().add(thresLabel); + + final JButton okButton = new JButton(); + okButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + applySettings(); + dispose(); + } + }); + okButton.setText("OK"); + okButton.setBounds(245, 13, 93, 23); + getContentPane().add(okButton); + + final JButton cancelButton = new JButton(); + cancelButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + cancelButton.setText("Cancel"); + cancelButton.setBounds(245, 39, 93, 23); + getContentPane().add(cancelButton); + + setupDisplay(); + } + + + /** + * Description of the Method + */ + private void setupDisplay() { + sizeFirstField_.setText(Double.toString(af_.SIZE_FIRST)); + numFirstField_.setText(Double.toString(af_.NUM_FIRST)); + sizeSecondField_.setText(Double.toString(af_.SIZE_SECOND)); + numSecondField_.setText(Double.toString(af_.NUM_SECOND)); + cropSizeField_.setText(Double.toString(af_.CROP_SIZE)); + thresField_.setText(Double.toString(af_.THRES)); + channelField1_.setText(af_.CHANNEL1); + channelField2_.setText(af_.CHANNEL2); + } + + + /** + * Description of the Method + */ + protected void applySettings() { + af_.SIZE_FIRST = Double.parseDouble(sizeFirstField_.getText()); + af_.NUM_FIRST = Double.parseDouble(numFirstField_.getText()); + af_.SIZE_SECOND = Double.parseDouble(sizeSecondField_.getText()); + af_.NUM_SECOND = Double.parseDouble(numSecondField_.getText()); + af_.CROP_SIZE = Double.parseDouble(cropSizeField_.getText()); + af_.THRES = Double.parseDouble(thresField_.getText()); + af_.CHANNEL1 = channelField1_.getText(); + af_.CHANNEL2 = channelField2_.getText(); + } + +} diff --git a/autofocus/AutofocusTB_.java b/autofocus/AutofocusTB_.java new file mode 100644 index 0000000000..7e299fa74b --- /dev/null +++ b/autofocus/AutofocusTB_.java @@ -0,0 +1,574 @@ +import ij.IJ; +import ij.ImagePlus; +import ij.gui.ImageWindow; +import ij.plugin.PlugIn; +import ij.process.ByteProcessor; +import ij.process.ImageProcessor; +import ij.process.ShortProcessor; + +import java.awt.Color; +import java.util.prefs.Preferences; +import java.util.Date; +import java.lang.System; +import java.awt.Rectangle; + +import org.micromanager.api.Autofocus; + +import mmcorej.CMMCore; + +/* +* Created on June 2nd 2007 +* author: Pakpoom Subsoontorn & Hernan Garcia +*/ +/** +* ImageJ plugin wrapper for uManager. +* +*@author thomas +*@created 30 mai 2008 +*/ + +/* +* This plugin take a stack of snapshots and computes their sharpness +*/ +public class AutofocusTB_ implements PlugIn, Autofocus { + + private final static String KEY_SIZE_FIRST = "size_first"; + private final static String KEY_NUM_FIRST = "num_first"; + private final static String KEY_SIZE_SECOND = "size_second"; + private final static String KEY_NUM_SECOND = "num_second"; + private final static String KEY_THRES = "thres"; + private final static String KEY_CROP_SIZE = "crop_size"; + private final static String KEY_CHANNEL1 = "channel1"; + private final static String KEY_CHANNEL2 = "channel2"; + private final static String AF_SETTINGS_NODE = "micro-manager/extensions/autofocus"; + + private CMMCore core_; + private ImageProcessor ipCurrent_ = null; + + /** + * Description of the Field + */ + public double SIZE_FIRST = 2; + // + /** + * Description of the Field + */ + public double NUM_FIRST = 1; + // +/- #of snapshot + /** + * Description of the Field + */ + public double SIZE_SECOND = 0.2; + /** + * Description of the Field + */ + public double NUM_SECOND = 5; + /** + * Description of the Field + */ + public double THRES = 0.02; + /** + * Description of the Field + */ + public double CROP_SIZE = 0.2; + /** + * Description of the Field + */ + public String CHANNEL1 = "Bright-Field"; + /** + * Description of the Field + */ + public String CHANNEL2 = "DAPI"; + + private double indx = 0; + //snapshot show new window iff indx = 1 + + private boolean verbose_ = true; + // displaying debug info or not + + private Preferences prefs_; + //******** + + private double curDist; + private double baseDist; + private double bestDist; + private double curSh; + private double bestSh; + private long t0; + private long tPrev; + private long tcur; + + + /** + * Constructor for the Autofocus_ object + */ + public AutofocusTB_() { + //constructor!!! + Preferences root = Preferences.userNodeForPackage(this.getClass()); + prefs_ = root.node(root.absolutePath() + "/" + AF_SETTINGS_NODE); + loadSettings(); + } + + + /** + * Main processing method for the Autofocus_ object + * + *@param arg Description of the Parameter + */ + public void run(String arg) { + t0 = System.currentTimeMillis(); + bestDist = 5000; + bestSh = 0; + //############# CHECK INPUT ARG AND CORE ######## + if (arg.compareTo("silent") == 0) { + verbose_ = false; + } else { + verbose_ = true; + } + + if (arg.compareTo("options") == 0) { + showOptionsDialog(); + } + + if (core_ == null) { + // if core object is not set attempt to get its global handle + core_ = MMStudioPlugin.getMMCoreInstance(); + } + + if (core_ == null) { + IJ.error("Unable to get Micro-Manager Core API handle.\n" + + "If this module is used as ImageJ plugin, Micro-Manager Studio must be running first!"); + return; + } + + //######################## START THE ROUTINE ########### + + try { + IJ.write("Autofocus TB started."); + //########System setup########## + core_.setConfig("Channel", CHANNEL1); + core_.waitForSystem(); + core_.waitForDevice(core_.getShutterDevice()); + //delay_time(3000); + + + //Snapshot, zdistance and sharpNess before AF + /* + * curDist = core_.getPosition(core_.getFocusDevice()); + * indx =1; + * snapSingleImage(); + * indx =0; + * tPrev = System.currentTimeMillis(); + * curSh = sharpNess(ipCurrent_); + * tcur = System.currentTimeMillis()-tPrev; + */ + //set z-distance to the lowest z-distance of the stack + curDist = core_.getPosition(core_.getFocusDevice()); + baseDist = curDist - SIZE_FIRST * NUM_FIRST; + core_.setPosition(core_.getFocusDevice(), baseDist); + core_.waitForDevice(core_.getFocusDevice()); + delay_time(100); + + //core_.setShutterOpen(true); + //core_.setAutoShutter(false); + + IJ.write("Before rough search: " + String.valueOf(curDist)); + + //Rough search + for (int i = 0; i < 2 * NUM_FIRST + 1; i++) { + tPrev = System.currentTimeMillis(); + + core_.setPosition(core_.getFocusDevice(), baseDist + i * SIZE_FIRST); + core_.waitForDevice(core_.getFocusDevice()); + + curDist = core_.getPosition(core_.getFocusDevice()); + // indx =1; + snapSingleImage(); + // indx =0; + + + curSh = sharpNess(ipCurrent_); + + if (curSh > bestSh) { + bestSh = curSh; + bestDist = curDist; + } else if (bestSh - curSh > THRES * bestSh) { + break; + } + tcur = System.currentTimeMillis() - tPrev; + + //===IJ.write(String.valueOf(curDist)+" "+String.valueOf(curSh)+" " +String.valueOf(tcur)); + } + + //===IJ.write("BEST_DIST_FIRST"+String.valueOf(bestDist)+" BEST_SH_FIRST"+String.valueOf(bestSh)); + + baseDist = bestDist - SIZE_SECOND * NUM_SECOND; + core_.setPosition(core_.getFocusDevice(), baseDist); + delay_time(100); + + bestSh = 0; + + core_.setConfig("Channel", CHANNEL2); + core_.waitForSystem(); + core_.waitForDevice(core_.getShutterDevice()); + + //Fine search + for (int i = 0; i < 2 * NUM_SECOND + 1; i++) { + tPrev = System.currentTimeMillis(); + core_.setPosition(core_.getFocusDevice(), baseDist + i * SIZE_SECOND); + core_.waitForDevice(core_.getFocusDevice()); + + curDist = core_.getPosition(core_.getFocusDevice()); + // indx =1; + snapSingleImage(); + // indx =0; + + curSh = sharpNess(ipCurrent_); + + if (curSh > bestSh) { + bestSh = curSh; + bestDist = curDist; + } else if (bestSh - curSh > THRES * bestSh) { + break; + } + tcur = System.currentTimeMillis() - tPrev; + + //===IJ.write(String.valueOf(curDist)+" "+String.valueOf(curSh)+" "+String.valueOf(tcur)); + } + + IJ.write("BEST_DIST_SECOND= " + String.valueOf(bestDist) + " BEST_SH_SECOND= " + String.valueOf(bestSh)); + + core_.setPosition(core_.getFocusDevice(), bestDist); + // indx =1; + snapSingleImage(); + // indx =0; + //core_.setShutterOpen(false); + //core_.setAutoShutter(true); + + IJ.write("Total Time: " + String.valueOf(System.currentTimeMillis() - t0)); + } catch (Exception e) { + IJ.error(e.getMessage()); + } + } + + + + //take a snapshot and save pixel values in ipCurrent_ + /** + * Description of the Method + * + *@return Description of the Return Value + */ + private boolean snapSingleImage() { + + try { + core_.snapImage(); + Object img = core_.getImage(); + ImagePlus implus = newWindow(); + // this step will create a new window iff indx = 1 + implus.getProcessor().setPixels(img); + ipCurrent_ = implus.getProcessor(); + } catch (Exception e) { + IJ.write(e.getMessage()); + IJ.error(e.getMessage()); + return false; + } + + return true; + } + + + //waiting + /** + * Description of the Method + * + *@param delay Description of the Parameter + */ + private void delay_time(double delay) { + Date date = new Date(); + long sec = date.getTime(); + while (date.getTime() < sec + delay) { + date = new Date(); + } + } + + + + /* + * calculate the sharpness of a given image (in "impro"). + */ + /** + * Description of the Method + * + *@param impro Description of the Parameter + *@return Description of the Return Value + */ + private double sharpNessp(ImageProcessor impro) { + + int width = (int) (CROP_SIZE * core_.getImageWidth()); + int height = (int) (CROP_SIZE * core_.getImageHeight()); + int ow = (int) (((1 - CROP_SIZE) / 2) * core_.getImageWidth()); + int oh = (int) (((1 - CROP_SIZE) / 2) * core_.getImageHeight()); + + double[][] medPix = new double[width][height]; + double sharpNess = 0; + double[] windo = new double[9]; + + /* + * Apply 3x3 median filter to reduce noise + */ + for (int i = 1; i < width - 1; i++) { + for (int j = 1; j < height - 1; j++) { + + windo[0] = (double) impro.getPixel(ow + i - 1, oh + j - 1); + windo[1] = (double) impro.getPixel(ow + i, oh + j - 1); + windo[2] = (double) impro.getPixel(ow + i + 1, oh + j - 1); + windo[3] = (double) impro.getPixel(ow + i - 1, oh + j); + windo[4] = (double) impro.getPixel(ow + i, oh + j); + windo[5] = (double) impro.getPixel(ow + i + 1, oh + j); + windo[6] = (double) impro.getPixel(ow + i - 1, oh + j + 1); + windo[7] = (double) impro.getPixel(ow + i, oh + j + 1); + windo[8] = (double) impro.getPixel(ow + i + 1, oh + j + 1); + + medPix[i][j] = findMed(windo); + } + } + + /* + * Edge detection using a 3x3 filter: [-2 -1 0; -1 0 1; 0 1 2]. Then sum all pixel values. Ideally, the sum is large if most edges are sharp + */ + double edgehoriz; + double edvevert; + for (int k = 1; k < width - 1; k++) { + for (int l = 1; l < height - 1; l++) { + edgehoriz = Math.pow((-2 * medPix[k - 1][l] - medPix[k - 1][l - 1] - medPix[k - 1][l + 1] + medPix[k + 1][l - 1] + medPix[k + 1][l + 1] + 2 * medPix[k + 1][l]), 2); + edvevert = Math.pow((-2 * medPix[k][l - 1] - medPix[k - 1][l - 1] - medPix[k + 1][l - 1] + medPix[k - 1][l + 1] + medPix[k + 1][l + 1] + 2 * medPix[k][l + 1]), 2); + sharpNess += (edgehoriz + edvevert); + //sharpNess = sharpNess + Math.pow((-2 * medPix[k - 1][l - 1] - medPix[k][l - 1] - medPix[k - 1][l] + medPix[k + 1][l] + medPix[k][l + 1] + 2 * medPix[k + 1][l + 1]), 2); + + } + } + return sharpNess; + } + + + /* + * calculate the sharpness of a given image (in "impro"). + */ + /** + * Description of the Method + * + *@param impro Description of the Parameter + *@return Description of the Return Value + */ + private double sharpNess(ImageProcessor impro) { + + int width = (int) (CROP_SIZE * core_.getImageWidth()); + int height = (int) (CROP_SIZE * core_.getImageHeight()); + int sx = (int) (core_.getImageWidth() - width) / 2; + int sy = (int) (core_.getImageHeight() - height) / 2; + //int ow = (int) (((1 - CROP_SIZE) / 2) * core_.getImageWidth()); + //int oh = (int) (((1 - CROP_SIZE) / 2) * core_.getImageHeight()); + + // double[][] medPix = new double[width][height]; + double sharpNess = 0; + //double[] windo = new double[9]; + + /* + * Apply 3x3 median filter to reduce noise + */ + /* + * for (int i=0; i - + + + + + + + + + + @@ -48,12 +57,22 @@ + + + + + + + + + + \ No newline at end of file diff --git a/build_instructions_debian.txt b/build_instructions_debian.txt new file mode 100644 index 0000000000..edb9a53f8d --- /dev/null +++ b/build_instructions_debian.txt @@ -0,0 +1,36 @@ + (special build instructions +for linux users) +1. install packages: +sun-java6-sdk or equivalent +autoconf +automake +swig +libace-dev +g++ +libtool + +2. ImageJ. Download and install from +http://rsb.info.nih.gov/ij/download.html. + +3. run ./mmUnixBuild.sh + +4. run ./configure --with-imagej=/home/mahogny/umanager/ImageJ + with whatever path to imagej fits in your case + +5. (will not be needed later) change /usr/include/ace/config-lite.h + +error _REENTRANT has to be defined! +into +define _REENTRANT + +6. make + +7. when it fails, edit MMCoreJ_wrap/MMCoreJ_wrap.cxx +remove +{ + jint jvalue = (jint)temp2; + jenv->SetIntArrayRegion(jarg2, 0, 1, &jvalue); + } + +8. make +9. make install diff --git a/classext/ij.jar b/classext/ij.jar index 4cb221476d..e977f6da90 100644 Binary files a/classext/ij.jar and b/classext/ij.jar differ diff --git a/configure.in b/configure.in index 23db1f29ca..b25edee6b3 100755 --- a/configure.in +++ b/configure.in @@ -67,6 +67,15 @@ fi AC_MSG_RESULT($LINKFORSHARED) AC_SUBST(LINKFORSHARED) +#--------------------------------------------------- +# Platform dependent flags +#--------------------------------------------------- +case $host in + *-*-linux*) + LPTHREAD="-lpthread";; +esac +AC_MSG_RESULT($LPTHREAD) + #---------------------------------------------------------------- # Look for java binaries and headers @@ -228,8 +237,12 @@ then *-*-linux*) if test -r /usr/local/lib/libACE.la ; then LIBACE="/usr/local/lib/libACE.la" - else - AC_MSG_ERROR([not found, download from http://deuce.doc.wustl.edu/Download.html, build and install (cd ACE_wrappers \ mkdir build \ cd build \ ../configure \ make \ make install ) and rerun configure]) + else + if test -r /usr/lib/libACE.a ; then + LIBACE="/usr/lib/libACE.a" + else + AC_MSG_ERROR([not found, download from http://deuce.doc.wustl.edu/Download.html, build and install (cd ACE_wrappers \ mkdir build \ cd build \ ../configure \ make \ make install ) and rerun configure]) + fi fi ;; *-*-darwin*) @@ -256,6 +269,7 @@ AC_SUBST(IJJARPATH) AC_SUBST(BSHJARPATH) AC_SUBST(I5DJARPATH) AC_SUBST(LIBACE) +AC_SUBST(LPTHREAD) # Checks for programs. diff --git a/debiancontrol b/debiancontrol new file mode 100644 index 0000000000..a1941225d5 --- /dev/null +++ b/debiancontrol @@ -0,0 +1,11 @@ +Package: micro-manager +Version: 1.2 +Section: contrib/science +Priority: optional +Architecture: all +Essential: no +Depends: libace-dev, java2-runtime, bsh +Installed-Size: 10 +Maintainer: Johan Henriksson [mahogny@areta.org] +Description: Micro-Manager provides a programmatic and user interface for research microscopes and related equipment +Homepage: http://www.micro-manager.org diff --git a/mkdebian.sh b/mkdebian.sh new file mode 100644 index 0000000000..48c2b0d4b1 --- /dev/null +++ b/mkdebian.sh @@ -0,0 +1,58 @@ +ROOT=../root +rm -Rf $ROOT +mkdir $ROOT + +##### Meta information +mkdir $ROOT/DEBIAN +cp doc/copyright.txt $ROOT/DEBIAN/copyright +cp debiancontrol $ROOT/DEBIAN/control +echo "#!/bin/sh" > $ROOT/DEBIAN/postinst +chmod 0555 $ROOT/DEBIAN/postinst + +##### Programs +mkdir $ROOT/usr/ +mkdir $ROOT/usr/bin/ +cp Test_Serial/testserial $ROOT/usr/bin/mm_testserial +cp ModuleTest/moduletest $ROOT/usr/bin/mm_moduletest +cp Test_MMCore/testCore $ROOT/usr/bin/mm_testcore +strip $ROOT/usr/bin/* + +##### JAR-files +mkdir $ROOT/usr/share/ +mkdir $ROOT/usr/share/java/ +mkdir $ROOT/usr/share/java/micro-manager/ +cp Bleach/MMBleach_.jar autofocus/MMAutofocus_.jar autofocus/MMAutofocusTB_.jar MMCoreJ_wrap/MMCoreJ.jar Tracking/Tracker_.jar \ +mmstudio/MMJ_.jar mmstudio/MMReader_.jar $ROOT/usr/share/java/micro-manager/ +#classext/bsh-2.0b4.jar classext/syntax.jar classext/ij.jar + +##### Core +mkdir $ROOT/usr/lib/ +mkdir $ROOT/usr/lib/micro-manager/ + +cp MMCoreJ_wrap/.libs/libMMCoreJ_wrap.so $ROOT/usr/lib/micro-manager/ + +##### All plugins +for from in `ls DeviceAdapters/*/.libs/*.so` + do + to=${from##*/} + to=$ROOT/usr/lib/micro-manager/libmmgr_dal_`echo $to|sed 's/\..\{2\}$//'` + to=$to.so + cp $from $to + done +strip $ROOT/usr/lib/micro-manager/* + +##### Make shared objects visible without hardcoding the path +mkdir $ROOT/etc/ +mkdir $ROOT/etc/ld.so.conf.d/ +echo "/usr/lib/micro-manager" > $ROOT/etc/ld.so.conf.d/micro-manager.conf +echo "/sbin/ldconfig" >> $ROOT/DEBIAN/postinst + +##### Put together +cd .. +dpkg-deb -b root +mv root.deb micro-manager.deb + +#use later. buggy now +#jpackage-utils + + diff --git a/mmstudio/src/MMImage5DReaderPlugin_.java b/mmstudio/src/MMImage5DReaderPlugin_.java index bdf10d53a4..ca2869bfd6 100644 --- a/mmstudio/src/MMImage5DReaderPlugin_.java +++ b/mmstudio/src/MMImage5DReaderPlugin_.java @@ -79,6 +79,8 @@ public void run(String arg) { // choose the directory // -------------------- + System.setProperty("apple.laf.useScreenMenuBar", "true"); + JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); String openAcqDirectory = new String(Prefs.get(MMImage5DReaderDirKey, "")); diff --git a/mmstudio/src/MMStudioPlugin.java b/mmstudio/src/MMStudioPlugin.java index 2a89a7667a..6b919d1845 100644 --- a/mmstudio/src/MMStudioPlugin.java +++ b/mmstudio/src/MMStudioPlugin.java @@ -63,6 +63,7 @@ public void run(String arg) { "ch.randelshofer.quaqua.QuaquaLookAndFeel"); // set UI manager properties here that affect Quaqua // ... + System.setProperty("apple.laf.useScreenMenuBar", "true"); } catch (ClassNotFoundException e) { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { diff --git a/mmstudio/src/org/micromanager/AcqControlDlg.java b/mmstudio/src/org/micromanager/AcqControlDlg.java index 45426c6917..3497237599 100644 --- a/mmstudio/src/org/micromanager/AcqControlDlg.java +++ b/mmstudio/src/org/micromanager/AcqControlDlg.java @@ -41,6 +41,7 @@ import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; +import java.util.Enumeration; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import java.beans.PropertyChangeListener; @@ -71,11 +72,14 @@ import javax.swing.border.LineBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.TableModelListener; +import javax.swing.event.TableModelEvent; import javax.swing.filechooser.FileFilter; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; import org.micromanager.api.AcquisitionEngine; import org.micromanager.api.Autofocus; @@ -107,6 +111,7 @@ public class AcqControlDlg extends JDialog implements PropertyChangeListener { private JComboBox posModeCombo_; public static final String NEW_ACQFILE_NAME = "MMAcquistion.xml"; public static final String ACQ_SETTINGS_NODE = "AcquistionSettings"; + public static final String COLOR_SETTINGS_NODE = "ColorSettings"; private JComboBox channelGroupCombo_; private JTextArea commentTextArea_; @@ -127,6 +132,7 @@ public class AcqControlDlg extends JDialog implements PropertyChangeListener { private ChannelTableModel model_; private Preferences prefs_; private Preferences acqPrefs_; + private Preferences colorPrefs_; private File acqFile_; private String acqDir_; private int zVals_=0; @@ -176,8 +182,13 @@ public class AcqControlDlg extends JDialog implements PropertyChangeListener { private static final String ACQ_SAVE_FILES = "acqSaveFiles"; private static final String ACQ_SINGLE_FRAME = "singleFrame"; private static final String ACQ_AF_ENABLE = "autofocus_enabled"; + private static final String ACQ_COLUMN_WIDTH = "column_width"; + private static final String ACQ_COLUMN_ORDER = "column_order"; + private static final int ACQ_DEFAULT_COLUMN_WIDTH = 77; private JCheckBox multiPosCheckBox_; private JCheckBox singleFrameCheckBox_; + private int columnWidth_[]; + private int columnOrder_[]; /** @@ -221,7 +232,7 @@ private String getExtension(File f) { /** * Data representation class for the channels list */ - public class ChannelTableModel extends AbstractTableModel { + public class ChannelTableModel extends AbstractTableModel implements TableModelListener{ private static final long serialVersionUID = 3290621191844925827L; private ArrayList channels_; private AcquisitionEngine acqEng_; @@ -236,6 +247,7 @@ public class ChannelTableModel extends AbstractTableModel { public ChannelTableModel(AcquisitionEngine eng) { acqEng_ = eng; + addTableModelListener(this); } public int getRowCount() { @@ -291,6 +303,25 @@ public boolean isCellEditable(int nRow, int nCol) { return true; } + /* + * Catched events thrown by the ColorEditor + * Will write the new color into the Color Prefs + */ + public void tableChanged(TableModelEvent e) { + int row = e.getFirstRow(); + if (row < 0) + return; + int col = e.getColumn(); + if (col < 0) + return; + ChannelSpec channel = channels_.get(row); + TableModel model = (TableModel)e.getSource(); + if (col == 4) { + Color color = (Color) model.getValueAt(row, col); + colorPrefs_.putInt("Color_" + acqEng_.getChannelGroup() + "_" + channel.config_, color.getRGB()); + } + } + public void setChannels(ArrayList ch) { channels_ = ch; @@ -304,6 +335,7 @@ public void addNewChannel() { ChannelSpec channel = new ChannelSpec(); if (acqEng_.getChannelConfigs().length > 0) { channel.config_ = acqEng_.getChannelConfigs()[0]; + channel.color_ = new Color (colorPrefs_.getInt("Color_" + acqEng_.getChannelGroup() + "_" + channel.config_, Color.white.getRGB())); channels_.add(channel); } } @@ -313,7 +345,7 @@ public void removeChannel(int chIndex) { channels_.remove(chIndex); } - public int rowUp(int rowIdx) { + public int rowDown(int rowIdx) { if (rowIdx >= 0 && rowIdx < channels_.size() - 1) { ChannelSpec channel = channels_.get(rowIdx); channels_.add(rowIdx+2, channel); @@ -323,7 +355,7 @@ public int rowUp(int rowIdx) { return rowIdx; } - public int rowDown(int rowIdx) { + public int rowUp(int rowIdx) { if (rowIdx >= 1 && rowIdx < channels_.size()) { ChannelSpec channel = channels_.get(rowIdx); channels_.add(rowIdx-1, channel); @@ -360,6 +392,8 @@ public class ChannelCellEditor extends AbstractCellEditor implements TableCellEd JComboBox combo_ = new JComboBox(); JLabel colorLabel_ = new JLabel(); int editCol_ = -1; + int editRow_ = -1; + ChannelSpec channel_ = null; // This method is called when a cell value is edited by the user. public Component getTableCellEditorComponent(JTable table, Object value, @@ -371,9 +405,13 @@ public Component getTableCellEditorComponent(JTable table, Object value, ChannelTableModel model = (ChannelTableModel)table.getModel(); ArrayList channels = model.getChannels(); - ChannelSpec channel = channels.get(rowIndex); - // Configure the component with the specified value + final ChannelSpec channel = channels.get(rowIndex); + channel_ = channel; + + colIndex = table.convertColumnIndexToModel(colIndex); + // Configure the component with the specified value + editRow_ = rowIndex; editCol_ = colIndex; if (colIndex==1 || colIndex==2) { @@ -400,10 +438,12 @@ public Component getTableCellEditorComponent(JTable table, Object value, combo_.addItem(configs[i]); } combo_.setSelectedItem(channel.config_); + channel.color_ = new Color (colorPrefs_.getInt("Color_" + acqEng_.getChannelGroup() + "_" + channel.config_, Color.white.getRGB())); // end editing on selection change combo_.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + channel.color_ = new Color (colorPrefs_.getInt("Color_" + acqEng_.getChannelGroup() + "_" + channel.config_, Color.white.getRGB())); fireEditingStopped(); } }); @@ -411,12 +451,7 @@ public void actionPerformed(ActionEvent e) { // Return the configured component return combo_; } else { - // color - // TODO: this is never called ???? - Color selColor = JColorChooser.showDialog(null, "Channel color", (Color)value); - colorLabel_.setOpaque(true); - colorLabel_.setBackground(selColor); - channel.color_ = selColor; + // ColorEditor takes care of this return colorLabel_; } } @@ -424,9 +459,12 @@ public void actionPerformed(ActionEvent e) { // This method is called when editing is completed. // It must return the new value to be stored in the cell. public Object getCellEditorValue() { - if (editCol_ == 0) + // TODO: if content of column does not match type we get an exception + if (editCol_ == 0) { + // As a side effect, change to the color of the new channel + channel_.color_ = new Color (colorPrefs_.getInt("Color_" + acqEng_.getChannelGroup() + "_" + combo_.getSelectedItem(), Color.white.getRGB())); return combo_.getSelectedItem(); - else if (editCol_ == 1 || editCol_ == 2) + } else if (editCol_ == 1 || editCol_ == 2) return new Double(text_.getText()); else if (editCol_ == 3) { return new Integer(text_.getText()); @@ -443,7 +481,7 @@ else if (editCol_ == 3) { } /** - * Renederer class for the channel table. + * Renderer class for the channel table. */ public class ChannelCellRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = -4328340719459382679L; @@ -459,14 +497,12 @@ public Component getTableCellRendererComponent(JTable table, Object value, ArrayList channels = model.getChannels(); ChannelSpec channel = channels.get(rowIndex); - if (isSelected) { - // cell (and perhaps other cells) are selected - } - if (hasFocus) { // this cell is the anchor and the table has the focus } + colIndex = table.convertColumnIndexToModel(colIndex); + setOpaque(false); if (colIndex == 0) setText(channel.config_); @@ -482,6 +518,14 @@ else if (colIndex == 3) { setOpaque(true); } + if (isSelected) { + setBackground(table.getSelectionBackground()); + setOpaque(true); + } else { + setOpaque(false); + setBackground(table.getBackground()); + } + // Since the renderer is a component, return itself return this; } @@ -509,6 +553,7 @@ public AcqControlDlg(AcquisitionEngine acqEng, Preferences prefs, DeviceControlG Preferences root = Preferences.userNodeForPackage(this.getClass()); acqPrefs_ = root.node(root.absolutePath() + "/" + ACQ_SETTINGS_NODE); + colorPrefs_ = root.node(root.absolutePath() + "/" + COLOR_SETTINGS_NODE); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); @@ -622,9 +667,12 @@ public void actionPerformed(ActionEvent e) { upButton.setFont(new Font("Arial", Font.PLAIN, 10)); upButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - int newSel = model_.rowUp(table_.getSelectedRow()); - model_.fireTableStructureChanged(); - table_.setRowSelectionInterval(newSel, newSel); + int sel = table_.getSelectedRow(); + if (sel > -1) { + int newSel = model_.rowUp(sel); + model_.fireTableStructureChanged(); + table_.setRowSelectionInterval(newSel, newSel); + } } }); upButton.setText("Up"); @@ -636,9 +684,11 @@ public void actionPerformed(ActionEvent e) { downButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int sel = table_.getSelectedRow(); - int newSel = model_.rowDown(sel); - model_.fireTableStructureChanged(); - table_.setRowSelectionInterval(newSel, newSel); + if (sel > -1) { + int newSel = model_.rowDown(sel); + model_.fireTableStructureChanged(); + table_.setRowSelectionInterval(newSel, newSel); + } } }); downButton.setText("Dn"); @@ -756,7 +806,7 @@ public void actionPerformed(final ActionEvent e) { // load window settings int x = 100; int y = 100; - setBounds(x, y, 514, 643); + setBounds(x, y, 514, 587); if (prefs_ != null) { x = prefs_.getInt(ACQ_CONTROL_X, x); y = prefs_.getInt(ACQ_CONTROL_Y, y); @@ -804,12 +854,12 @@ public void actionPerformed(final ActionEvent e) { rootField_ = new JTextField(); rootField_.setFont(new Font("Arial", Font.PLAIN, 10)); - rootField_.setBounds(91, 483, 354, 22); + rootField_.setBounds(81, 429, 354, 22); getContentPane().add(rootField_); nameField_ = new JTextField(); nameField_.setFont(new Font("Arial", Font.PLAIN, 10)); - nameField_.setBounds(91, 511, 354, 22); + nameField_.setBounds(81, 457, 354, 22); getContentPane().add(nameField_); final JButton browseRootButton = new JButton(); @@ -821,25 +871,25 @@ public void actionPerformed(final ActionEvent e) { browseRootButton.setMargin(new Insets(2, 5, 2, 5)); browseRootButton.setFont(new Font("Dialog", Font.PLAIN, 10)); browseRootButton.setText("..."); - browseRootButton.setBounds(451, 481, 47, 24); + browseRootButton.setBounds(441, 427, 47, 24); getContentPane().add(browseRootButton); final JLabel hardwareAutofocus = new JLabel(); hardwareAutofocus.setFont(new Font("Arial", Font.BOLD, 11)); hardwareAutofocus.setText("Hardware Autofocus"); - hardwareAutofocus.setBounds(10, 395, 140, 14); + hardwareAutofocus.setBounds(248, 216, 140, 14); getContentPane().add(hardwareAutofocus); continuousFocusOffForXYMoveCheckBox_ = new JCheckBox(); continuousFocusOffForXYMoveCheckBox_.setFont(new Font("Arial", Font.PLAIN, 10)); continuousFocusOffForXYMoveCheckBox_.setText("Switch off for XY move"); - continuousFocusOffForXYMoveCheckBox_.setBounds(10, 413, 140, 21); + continuousFocusOffForXYMoveCheckBox_.setBounds(240, 231, 139, 21); getContentPane().add(continuousFocusOffForXYMoveCheckBox_); continuousFocusOffForZMoveCheckBox_ = new JCheckBox(); continuousFocusOffForZMoveCheckBox_.setFont(new Font("Arial", Font.PLAIN, 10)); continuousFocusOffForZMoveCheckBox_.setText("Switch off for Z move"); - continuousFocusOffForZMoveCheckBox_.setBounds(238, 412, 183, 23); + continuousFocusOffForZMoveCheckBox_.setBounds(380, 230, 130, 23); getContentPane().add(continuousFocusOffForZMoveCheckBox_); saveFilesCheckBox_ = new JCheckBox(); @@ -856,19 +906,19 @@ public void actionPerformed(final ActionEvent e) { }); saveFilesCheckBox_.setFont(new Font("Arial", Font.PLAIN, 10)); saveFilesCheckBox_.setText("Save files to acquisition directory"); - saveFilesCheckBox_.setBounds(10, 455, 207, 21); + saveFilesCheckBox_.setBounds(6, 402, 207, 21); getContentPane().add(saveFilesCheckBox_); final JLabel directoryPrefixLabel = new JLabel(); directoryPrefixLabel.setFont(new Font("Arial", Font.PLAIN, 10)); directoryPrefixLabel.setText("Name prefix"); - directoryPrefixLabel.setBounds(11, 511, 76, 22); + directoryPrefixLabel.setBounds(2, 457, 76, 22); getContentPane().add(directoryPrefixLabel); final JLabel directoryPrefixLabel_1 = new JLabel(); directoryPrefixLabel_1.setFont(new Font("Arial", Font.PLAIN, 10)); directoryPrefixLabel_1.setText("Directory root"); - directoryPrefixLabel_1.setBounds(11, 482, 72, 22); + directoryPrefixLabel_1.setBounds(6, 429, 72, 22); getContentPane().add(directoryPrefixLabel_1); final JLabel summaryLabel = new JLabel(); @@ -889,23 +939,23 @@ public void actionPerformed(final ActionEvent e) { getContentPane().add(zValCombo_); JScrollPane commentScrollPane = new JScrollPane(); - commentScrollPane.setBounds(91, 539, 354, 62); + commentScrollPane.setBounds(81, 485, 354, 62); getContentPane().add(commentScrollPane); commentTextArea_ = new JTextArea(); + commentScrollPane.setViewportView(commentTextArea_); commentTextArea_.setFont(new Font("", Font.PLAIN, 10)); commentTextArea_.setToolTipText("Comment for the current acquistion"); commentTextArea_.setWrapStyleWord(true); commentTextArea_.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); //commentTextArea_.setBounds(91, 505, 354, 62); //getContentPane().add(commentTextArea_); - commentScrollPane.setViewportView(commentTextArea_); JLabel directoryPrefixLabel_2 = new JLabel(); directoryPrefixLabel_2.setFont(new Font("Arial", Font.PLAIN, 10)); directoryPrefixLabel_2.setText("Comment"); - directoryPrefixLabel_2.setBounds(14, 538, 76, 22); + directoryPrefixLabel_2.setBounds(12, 485, 76, 22); getContentPane().add(directoryPrefixLabel_2); useSliceSettingsCheckBox_ = new JCheckBox(); @@ -927,7 +977,7 @@ public void actionPerformed(final ActionEvent e) { JSeparator separator_2 = new JSeparator(); separator_2.setFont(new Font("Arial", Font.PLAIN, 10)); - separator_2.setBounds(5, 445, 493, 5); + separator_2.setBounds(5, 391, 493, 5); getContentPane().add(separator_2); JSeparator separator_3 = new JSeparator(); @@ -1006,7 +1056,7 @@ public void actionPerformed(ActionEvent e) { singleFrameCheckBox_.setFont(new Font("", Font.PLAIN, 10)); singleFrameCheckBox_.setText("Display only last frame"); singleFrameCheckBox_.setEnabled(false); - singleFrameCheckBox_.setBounds(238, 451, 183, 23); + singleFrameCheckBox_.setBounds(223, 401, 183, 23); getContentPane().add(singleFrameCheckBox_); afCheckBox_ = new JCheckBox(); @@ -1153,7 +1203,11 @@ public void loadAcqSettings() { singleFrameCheckBox_.setSelected(false); } nameField_.setText(acqPrefs_.get(ACQ_DIR_NAME, "Untitled")); - rootField_.setText(acqPrefs_.get(ACQ_ROOT_NAME, "C:/AcquisitionData")); + String os_name = System.getProperty("os.name",""); + if (os_name.startsWith("Window")) + rootField_.setText(acqPrefs_.get(ACQ_ROOT_NAME, "C:/AcquisitionData")); + else + rootField_.setText(acqPrefs_.get(ACQ_ROOT_NAME, "AcquisitionData")); acqEng_.setSliceMode(acqPrefs_.getInt(ACQ_SLICE_MODE, acqEng_.getSliceMode())); acqEng_.setPositionMode(acqPrefs_.getInt(ACQ_POSITION_MODE, acqEng_.getPositionMode())); @@ -1188,6 +1242,16 @@ public void loadAcqSettings() { Color c = new Color(r, g, b); acqEng_.addChannel(name, exp, zOffset, s8, s16, skip, c); } + + // Restore Column Width and Column order + int columnCount = 5; + columnWidth_ = new int[columnCount]; + columnOrder_ = new int[columnCount]; + for (int k=0; k 1) { core_.setPosition(zStage_, z); + if (oldFocusEnabled_ && !continuousFocusOffForZMove_) + waitForFocusLock(); zCur = z; } for (int k=0; k