Commit ac123cc1 authored by Lars Bittrich's avatar Lars Bittrich
Browse files

Initial commit of current project status. Some modification will be needed...

Initial commit of current project status. Some modification will be needed before this will work without manual adaptations…
parent b20a8281
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
# GEPARD

GEPARD - Gepard-Enabled PARticle Detection for Raman microscopes.

Copyright (C) 2018  Lars Bittrich and Josef Brandt, Leibniz-Institut für 
Polymerforschung Dresden e. V. <bittrich-lars@ipfdd.de> 

Requirements:

* python 3.6, PyQt5, OpenCV 3.4.1, numpy 1.14, scikit-image 0.13.1, scipy 1.1.0,
  win32com, pythoncom, cython 0.28
  
* we advise the use of Anaconda (python 3.6): https://www.anaconda.com/download
  this package contains most of the python libraries
  however, opencv and scikit-image are missing
  start anaconda prompt and install opencv:
  pip install opencv-python
  conda install scikit-image

* we recommend working with a 64bit OS and also a python interpreter compiled 
  for 64bit as many use cases require a lot of memory (16 GB better 32 GB 
  recommended)
  
* the tsp module in externalmodules can be built with
  python setuptsp.py
  please note: for this step a valid compiler needs to be installed in the 
  system; Otherwise use the precompiled tsp-module
  
If you plan on using the WITec Raman interface to control your device, please
note: You use this interface at your OWN RISK! Make sure, that no obstacles
block the objective and that you UNDERSTAND and VALIDATE the code, that controls
the microscope! Start with "witectesting.py", which should read and move within
small margins.
  
At the moment the program is an executable python script. Copy the folder with 
all its content to some place and run (e.g. using anaconda prompt):
python gepard.py

It is possible to create a windows link file, that executes python with the
gepard script as an argument and the working directory pointing to the folder
containing gepard for convenience.

WITecCOM.py

0 → 100644
+289 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
"""
GEPARD - Gepard-Enabled PARticle Detection
Copyright (C) 2018  Lars Bittrich and Josef Brandt, Leibniz-Institut für 
Polymerforschung Dresden e. V. <bittrich-lars@ipfdd.de>    

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 <https://www.gnu.org/licenses/>.
"""

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}"
    hostname = "unknown"
    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.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")
        # Get Float Manipulators
        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')
        
        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')
        
        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]))<epsxy) or (time()-t0>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)<epsz)  or (time()-t0>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

        
 No newline at end of file

dataset.py

0 → 100644
+251 −0

File added.

Preview size limit exceeded, changes collapsed.

detectionview.py

0 → 100755
+612 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −0

Empty file added.

Loading