# -*- coding: utf-8 -*- """ GEPARD - Gepard-Enabled PARticle Detection Copyright (C) 2018 Lars Bittrich and Josef Brandt, Leibniz-Institut für Polymerforschung Dresden e. V. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program, see COPYING. If not, see . """ import os import sys try: import pythoncom import win32com.client except ImportError: os.environ["NO_WITEC_CONTROL"] = "True" from time import sleep, time try: #when running the witectesting, the paths have to be differently, as it is in the same directory as the other raman com modules from .ramanbase import RamanBase from .configRaman import RamanSettingParam except ModuleNotFoundError: from ramanbase import RamanBase from configRaman import RamanSettingParam from socket import gethostname class WITecCOM(RamanBase): CLSID = "{C45E77CE-3D66-489A-B5E2-159F443BD1AA}" magn = 20 ramanParameters = [RamanSettingParam('IntegrationTime (s)', 'double', default=0.5, minVal=0.01, maxVal=100), RamanSettingParam('Accumulations', 'int', default=5, minVal=1, maxVal=100)] def __init__(self, hostname=None): super().__init__() self.name = 'WITecCOM' if hostname is None: hostname = gethostname() self.IBUCSAccess = win32com.client.DispatchEx(self.CLSID, machine=hostname, clsctx=pythoncom.CLSCTX_REMOTE_SERVER) self.advancedInterface = False self.doAutoFocus = False def connect(self): if not self.IBUCSAccess.RequestWriteAccess(True): self.connected = False return False IBUCSCore = win32com.client.CastTo(self.IBUCSAccess, 'IBUCSCore') self.VersionInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Software|Application|ProgramVersion") self.VersionMan = win32com.client.CastTo(self.VersionInterface, 'IBUCSStatusContainer') self.VersionMan.Update() version = self.VersionMan.GetSingleValueAsString()[1] try: vnr = version.split(",")[1].split(" Release")[0].strip() except: vnr = "" try: vnr = float(vnr) except ValueError: print("WITec: unknown version format:", version) vnr = 0.0 # version format unknown self.version = vnr self.PosXInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SamplePositioning|AbsolutePositionX") self.PosYInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SamplePositioning|AbsolutePositionY") self.PosZInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|ScanTable|PositionMicroscopeZ") self.GoToInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SamplePositioning|GoToPosition") self.PosXCurInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Software|SamplePositioner|CurrentPositionX") self.PosYCurInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Software|SamplePositioner|CurrentPositionY") self.PosZCurInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Software|SamplePositioner|CurrentPositionZ") self.PosZCurUserInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Hardware|Controller|DataChannels|StepperMotorPosition") self.PosXFloatMan = win32com.client.CastTo(self.PosXInterface, 'IBUCSFloat') self.PosYFloatMan = win32com.client.CastTo(self.PosYInterface, 'IBUCSFloat') self.PosZFloatMan = win32com.client.CastTo(self.PosZInterface, 'IBUCSFloat') self.PosXCurFloatMan = win32com.client.CastTo(self.PosXCurInterface, 'IBUCSStatusContainer') self.PosYCurFloatMan = win32com.client.CastTo(self.PosYCurInterface, 'IBUCSStatusContainer') self.PosZCurFloatMan = win32com.client.CastTo(self.PosZCurInterface, 'IBUCSStatusContainer') self.PosZCurUserFloatMan = win32com.client.CastTo(self.PosZCurUserInterface, 'IBUCSStatusContainer') self.GoToTrigger = win32com.client.CastTo(self.GoToInterface, 'IBUCSTrigger') if vnr<5.1: self.ImageNameInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MultiCommVideoSystem|BitmapFileName") self.ImageNameMan = win32com.client.CastTo(self.ImageNameInterface, 'IBUCSString') self.ImageSaveInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MultiCommVideoSystem|SaveColorBitmapToFile") self.ImageSaveMan = win32com.client.CastTo(self.ImageSaveInterface, 'IBUCSTrigger') self.ImageHeightInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|Calibration|ImageHeightMicrons") self.ImageHeightMan = win32com.client.CastTo(self.ImageHeightInterface, 'IBUCSFloat') self.ImageWidthInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|Calibration|ImageWidthMicrons") self.ImageWidthMan = win32com.client.CastTo(self.ImageWidthInterface, 'IBUCSFloat') self.ImageRotationInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|Calibration|RotationDegrees") self.ImageRotationMan = win32com.client.CastTo(self.ImageRotationInterface, 'IBUCSFloat') else: self.ImageNameInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|VideoImageFileName") self.ImageNameMan = win32com.client.CastTo(self.ImageNameInterface, 'IBUCSString') self.ImageSaveInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|AcquireVideoImageToFile") self.ImageSaveMan = win32com.client.CastTo(self.ImageSaveInterface, 'IBUCSTrigger') self.ImageHeightInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|Calibration|ImageHeightMicrons") self.ImageHeightMan = win32com.client.CastTo(self.ImageHeightInterface, 'IBUCSFloat') self.ImageWidthInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|Calibration|ImageWidthMicrons") self.ImageWidthMan = win32com.client.CastTo(self.ImageWidthInterface, 'IBUCSFloat') self.ImageRotationInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|Calibration|RotationDegrees") self.ImageRotationMan = win32com.client.CastTo(self.ImageRotationInterface, 'IBUCSFloat') if vnr>=5.2: self.TimeSeriesSlowNameInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|Naming|SampleName") self.TimeSeriesSlowNumInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|Naming|Counter") else: self.TimeSeriesSlowNameInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|Naming|DataName") self.TimeSeriesSlowNumInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|Naming|DataNumber") self.SequencerStartInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerSingleSpectrum|Start") self.SequencerStartTrigger = win32com.client.CastTo(self.SequencerStartInterface, 'IBUCSTrigger') self.SequencerBusyInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Software|Sequencers|IsASequencerActive") self.SequencerBusyStatus = win32com.client.CastTo(self.SequencerBusyInterface, 'IBUCSStatusContainer') self.TimeSeriesSlowNumMeasurementsInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|AmountOfMeasurements") self.TimeSeriesSlowNumMeasurementsMan = win32com.client.CastTo(self.TimeSeriesSlowNumMeasurementsInterface, 'IBUCSInt') self.TimeSeriesSlowNameMan = win32com.client.CastTo(self.TimeSeriesSlowNameInterface, 'IBUCSString') self.TimeSeriesSlowNumAccumulationsInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|SpectrumAcquisition|Accumulations") self.TimeSeriesSlowNumAccumulationsMan = win32com.client.CastTo(self.TimeSeriesSlowNumAccumulationsInterface, 'IBUCSInt') self.TimeSeriesSlowIntTimeInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|SpectrumAcquisition|IntegrationTime") self.TimeSeriesSlowIntTimeMan = win32com.client.CastTo(self.TimeSeriesSlowIntTimeInterface, 'IBUCSFloat') self.TimeSeriesSlowNumMan = win32com.client.CastTo(self.TimeSeriesSlowNumInterface, 'IBUCSInt') self.TimeSeriesSlowModeInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|MeasurementMode") self.TimeSeriesSlowModeMan = win32com.client.CastTo(self.TimeSeriesSlowModeInterface, 'IBUCSEnum') self.TimeSeriesSlowNextInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|NextMeasurement") self.TimeSeriesSlowNextMan = win32com.client.CastTo(self.TimeSeriesSlowNextInterface, 'IBUCSTrigger') self.TimeSeriesSlowStartInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|Start") self.TimeSeriesSlowStartMan = win32com.client.CastTo(self.TimeSeriesSlowStartInterface, 'IBUCSTrigger') self.TimeSeriesSlowStopInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|StopSequencer") self.TimeSeriesSlowStopMan = win32com.client.CastTo(self.TimeSeriesSlowStopInterface, 'IBUCSTrigger') self.TimeSeriesSlowIndNextInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|IndexOfNextMeasurement") self.TimeSeriesSlowIndNextMan = win32com.client.CastTo(self.TimeSeriesSlowIndNextInterface, 'IBUCSInt') self.TimeSeriesSlowActivityInterface = IBUCSCore.GetSubSystemDefaultInterface("Status|Software|Sequencers|ActiveSequencer|CurrentActivity") self.TimeSeriesSlowActivityMan = win32com.client.CastTo(self.TimeSeriesSlowActivityInterface, 'IBUCSStatusContainer') self.RamanRelativeXInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|ProbePosition|RelativeX") self.RamanRelativeXMan = win32com.client.CastTo(self.RamanRelativeXInterface, 'IBUCSFloat') self.RamanRelativeYInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|Video|ProbePosition|RelativeY") self.RamanRelativeYMan = win32com.client.CastTo(self.RamanRelativeYInterface, 'IBUCSFloat') self.BrightnessInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|WhiteLight|Top|BrightnessPercentage") self.BrightnessMan = win32com.client.CastTo(self.BrightnessInterface, 'IBUCSFloat') try: self.getAdvancedCOMFeatures(IBUCSCore) self.advancedInterface = True self.doAutoFocus = False except pythoncom.com_error: self.advancedInterface = False self.connected = True return True def getAdvancedCOMFeatures(self, IBUCSCore): self.AutoFocusInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerAutoFocus|Start") self.AutoFocusMan = win32com.client.CastTo(self.AutoFocusInterface, 'IBUCSTrigger') self.SilentSpecTextInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|SequencerSingleSpectrum|SilentSpectrumAsText") self.SilentSpecText = win32com.client.CastTo(self.SilentSpecTextInterface, 'IBUCSString') self.SilentSpecDoInterface = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|SequencerSingleSpectrum|DoSilentSpectrum") self.DoSilentSpectrum = win32com.client.CastTo(self.SilentSpecDoInterface, 'IBUCSBool') self.SingleSpecIntegrationTime = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerSingleSpectrum|IntegrationTime") self.SingleSpecIntegrationTimeMan = win32com.client.CastTo(self.SingleSpecIntegrationTime, 'IBUCSFloat') self.SingleSpecNumAccs = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerSingleSpectrum|NrOfAccumulations") self.SingleSpecNumAccsMan = win32com.client.CastTo(self.SingleSpecNumAccs, 'IBUCSInt') self.BeamPathState = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|BeamPath|State") self.BeamPathSetRamanState = IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|BeamPath|SetStateRaman") self.MicroscopeIdle = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|MicroscopeStateOnIdle") self.BeamPathSetVideoStateInterface =IBUCSCore.GetSubSystemDefaultInterface("MultiComm|MicroscopeControl|BeamPath|SetStateVideo") self.BeamPathSetVideoState = win32com.client.CastTo(self.BeamPathSetVideoStateInterface, 'IBUCSTrigger') try: from .advancedWITec import AdvancedWITecSpectra except ModuleNotFoundError: from advancedWITec import AdvancedWITecSpectra self.advSpec = AdvancedWITecSpectra() if 'Autofocus' not in [param.name for param in self.ramanParameters]: self.ramanParameters.append(RamanSettingParam('Autofocus', 'checkBox', default=False)) def getBrightness(self): assert self.connected return self.BrightnessMan.GetValue() def setBrightness(self, newval): if newval<0: newval = 0.0 elif newval>100.: newval = 100.0 self.BrightnessMan.SetValue(newval) sleep(.1) def getRamanPositionShift(self): rx = .5-self.RamanRelativeXMan.GetValue() # current assumption is, that image center is current position ry = self.RamanRelativeYMan.GetValue()-.5 width, height = self.ImageWidthMan.GetValue(), self.ImageHeightMan.GetValue() return rx*width, ry*height def disconnect(self): if self.connected: self.IBUCSAccess.RequestWriteAccess(False) self.connected = False def getPosition(self): assert self.connected self.PosXCurFloatMan.Update() x = self.PosXCurFloatMan.GetSingleValueAsDouble()[1] self.PosYCurFloatMan.Update() y = self.PosYCurFloatMan.GetSingleValueAsDouble()[1] self.PosZCurFloatMan.Update() z = self.PosZCurFloatMan.GetSingleValueAsDouble()[1] return x, y, z def getSoftwareZ(self): self.PosZCurFloatMan.Update() z = self.PosZCurFloatMan.GetSingleValueAsDouble()[1] return z def getUserZ(self): assert self.connected self.PosZCurUserFloatMan.Update() z = self.PosZCurUserFloatMan.GetSingleValueAsDouble()[1] return z def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011): assert self.connected initpos = self.getPosition() # move only if new position is really different; repeat if new position is ignored (happens some times) while max(abs(initpos[0]-x), abs(initpos[1]-y))>epsxy: t0 = time() numFails = 0 maxFails = 50 positionSubmitted = False while numFails < maxFails and not positionSubmitted: try: self.PosXFloatMan.SetValue(x) self.PosYFloatMan.SetValue(y) self.GoToTrigger.OperateTrigger() positionSubmitted = True except pythoncom.com_error: numFails += 1 sleep(.1) if numFails > 0: print(f'{numFails} of max. {maxFails} unsuccessfull position submits to Position: {x}, {y}', flush=True) if not positionSubmitted: print(f'Error setting Position: {x}, {y}\nExpecting \"signal ignored\" warning', flush=True) # wait till position is found within accuracy of epsxy; check if position changes at all distance = 2*epsxy while distance > epsxy:# and (lastpos is None or lastpos!=curpos): curpos = self.getPosition() distance = max(abs(curpos[0]-x), abs(curpos[1]-y)) if ((time()-t0>0.5) and max(abs(curpos[0]-initpos[0]), abs(curpos[1]-initpos[1]))10.): print("WARNING: signal ignored:", time()-t0, x, y, curpos, initpos) sys.stdout.flush() break sleep(.01) sleep(.1) initpos = self.getPosition() if z is not None: self.moveZto(z, epsz) def moveZto(self, z, epsz=0.011): assert self.connected #z = round(z,2) while abs(self.PosZCurFloatMan.GetSingleValueAsDouble()[1]-z)>epsz: initpos = self.PosZCurFloatMan.GetSingleValueAsDouble()[1] t0 = time() self.PosZFloatMan.SetValue(z) distance = 2*epsz while distance > epsz: self.PosZCurFloatMan.Update() curpos = self.PosZCurFloatMan.GetSingleValueAsDouble()[1] distance = abs(curpos-z) if ((time()-t0>0.5) and abs(curpos-initpos)10.): print("WARNING: signal z ignored:", time()-t0) sys.stdout.flush() break sleep(.01) sleep(.1) def saveImage(self, fname): assert self.connected self.ImageNameMan.SetValue(fname) self.ImageSaveMan.OperateTrigger() sleep(.1) def getImageDimensions(self, mode = 'df'): """ Get the image width and height in um and the orientation angle in degrees. """ assert self.connected width, height = self.ImageWidthMan.GetValue(), self.ImageHeightMan.GetValue() angle = self.ImageRotationMan.GetValue() return width, height, angle def startSinglePointScan(self): assert self.connected self.SequencerStartTrigger.OperateTrigger() # Wait until sequencer has finished while True: self.SequencerBusyStatus.Update() Busy = self.SequencerBusyStatus.GetSingleValueAsInt()[1] if not Busy: break def initiateMeasurement(self, ramanSettings): assert self.connected if not self.advancedInterface: self.initiateTimeSeriesMeasurement(ramanSettings) else: self.initateSilentSpectrumAcquisition(ramanSettings) def triggerMeasurement(self, num): if not self.advancedInterface: self.triggerTimeSeriesMeasurement(num) else: if self.doAutoFocus: self.doSpectralAutoFocus() self.acquireSilentSpectrum(num) def finishMeasurement(self, aborted=False): if self.advancedInterface: state = self.BeamPathState.GetValue() if state == 'Raman': self.MicroscopeIdle.SetValue('BeamPath|SetStateVideo') self.BeamPathSetVideoState.OperateTrigger() if not aborted: self.advSpec.createSummarizedSpecFiles() def initiateTimeSeriesMeasurement(self, ramanSettings): self.timeseries = ramanSettings['numPoints'] self.TimeSeriesSlowNameMan.SetValue(ramanSettings['filename']) self.TimeSeriesSlowNumMeasurementsMan.SetValue(ramanSettings['numPoints']) self.TimeSeriesSlowNumAccumulationsMan.SetValue(ramanSettings['Accumulations']) self.TimeSeriesSlowIntTimeMan.SetValue(ramanSettings['IntegrationTime (s)']) self.TimeSeriesSlowModeMan.SetValueNumeric(0) self.TimeSeriesSlowNumMan.SetValue(0) self.TimeSeriesSlowStartMan.OperateTrigger() sleep(0.1) t1 = time() while True: self.TimeSeriesSlowActivityMan.Update() valid, act = self.TimeSeriesSlowActivityMan.GetSingleValueAsString() if act=="Waiting for next Measurement": break else: sleep(0.02) if time()-t1>3.: print("Waiting for measurement ready...") t1 = time() def initateSilentSpectrumAcquisition(self, ramanSettings): self.advSpec.setDatasetPath(ramanSettings['path']) self.doAutoFocus = ramanSettings['Autofocus'] self.advSpec.createTmpSpecFolder() state = self.BeamPathState.GetValue() if state == 'Video': self.MicroscopeIdle.SetValue('BeamPath|SetStateRaman') self.BeamPathSetRamanState.OperateTrigger() self.SingleSpecIntegrationTimeMan.SetValue(ramanSettings['IntegrationTime (s)']) self.SingleSpecNumAccsMan.SetValue(ramanSettings['Accumulations']) def triggerTimeSeriesMeasurement(self, num): assert self.timeseries self.TimeSeriesSlowNextMan.OperateTrigger() # Wait until sequencer has finished sleep(0.1) t1 = time() while True: ind = self.TimeSeriesSlowIndNextMan.GetValue() if ind>num: break else: sleep(0.02) if time()-t1>3.: print("Waiting for next index...") t1 = time() while True: valid, act = self.TimeSeriesSlowActivityMan.GetSingleValueAsString() if act=="Waiting for next Measurement": break else: sleep(0.02) if time()-t1>3.: print("Waiting for measurement ready...") t1 = time() if num==self.timeseries-1: self.timeseries = False def doSpectralAutoFocus(self): assert self.advancedInterface self.AutoFocusMan.OperateTrigger() self.waitForSequencerToFinish() def acquireSilentSpectrum(self, num): assert self.advancedInterface self.DoSilentSpectrum.SetValue(True) self.SequencerStartTrigger.OperateTrigger() self.waitForSequencerToFinish() out_spec = self.SilentSpecText.GetValue() out_spec = out_spec.split('\n') self.advSpec.registerNewSpectrum(out_spec, num) return out_spec def waitForSequencerToFinish(self): while True: self.SequencerBusyStatus.Update() Busy = self.SequencerBusyStatus.GetSingleValueAsInt()[1] if not Busy: break