From e0225a1d793d4e3ff869f0ddf9f2a8d16b1e0284 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 2 Jul 2025 15:22:49 -0400 Subject: [PATCH 1/4] feat: store labels and only write user defined ones --- MMCore/MMCore.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++- MMCore/MMCore.h | 3 ++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/MMCore/MMCore.cpp b/MMCore/MMCore.cpp index 702f798de..dfff479f4 100644 --- a/MMCore/MMCore.cpp +++ b/MMCore/MMCore.cpp @@ -779,6 +779,14 @@ void CMMCore::unloadDevice(const char* label///< the name of the device to unloa try { mm::DeviceModuleLockGuard guard(pDevice); LOG_DEBUG(coreLogger_) << "Will unload device " << label; + + // Clean up initial state labels for this device if it exists + auto it = initialStateLabels_.find(label); + if (it != initialStateLabels_.end()) { + initialStateLabels_.erase(it); + LOG_DEBUG(coreLogger_) << "Cleaned up initial state labels for device " << label; + } + deviceManager_->UnloadDevice(pDevice); LOG_DEBUG(coreLogger_) << "Did unload device " << label; @@ -814,6 +822,10 @@ void CMMCore::unloadAllDevices() throw (CMMError) } LOG_DEBUG(coreLogger_) << "Will unload all devices"; + + // Clear all initial state labels since all devices are being unloaded + initialStateLabels_.clear(); + deviceManager_->UnloadAllDevices(); LOG_INFO(coreLogger_) << "Did unload all devices"; @@ -1098,6 +1110,47 @@ void CMMCore::initializeDevice(const char* label ///< the device to initialize pDevice->Initialize(); LOG_INFO(coreLogger_) << "Did initialize device " << label; + // For State devices, capture initial position labels after initialization + if (pDevice->GetType() == MM::StateDevice) + { + try + { + std::shared_ptr pStateDev = + deviceManager_->GetDeviceOfType(label); + + unsigned long numPositions = pStateDev->GetNumberOfPositions(); + std::map initialLabels; + + for (unsigned long pos = 0; pos < numPositions; pos++) + { + try + { + std::string posLabel = pStateDev->GetPositionLabel(pos); + if (!posLabel.empty()) + { + initialLabels[pos] = posLabel; + } + } + catch (const CMMError&) + { + // Label not defined for this position, skip + } + } + + // Store the initial labels for this device + initialStateLabels_[label] = initialLabels; + + LOG_DEBUG(coreLogger_) << "Captured " << initialLabels.size() + << " initial state labels for device " << label; + } + catch (const CMMError& e) + { + // Log but don't fail initialization if we can't capture labels + LOG_WARNING(coreLogger_) << "Failed to capture initial state labels for device " + << label << ": " << e.getMsg(); + } + } + updateCoreProperties(); } @@ -7117,6 +7170,8 @@ void CMMCore::loadSystemState(const char* fileName) throw (CMMError) * Saves the current system configuration to a text file of the MM specific format. * The configuration file records only the information essential to the hardware * setup: devices, labels, pre-initialization properties, and configurations. + * For state devices, only position labels that have been modified from their + * initial values (captured during device initialization) are saved. * The file format is the same as for the system state. */ void CMMCore::saveSystemConfiguration(const char* fileName) throw (CMMError) @@ -7223,6 +7278,11 @@ void CMMCore::saveSystemConfiguration(const char* fileName) throw (CMMError) deviceManager_->GetDeviceOfType(deviceLabels[i]); mm::DeviceModuleLockGuard guard(pSD); unsigned numPos = pSD->GetNumberOfPositions(); + + // Check if we have initial labels stored for this device + auto initialLabelsIt = initialStateLabels_.find(deviceLabels[i]); + bool hasInitialLabels = (initialLabelsIt != initialStateLabels_.end()); + for (unsigned long j=0; jsecond; + auto initialLabelIt = initialLabels.find(j); + + if (initialLabelIt != initialLabels.end() && + initialLabelIt->second == stateLabel) + { + // Current label matches initial label, don't save it + shouldSaveLabel = false; + } + } + + if (shouldSaveLabel) + { + os << MM::g_CFGCommand_Label << ',' << deviceLabels[i] << ',' << j << ',' << stateLabel << '\n'; + } } } } diff --git a/MMCore/MMCore.h b/MMCore/MMCore.h index 2a10b8b6a..a978cb88f 100644 --- a/MMCore/MMCore.h +++ b/MMCore/MMCore.h @@ -725,6 +725,9 @@ class CMMCore mutable MMThreadLock stateCacheLock_; mutable Configuration stateCache_; // Synchronized by stateCacheLock_ + // Storage for initial state labels after device initialization + std::map> initialStateLabels_; + MMThreadLock* pPostedErrorsLock_; mutable std::deque > postedErrors_; From 5f0ab715e41c58aa017090c1f995ad2e5869a98d Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 2 Jul 2025 15:57:23 -0400 Subject: [PATCH 2/4] update code --- MMCore/MMCore.cpp | 30 +++++++++++++++++++++++++++--- MMCore/MMCore.h | 1 + 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/MMCore/MMCore.cpp b/MMCore/MMCore.cpp index dfff479f4..73b0ba485 100644 --- a/MMCore/MMCore.cpp +++ b/MMCore/MMCore.cpp @@ -927,6 +927,9 @@ void CMMCore::initializeAllDevicesSerial() throw (CMMError) pDevice->Initialize(); LOG_INFO(coreLogger_) << "Did initialize device " << devices[i]; + // Capture initial state labels for State devices + captureInitialStateLabels(pDevice, devices[i].c_str()); + assignDefaultRole(pDevice); } @@ -1058,6 +1061,9 @@ int CMMCore::initializeVectorOfDevices(std::vectorInitialize(); LOG_INFO(coreLogger_) << "Did initialize device " << pDevices[i].second; + + // Capture initial state labels for State devices + captureInitialStateLabels(pDevice, pDevices[i].second.c_str()); } return DEVICE_OK; } @@ -1110,11 +1116,28 @@ void CMMCore::initializeDevice(const char* label ///< the device to initialize pDevice->Initialize(); LOG_INFO(coreLogger_) << "Did initialize device " << label; + // Capture initial state labels for State devices + captureInitialStateLabels(pDevice, label); + + updateCoreProperties(); +} + + +/** + * Helper function to capture initial state labels for State devices after initialization. + * This function should be called after any device initialization to ensure state labels are captured. + * + * @param pDevice the initialized device instance + * @param label the device label + */ +void CMMCore::captureInitialStateLabels(std::shared_ptr pDevice, const char* label) +{ // For State devices, capture initial position labels after initialization if (pDevice->GetType() == MM::StateDevice) { try { + std::cout << "Capturing initial state labels for device " << label << std::endl; std::shared_ptr pStateDev = deviceManager_->GetDeviceOfType(label); @@ -1139,7 +1162,10 @@ void CMMCore::initializeDevice(const char* label ///< the device to initialize // Store the initial labels for this device initialStateLabels_[label] = initialLabels; - + + std::cout << "Captured " << initialLabels.size() + << " initial state labels for device " << label << std::endl; + LOG_DEBUG(coreLogger_) << "Captured " << initialLabels.size() << " initial state labels for device " << label; } @@ -1150,8 +1176,6 @@ void CMMCore::initializeDevice(const char* label ///< the device to initialize << label << ": " << e.getMsg(); } } - - updateCoreProperties(); } diff --git a/MMCore/MMCore.h b/MMCore/MMCore.h index a978cb88f..9976a2dcb 100644 --- a/MMCore/MMCore.h +++ b/MMCore/MMCore.h @@ -762,6 +762,7 @@ class CMMCore void initializeAllDevicesSerial() throw (CMMError); void initializeAllDevicesParallel() throw (CMMError); int initializeVectorOfDevices(std::vector, std::string> > pDevices); + void captureInitialStateLabels(std::shared_ptr pDevice, const char* label); }; #if defined(__GNUC__) && !defined(__clang__) From d84229a7a813805430d44466c3e7f47064cb1b4f Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 2 Jul 2025 15:59:29 -0400 Subject: [PATCH 3/4] remove prints --- MMCore/MMCore.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MMCore/MMCore.cpp b/MMCore/MMCore.cpp index 73b0ba485..363dee6dd 100644 --- a/MMCore/MMCore.cpp +++ b/MMCore/MMCore.cpp @@ -1137,7 +1137,7 @@ void CMMCore::captureInitialStateLabels(std::shared_ptr pDevice, { try { - std::cout << "Capturing initial state labels for device " << label << std::endl; + std::shared_ptr pStateDev = deviceManager_->GetDeviceOfType(label); @@ -1162,9 +1162,6 @@ void CMMCore::captureInitialStateLabels(std::shared_ptr pDevice, // Store the initial labels for this device initialStateLabels_[label] = initialLabels; - - std::cout << "Captured " << initialLabels.size() - << " initial state labels for device " << label << std::endl; LOG_DEBUG(coreLogger_) << "Captured " << initialLabels.size() << " initial state labels for device " << label; From 0ca053bfd1c00fe25c187bff54e777f9334b46cd Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 2 Jul 2025 17:59:06 -0400 Subject: [PATCH 4/4] fix build --- MMCore/MMCore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMCore/MMCore.cpp b/MMCore/MMCore.cpp index 60c09ddd1..2f4232e84 100644 --- a/MMCore/MMCore.cpp +++ b/MMCore/MMCore.cpp @@ -1048,7 +1048,7 @@ int CMMCore::initializeVectorOfDevices(std::vector