# -*- 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 from ramanbase import RamanBase from socket import gethostname class WITecCOM(RamanBase): CLSID = "{C45E77CE-3D66-489A-B5E2-159F443BD1AA}" def __init__(self, hostname=None): super().__init__() if hostname is None: hostname = gethostname() self.IBUCSAccess = win32com.client.DispatchEx(self.CLSID, machine=hostname, clsctx=pythoncom.CLSCTX_REMOTE_SERVER) 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') 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.TimeSeriesSlowNameInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|Naming|DataName") 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.TimeSeriesSlowNumInterface = IBUCSCore.GetSubSystemDefaultInterface("UserParameters|SequencerTimeSeriesSlow|Naming|DataNumber") 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') self.connected = True return True 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() self.PosXFloatMan.SetValue(x) self.PosYFloatMan.SetValue(y) self.GoToTrigger.OperateTrigger() # 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.): if ((time()-t0>2) and max(abs(curpos[0]-initpos[0]), abs(curpos[1]-initpos[1]))10.): print("WARNING: signal ignored; time: {} s, x, y: {}, {}, curPos: {}, initPos: {}".format((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): """ 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 initiateTimeSeriesScan(self, label, numberofscans, accumulations, integrtime): assert self.connected self.timeseries = numberofscans self.TimeSeriesSlowNameMan.SetValue(label) self.TimeSeriesSlowNumMeasurementsMan.SetValue(numberofscans) self.TimeSeriesSlowNumAccumulationsMan.SetValue(accumulations) self.TimeSeriesSlowIntTimeMan.SetValue(integrtime) 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 nextTimeSeriesScan(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