|
# COPYRIGHT:
|
|
# The Leginon software is Copyright 2003
|
|
# The Scripps Research Institute, La Jolla, CA
|
|
# For terms of the license agreement
|
|
# see http://ami.scripps.edu/software/leginon-license
|
|
|
|
import tem
|
|
import time
|
|
import sys
|
|
try:
|
|
import nidaq
|
|
except:
|
|
nidaq = None
|
|
use_nidaq = False
|
|
|
|
try:
|
|
import pythoncom
|
|
import win32com.client
|
|
import winerror
|
|
except ImportError:
|
|
pass
|
|
|
|
# This scale convert beam tilt readout in radian to
|
|
# Tecnai or TEM Scripting Illumination.RotationCenter value
|
|
# Depending on the version, this may be 1.0 or closer to 6
|
|
rotation_center_scale = 1.0
|
|
|
|
# if a stage position movement is less than the following, then ignore it
|
|
minimum_stage = {
|
|
'x': 5e-8,
|
|
'y': 5e-8,
|
|
'z': 5e-8,
|
|
'a': 6e-5,
|
|
'b': 6e-5,
|
|
}
|
|
|
|
class MagnificationsUninitialized(Exception):
|
|
pass
|
|
|
|
class Tecnai(tem.TEM):
|
|
name = 'Tecnai'
|
|
def __init__(self):
|
|
tem.TEM.__init__(self)
|
|
self.correctedstage = True
|
|
pythoncom.CoInitializeEx(pythoncom.COINIT_MULTITHREADED)
|
|
|
|
self.tecnai = None
|
|
# should determine this in updatecom instead of guessing it here
|
|
for comname in ('Tecnai.Instrument', 'TEMScripting.Instrument.1'):
|
|
try:
|
|
self.tecnai = win32com.client.Dispatch(comname)
|
|
break
|
|
except:
|
|
pass
|
|
|
|
if self.tecnai is None:
|
|
raise RuntimeError('unable to initialize Tecnai interface, %s' % msg)
|
|
|
|
try:
|
|
self.tom = win32com.client.Dispatch('TEM.Instrument.1')
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
print 'unable to initialize TOM Moniker interface, %s' % msg
|
|
self.tom = None
|
|
|
|
try:
|
|
self.lowdose = win32com.client.Dispatch('LDServer.LdSrv')
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
print 'unable to initialize low dose interface, %s' % msg
|
|
self.lowdose = None
|
|
|
|
try:
|
|
self.exposure = win32com.client.Dispatch('adaExp.TAdaExp',
|
|
clsctx=pythoncom.CLSCTX_LOCAL_SERVER)
|
|
except:
|
|
self.exposure = None
|
|
|
|
self.magnifications = []
|
|
self.mainscreenscale = 44000.0 / 50000.0
|
|
|
|
## figure out which intensity property to use
|
|
## try to move this to installation
|
|
try:
|
|
ia = self.tecnai.Illumination.IlluminatedArea
|
|
except:
|
|
self.intensity_prop = 'Intensity'
|
|
else:
|
|
self.intensity_prop = 'IlluminatedArea'
|
|
|
|
## figure out which gauge to use
|
|
## try to move this to installation
|
|
gauges_to_try = ['PPc1', 'P4', 'IGP1']
|
|
self.pressure_prop = None
|
|
for gauge in gauges_to_try:
|
|
try:
|
|
p = self.tecnai.Vacuum.Gauges(gauge)
|
|
self.pressure_prop = gauge
|
|
except:
|
|
pass
|
|
|
|
def getMagnificationsInitialized(self):
|
|
if self.magnifications:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def setCorrectedStagePosition(self, value):
|
|
self.correctedstage = bool(value)
|
|
return self.correctedstage
|
|
|
|
def getCorrectedStagePosition(self):
|
|
return self.correctedstage
|
|
|
|
def checkStagePosition(self, position):
|
|
current = self.getStagePosition()
|
|
bigenough = {}
|
|
for axis in ('x', 'y', 'z', 'a', 'b'):
|
|
if axis in position:
|
|
delta = abs(position[axis] - current[axis])
|
|
if delta > minimum_stage[axis]:
|
|
bigenough[axis] = position[axis]
|
|
return bigenough
|
|
|
|
def setStagePosition(self, value):
|
|
# pre-position x and y (maybe others later)
|
|
value = self.checkStagePosition(value)
|
|
if not value:
|
|
return
|
|
if self.correctedstage:
|
|
delta = 2e-6
|
|
stagenow = self.getStagePosition()
|
|
# calculate pre-position
|
|
prevalue = {}
|
|
for axis in ('x','y','z'):
|
|
if axis in value:
|
|
prevalue[axis] = value[axis] - delta
|
|
if prevalue:
|
|
self._setStagePosition(prevalue)
|
|
return self._setStagePosition(value)
|
|
|
|
def setStageSpeed(self, value):
|
|
self.tom.Stage.Speed = value
|
|
|
|
def getStageSpeed(self):
|
|
return self.tom.Stage.Speed
|
|
|
|
def normalizeLens(self, lens = 'all'):
|
|
if lens == 'all':
|
|
self.tecnai.NormalizeAll()
|
|
elif lens == 'objective':
|
|
self.tecnai.Projection.Normalize(win32com.client.constants.pnmObjective)
|
|
elif lens == 'projector':
|
|
self.tecnai.Projection.Normalize(win32com.client.constants.pnmProjector)
|
|
elif lens == 'allprojection':
|
|
self.tecnai.Projection.Normalize(win32com.client.constants.pnmAll)
|
|
elif lens == 'spotsize':
|
|
self.tecnai.Illumination.Normalize(win32com.client.constants.nmSpotsize)
|
|
elif lens == 'intensity':
|
|
self.tecnai.Illumination.Normalize(win32com.client.constants.nmIntensity)
|
|
elif lens == 'condenser':
|
|
self.tecnai.Illumination.Normalize(win32com.client.constants.nmCondenser)
|
|
elif lens == 'minicondenser':
|
|
self.tecnai.Illumination.Normalize(win32com.client.constants.nmMiniCondenser)
|
|
elif lens == 'objectivepole':
|
|
self.tecnai.Illumination.Normalize(win32com.client.constants.nmObjectivePole)
|
|
elif lens == 'allillumination':
|
|
self.tecnai.Illumination.Normalize(win32com.client.constants.nmAll)
|
|
else:
|
|
raise ValueError
|
|
|
|
def getScreenCurrent(self):
|
|
return float(self.tecnai.Camera.ScreenCurrent)
|
|
|
|
def getGunTilt(self):
|
|
value = {'x': None, 'y': None}
|
|
value['x'] = float(self.tecnai.Gun.Tilt.X)
|
|
value['y'] = float(self.tecnai.Gun.Tilt.Y)
|
|
|
|
return value
|
|
|
|
def setGunTilt(self, vector, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
try:
|
|
vector['x'] += self.tecnai.Gun.Tilt.X
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vector['y'] += self.tecnai.Gun.Tilt.Y
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
vec = self.tecnai.Gun.Tilt
|
|
try:
|
|
vec.X = vector['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vec.Y = vector['y']
|
|
except KeyError:
|
|
pass
|
|
self.tecnai.Gun.Tilt = vec
|
|
|
|
def getGunShift(self):
|
|
value = {'x': None, 'y': None}
|
|
value['x'] = self.tecnai.Gun.Shift.X
|
|
value['y'] = self.tecnai.Gun.Shift.Y
|
|
|
|
return value
|
|
|
|
def setGunShift(self, vector, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
try:
|
|
vector['x'] += self.tecnai.Gun.Shift.X
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vector['y'] += self.tecnai.Gun.Shift.Y
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
vec = self.tecnai.Gun.Shift
|
|
try:
|
|
vec.X = vector['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vec.Y = vector['y']
|
|
except KeyError:
|
|
pass
|
|
self.tecnai.Gun.Shift = vec
|
|
|
|
def getHighTensionStates(self):
|
|
return ['off', 'on', 'disabled']
|
|
|
|
def getHighTensionState(self):
|
|
state = self.tecnai.Gun.HTState
|
|
if state == win32com.client.constants.htOff:
|
|
return 'off'
|
|
elif state == win32com.client.constants.htOn:
|
|
return 'on'
|
|
elif state == win32com.client.constants.htDisabled:
|
|
return 'disabled'
|
|
else:
|
|
raise RuntimeError('unknown high tension state')
|
|
|
|
def getHighTension(self):
|
|
return float(self.tecnai.Gun.HTValue)
|
|
|
|
def setHighTension(self, ht):
|
|
self.tecnai.Gun.HTValue = ht
|
|
|
|
def getIntensity(self):
|
|
intensity = getattr(self.tecnai.Illumination, self.intensity_prop)
|
|
return float(intensity)
|
|
|
|
def setIntensity(self, intensity, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
intensity += getattr(self.tecnai.Illumination, self.intensity_prop)
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
setattr(self.tecnai.Illumination, self.intensity_prop, intensity)
|
|
|
|
def getDarkFieldMode(self):
|
|
if self.tecnai.Illumination.DFMode == win32com.client.constants.dfOff:
|
|
return 'off'
|
|
elif self.tecnai.Illumination.DFMode == win32com.client.constants.dfCartesian:
|
|
return 'cartesian'
|
|
elif self.tecnai.Illumination.DFMode == win32com.client.constants.dfConical:
|
|
return 'conical'
|
|
else:
|
|
raise SystemError
|
|
|
|
def setDarkFieldMode(self, mode):
|
|
if mode == 'off':
|
|
self.tecnai.Illumination.DFMode = win32com.client.constants.dfOff
|
|
elif mode == 'cartesian':
|
|
self.tecnai.Illumination.DFMode = win32com.client.constants.dfCartesian
|
|
elif mode == 'conical':
|
|
self.tecnai.Illumination.DFMode = win32com.client.constants.dfConical
|
|
else:
|
|
raise ValueError
|
|
|
|
def getBeamBlank(self):
|
|
if self.tecnai.Illumination.BeamBlanked == 0:
|
|
return 'off'
|
|
elif self.tecnai.Illumination.BeamBlanked == 1:
|
|
return 'on'
|
|
else:
|
|
raise SystemError
|
|
|
|
def setBeamBlank(self, bb):
|
|
if bb == 'off' :
|
|
self.tecnai.Illumination.BeamBlanked = 0
|
|
elif bb == 'on':
|
|
self.tecnai.Illumination.BeamBlanked = 1
|
|
else:
|
|
raise ValueError
|
|
|
|
def getStigmator(self):
|
|
value = {'condenser': {'x': None, 'y': None},
|
|
'objective': {'x': None, 'y': None},
|
|
'diffraction': {'x': None, 'y': None}}
|
|
value['condenser']['x'] = \
|
|
float(self.tecnai.Illumination.CondenserStigmator.X)
|
|
value['condenser']['y'] = \
|
|
float(self.tecnai.Illumination.CondenserStigmator.Y)
|
|
value['objective']['x'] = \
|
|
float(self.tecnai.Projection.ObjectiveStigmator.X)
|
|
value['objective']['y'] = \
|
|
float(self.tecnai.Projection.ObjectiveStigmator.Y)
|
|
value['diffraction']['x'] = \
|
|
float(self.tecnai.Projection.DiffractionStigmator.X)
|
|
value['diffraction']['y'] = \
|
|
float(self.tecnai.Projection.DiffractionStigmator.Y)
|
|
|
|
return value
|
|
|
|
def setStigmator(self, stigs, relative = 'absolute'):
|
|
for key in stigs.keys():
|
|
if key == 'condenser':
|
|
stigmator = self.tecnai.Illumination.CondenserStigmator
|
|
elif key == 'objective':
|
|
stigmator = self.tecnai.Projection.ObjectiveStigmator
|
|
elif key == 'diffraction':
|
|
stigmator = self.tecnai.Projection.DiffractionStigmator
|
|
else:
|
|
raise ValueError
|
|
|
|
if relative == 'relative':
|
|
try:
|
|
stigs[key]['x'] += stigmator.X
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
stigs[key]['y'] += stigmator.Y
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
try:
|
|
stigmator.X = stigs[key]['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
stigmator.Y = stigs[key]['y']
|
|
except KeyError:
|
|
pass
|
|
|
|
if key == 'condenser':
|
|
self.tecnai.Illumination.CondenserStigmator = stigmator
|
|
elif key == 'objective':
|
|
self.tecnai.Projection.ObjectiveStigmator = stigmator
|
|
elif key == 'diffraction':
|
|
self.tecnai.Projection.DiffractionStigmator = stigmator
|
|
else:
|
|
raise ValueError
|
|
|
|
def getSpotSize(self):
|
|
return int(self.tecnai.Illumination.SpotsizeIndex)
|
|
|
|
def setSpotSize(self, ss, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
ss += self.tecnai.Illumination.SpotsizeIndex
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
self.tecnai.Illumination.SpotsizeIndex = ss
|
|
|
|
def getBeamTilt(self):
|
|
value = {'x': None, 'y': None}
|
|
value['x'] = float(self.tecnai.Illumination.RotationCenter.X) / rotation_center_scale
|
|
value['y'] = float(self.tecnai.Illumination.RotationCenter.Y) / rotation_center_scale
|
|
|
|
return value
|
|
|
|
def setBeamTilt(self, vector, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
original_vector = self.getBeamTilt()
|
|
try:
|
|
vector['x'] += original_vector['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vector['y'] += original_vector['y']
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
vec = self.tecnai.Illumination.RotationCenter
|
|
try:
|
|
vec.X = vector['x'] * rotation_center_scale
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vec.Y = vector['y'] * rotation_center_scale
|
|
except KeyError:
|
|
pass
|
|
self.tecnai.Illumination.RotationCenter = vec
|
|
|
|
def getBeamShift(self):
|
|
value = {'x': None, 'y': None}
|
|
value['x'] = float(self.tom.Illumination.BeamShiftPhysical.X)
|
|
value['y'] = float(self.tom.Illumination.BeamShiftPhysical.Y)
|
|
|
|
return value
|
|
|
|
def setBeamShift(self, vector, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
try:
|
|
vector['x'] += self.tom.Illumination.BeamShiftPhysical.X
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vector['y'] += self.tom.Illumination.BeamShiftPhysical.Y
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
vec = self.tom.Illumination.BeamShiftPhysical
|
|
try:
|
|
vec.X = vector['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vec.Y = vector['y']
|
|
except KeyError:
|
|
pass
|
|
self.tom.Illumination.BeamShiftPhysical = vec
|
|
|
|
def getImageShift(self):
|
|
value = {'x': None, 'y': None}
|
|
value['x'] = float(self.tecnai.Projection.ImageBeamShift.X)
|
|
value['y'] = float(self.tecnai.Projection.ImageBeamShift.Y)
|
|
return value
|
|
|
|
def setImageShift(self, vector, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
try:
|
|
vector['x'] += self.tecnai.Projection.ImageBeamShift.X
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vector['y'] += self.tecnai.Projection.ImageBeamShift.Y
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
vec = self.tecnai.Projection.ImageBeamShift
|
|
try:
|
|
vec.X = vector['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vec.Y = vector['y']
|
|
except KeyError:
|
|
pass
|
|
self.tecnai.Projection.ImageBeamShift = vec
|
|
|
|
def getRawImageShift(self):
|
|
value = {'x': None, 'y': None}
|
|
value['x'] = float(self.tecnai.Projection.ImageShift.X)
|
|
value['y'] = float(self.tecnai.Projection.ImageShift.Y)
|
|
return value
|
|
|
|
def setRawImageShift(self, vector, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
try:
|
|
vector['x'] += self.tecnai.Projection.ImageShift.X
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vector['y'] += self.tecnai.Projection.ImageShift.Y
|
|
except KeyError:
|
|
pass
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
vec = self.tecnai.Projection.ImageShift
|
|
try:
|
|
vec.X = vector['x']
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
vec.Y = vector['y']
|
|
except KeyError:
|
|
pass
|
|
self.tecnai.Projection.ImageShift = vec
|
|
|
|
def getDefocus(self):
|
|
return float(self.tecnai.Projection.Defocus)
|
|
|
|
def setDefocus(self, defocus, relative = 'absolute'):
|
|
if relative == 'relative':
|
|
defocus += self.tecnai.Projection.Defocus
|
|
elif relative == 'absolute':
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
self.tecnai.Projection.Defocus = defocus
|
|
|
|
def resetDefocus(self):
|
|
self.tecnai.Projection.ResetDefocus()
|
|
|
|
def getMagnification(self, index=None):
|
|
if index is None:
|
|
return int(round(self.tecnai.Projection.Magnification))
|
|
elif not self.getMagnificationsInitialized():
|
|
raise MagnificationsUninitialized
|
|
else:
|
|
try:
|
|
return self.magnifications[index]
|
|
except IndexError:
|
|
raise ValueError('invalid magnification index')
|
|
|
|
def getMainScreenMagnification(self):
|
|
return int(round(self.tecnai.Projection.Magnification*self.mainscreenscale))
|
|
|
|
def getMainScreenScale(self):
|
|
return self.mainscreenscale
|
|
|
|
def setMainScreenScale(self, mainscreenscale):
|
|
self.mainscreenscale = mainscreenscale
|
|
|
|
def setMagnification(self, mag):
|
|
if not self.getMagnificationsInitialized():
|
|
raise MagnificationsUninitialized
|
|
|
|
try:
|
|
mag = int(round(mag))
|
|
except TypeError:
|
|
try:
|
|
mag = int(mag)
|
|
except:
|
|
raise TypeError
|
|
|
|
try:
|
|
index = self.magnifications.index(mag)
|
|
except ValueError:
|
|
raise ValueError('invalid magnification')
|
|
|
|
self.setMagnificationIndex(index)
|
|
return
|
|
|
|
def getMagnificationIndex(self, magnification=None):
|
|
if magnification is None:
|
|
return self.tecnai.Projection.MagnificationIndex - 1
|
|
elif not self.getMagnificationsInitialized():
|
|
raise MagnificationsUninitialized
|
|
else:
|
|
try:
|
|
return self.magnifications.index(magnification)
|
|
except IndexError:
|
|
raise ValueError('invalid magnification')
|
|
|
|
def setMagnificationIndex(self, value):
|
|
self.tecnai.Projection.MagnificationIndex = value + 1
|
|
|
|
def getMagnifications(self):
|
|
return self.magnifications
|
|
|
|
def setMagnifications(self, magnifications):
|
|
self.magnifications = magnifications
|
|
|
|
def findMagnifications(self):
|
|
savedindex = self.getMagnificationIndex()
|
|
magnifications = []
|
|
previousindex = None
|
|
index = 0
|
|
while True:
|
|
self.setMagnificationIndex(index)
|
|
index = self.getMagnificationIndex()
|
|
if index == previousindex:
|
|
break
|
|
magnifications.append(self.getMagnification())
|
|
previousindex = index
|
|
index += 1
|
|
self.setMagnifications(magnifications)
|
|
self.setMagnificationIndex(savedindex)
|
|
|
|
def getStagePosition(self):
|
|
value = {}
|
|
value['x'] = float(self.tecnai.Stage.Position.X)
|
|
value['y'] = float(self.tecnai.Stage.Position.Y)
|
|
value['z'] = float(self.tecnai.Stage.Position.Z)
|
|
value['a'] = float(self.tecnai.Stage.Position.A)
|
|
if use_nidaq:
|
|
value['b'] = nidaq.getBeta() * 3.14159 / 180.0
|
|
else:
|
|
try:
|
|
value['b'] = float(self.tecnai.Stage.Position.B)
|
|
except:
|
|
pass
|
|
return value
|
|
|
|
def _setStagePosition(self, position, relative = 'absolute'):
|
|
# tolerance = 1.0e-4
|
|
# polltime = 0.01
|
|
|
|
if relative == 'relative':
|
|
for key in position:
|
|
position[key] += getattr(self.tecnai.Stage.Position, key.upper())
|
|
elif relative != 'absolute':
|
|
raise ValueError
|
|
|
|
pos = self.tecnai.Stage.Position
|
|
|
|
axes = 0
|
|
for key, value in position.items():
|
|
if use_nidaq and key == 'b':
|
|
deg = value / 3.14159 * 180.0
|
|
nidaq.setBeta(deg)
|
|
continue
|
|
setattr(pos, key.upper(), value)
|
|
axes |= getattr(win32com.client.constants, 'axis' + key.upper())
|
|
|
|
if axes == 0:
|
|
return
|
|
try:
|
|
self.tecnai.Stage.Goto(pos, axes)
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
#print 'Stage.Goto failed with error %d: %s' % (hr, msg)
|
|
if exc is None:
|
|
raise ValueError('no extended error information, assuming stage limit was hit')
|
|
else:
|
|
wcode, source, text, helpFile, helpId, scode = exc
|
|
if winerror.SUCCEEDED(wcode) and text is None:
|
|
raise ValueError('no extended error information, assuming stage limit was hit')
|
|
else:
|
|
raise RuntimeError(text)
|
|
|
|
# for key in position:
|
|
# while abs(getattr(self.tecnai.Stage.Position, key.upper())
|
|
# - getattr(pos, key.upper())) > tolerance:
|
|
# time.sleep(polltime)
|
|
|
|
def getLowDoseStates(self):
|
|
return ['on', 'off', 'disabled']
|
|
|
|
def getLowDose(self):
|
|
try:
|
|
if (self.lowdose.IsInitialized == 1) and (self.lowdose.LowDoseActive == win32com.client.constants.IsOn):
|
|
return 'on'
|
|
else:
|
|
return 'off'
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
if exc is None:
|
|
# No extended error information, assuming low dose is disabled
|
|
return 'disabled'
|
|
else:
|
|
wcode, source, text, helpFile, helpId, scode = exc
|
|
if winerror.SUCCEEDED(wcode) and text is None:
|
|
# No extended error information, assuming low dose is disabled
|
|
return 'disabled'
|
|
else:
|
|
raise RuntimeError(text)
|
|
|
|
def setLowDose(self, ld):
|
|
try:
|
|
if ld == 'off' :
|
|
self.lowdose.LowDoseActive = win32com.client.constants.IsOff
|
|
elif ld == 'on':
|
|
if self.lowdose.IsInitialized == 0:
|
|
raise RuntimeError('Low dose is not initialized')
|
|
else:
|
|
self.lowdose.LowDoseActive = win32com.client.constants.IsOn
|
|
else:
|
|
raise ValueError
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
if exc is None:
|
|
# No extended error information, assuming low dose is disenabled
|
|
raise RuntimeError('Low dose is not enabled')
|
|
else:
|
|
wcode, source, text, helpFile, helpId, scode = exc
|
|
if winerror.SUCCEEDED(wcode) and text is None:
|
|
# No extended error information, assuming low dose is disenabled
|
|
raise RuntimeError('Low dose is not enabled')
|
|
else:
|
|
raise RuntimerError(text)
|
|
|
|
def getLowDoseModes(self):
|
|
return ['exposure', 'focus1', 'focus2', 'search', 'unknown', 'disabled']
|
|
|
|
def getLowDoseMode(self):
|
|
try:
|
|
if self.lowdose.LowDoseState == win32com.client.constants.eExposure:
|
|
return 'exposure'
|
|
elif self.lowdose.LowDoseState == win32com.client.constants.eFocus1:
|
|
return 'focus1'
|
|
elif self.lowdose.LowDoseState == win32com.client.constants.eFocus2:
|
|
return 'focus2'
|
|
elif self.lowdose.LowDoseState == win32com.client.constants.eSearch:
|
|
return 'search'
|
|
else:
|
|
return 'unknown'
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
if exc is None:
|
|
# No extended error information, assuming low dose is disenabled
|
|
return 'disabled'
|
|
else:
|
|
wcode, source, text, helpFile, helpId, scode = exc
|
|
if winerror.SUCCEEDED(wcode) and text is None:
|
|
# No extended error information, assuming low dose is disenabled
|
|
return 'disabled'
|
|
else:
|
|
raise RuntimerError(text)
|
|
|
|
def setLowDoseMode(self, mode):
|
|
try:
|
|
if mode == 'exposure':
|
|
self.lowdose.LowDoseState = win32com.client.constants.eExposure
|
|
elif mode == 'focus1':
|
|
self.lowdose.LowDoseState = win32com.client.constants.eFocus1
|
|
elif mode == 'focus2':
|
|
self.lowdose.LowDoseState = win32com.client.constants.eFocus2
|
|
elif mode == 'search':
|
|
self.lowdose.LowDoseState = win32com.client.constants.eSearch
|
|
else:
|
|
raise ValueError
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
if exc is None:
|
|
# No extended error information, assuming low dose is disenabled
|
|
raise RuntimeError('Low dose is not enabled')
|
|
else:
|
|
wcode, source, text, helpFile, helpId, scode = exc
|
|
if winerror.SUCCEEDED(wcode) and text is None:
|
|
# No extended error information, assuming low dose is disenabled
|
|
raise RuntimeError('Low dose is not enabled')
|
|
else:
|
|
raise RuntimerError(text)
|
|
|
|
def getDiffractionMode(self):
|
|
if self.tecnai.Projection.Mode == win32com.client.constants.pmImaging:
|
|
return 'imaging'
|
|
elif self.tecnai.Projection.Mode == win32com.client.constants.pmDiffraction:
|
|
return 'diffraction'
|
|
else:
|
|
raise SystemError
|
|
|
|
def setDiffractionMode(self, mode):
|
|
if mode == 'imaging':
|
|
self.tecnai.Projection.Mode = win32com.client.constants.pmImaging
|
|
elif mode == 'diffraction':
|
|
self.tecnai.Projection.Mode = win32com.client.constants.pmDiffraction
|
|
else:
|
|
raise ValueError
|
|
|
|
return 0
|
|
|
|
def getShutterPositions(self):
|
|
return ['open', 'closed']
|
|
|
|
def setShutter(self, state):
|
|
if self.exposure is None:
|
|
raise RuntimeError('setShutter requires adaExp')
|
|
if state == 'open':
|
|
if self.exposure.OpenShutter != 0:
|
|
raise RuntimeError('Open shutter failed')
|
|
elif state == 'closed':
|
|
if self.exposure.CloseShutter != 0:
|
|
raise RuntimeError('Close shutter failed')
|
|
else:
|
|
raise ValueError('Invalid value for setShutter \'%s\'' % (state,))
|
|
|
|
def getShutter(self):
|
|
if self.exposure is None:
|
|
raise RuntimeError('getShutter requires adaExp')
|
|
status = self.exposure.ShutterStatus
|
|
if status:
|
|
return 'closed'
|
|
else:
|
|
return 'open'
|
|
|
|
def getExternalShutterStates(self):
|
|
return ['connected', 'disconnected']
|
|
|
|
def setExternalShutter(self, state):
|
|
if self.exposure is None:
|
|
raise RuntimeError('setExternalShutter requires adaExp')
|
|
if state == 'connected':
|
|
if self.exposure.ConnectExternalShutter != 0:
|
|
raise RuntimeError('Connect shutter failed')
|
|
elif state == 'disconnected':
|
|
if self.exposure.DisconnectExternalShutter != 0:
|
|
raise RuntimeError('Disconnect shutter failed')
|
|
else:
|
|
raise ValueError('Invalid value for setExternalShutter \'%s\'' % (state,))
|
|
|
|
def getExternalShutter(self):
|
|
if self.exposure is None:
|
|
raise RuntimeError('getExternalShutter requires adaExp')
|
|
status = self.exposure.ExternalShutterStatus
|
|
if status:
|
|
return 'connected'
|
|
else:
|
|
return 'disconnected'
|
|
|
|
def preFilmExposure(self, value):
|
|
if self.exposure is None:
|
|
raise RuntimeError('preFilmExposure requires adaExp')
|
|
if not value:
|
|
return
|
|
|
|
if self.getFilmStock() < 1:
|
|
raise RuntimeError('No film to take exposure')
|
|
|
|
if self.exposure.LoadPlate != 0:
|
|
raise RuntimeError('Load plate failed')
|
|
if self.exposure.ExposePlateLabel != 0:
|
|
raise RuntimeError('Expose plate label failed')
|
|
|
|
def postFilmExposure(self, value):
|
|
if self.exposure is None:
|
|
raise RuntimeError('postFilmExposure requires adaExp')
|
|
if not value:
|
|
return
|
|
|
|
if self.exposure.UnloadPlate != 0:
|
|
raise RuntimeError('Unload plate failed')
|
|
# if self.exposure.UpdateExposureNumber != 0:
|
|
# raise RuntimeError('Update exposure number failed')
|
|
|
|
def filmExposure(self, value):
|
|
if not value:
|
|
return
|
|
|
|
'''
|
|
if self.getFilmStock() < 1:
|
|
raise RuntimeError('No film to take exposure')
|
|
|
|
if self.exposure.CloseShutter != 0:
|
|
raise RuntimeError('Close shutter (pre-exposure) failed')
|
|
if self.exposure.DisconnectExternalShutter != 0:
|
|
raise RuntimeError('Disconnect external shutter failed')
|
|
if self.exposure.LoadPlate != 0:
|
|
raise RuntimeError('Load plate failed')
|
|
if self.exposure.ExposePlateLabel != 0:
|
|
raise RuntimeError('Expose plate label failed')
|
|
if self.exposure.OpenShutter != 0:
|
|
raise RuntimeError('Open (pre-exposure) shutter failed')
|
|
'''
|
|
|
|
self.tecnai.Camera.TakeExposure()
|
|
|
|
'''
|
|
if self.exposure.CloseShutter != 0:
|
|
raise RuntimeError('Close shutter (post-exposure) failed')
|
|
if self.exposure.UnloadPlate != 0:
|
|
raise RuntimeError('Unload plate failed')
|
|
if self.exposure.UpdateExposureNumber != 0:
|
|
raise RuntimeError('Update exposure number failed')
|
|
if self.exposure.ConnectExternalShutter != 0:
|
|
raise RuntimeError('Connect external shutter failed')
|
|
if self.exposure.OpenShutter != 0:
|
|
raise RuntimeError('Open shutter (post-exposure) failed')
|
|
'''
|
|
|
|
def getMainScreenPositions(self):
|
|
return ['up', 'down', 'unknown']
|
|
|
|
def getMainScreenPosition(self):
|
|
timeout = 5.0
|
|
sleeptime = 0.05
|
|
while (self.tecnai.Camera.MainScreen
|
|
== win32com.client.constants.spUnknown):
|
|
time.sleep(sleeptime)
|
|
if self.tecnai.Camera.MainScreen != win32com.client.constants.spUnknown:
|
|
break
|
|
timeout -= sleeptime
|
|
if timeout <= 0.0:
|
|
return 'unknown'
|
|
if self.tecnai.Camera.MainScreen == win32com.client.constants.spUp:
|
|
return 'up'
|
|
elif self.tecnai.Camera.MainScreen == win32com.client.constants.spDown:
|
|
return 'down'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def getSmallScreenPosition(self):
|
|
if self.tecnai.Camera.IsSmallScreenDown:
|
|
return 'down'
|
|
else:
|
|
return 'up'
|
|
|
|
def setMainScreenPosition(self, mode):
|
|
if mode == 'up':
|
|
self.tecnai.Camera.MainScreen = win32com.client.constants.spUp
|
|
elif mode == 'down':
|
|
self.tecnai.Camera.MainScreen = win32com.client.constants.spDown
|
|
else:
|
|
raise ValueError
|
|
time.sleep(2)
|
|
|
|
def getHolderStatus(self):
|
|
if adacom is None:
|
|
raise RuntimeError('getHolderStatus requires adaExp')
|
|
if self.exposure.SpecimenHolderInserted == adacom.constants.eInserted:
|
|
return 'inserted'
|
|
elif self.exposure.SpecimenHolderInserted == adacom.constants.eNotInserted:
|
|
return 'not inserted'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def getHolderTypes(self):
|
|
return ['no holder', 'single tilt', 'cryo', 'unknown']
|
|
|
|
def getHolderType(self):
|
|
if self.exposure is None:
|
|
raise RuntimeError('getHolderType requires adaExp')
|
|
if self.exposure.CurrentSpecimenHolderName == u'No Specimen Holder':
|
|
return 'no holder'
|
|
elif self.exposure.CurrentSpecimenHolderName == u'Single Tilt':
|
|
return 'single tilt'
|
|
elif self.exposure.CurrentSpecimenHolderName == u'ST Cryo Holder':
|
|
return 'cryo'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def setHolderType(self, holdertype):
|
|
if self.exposure is None:
|
|
raise RuntimeError('setHolderType requires adaExp')
|
|
if holdertype == 'no holder':
|
|
holderstr = u'No Specimen Holder'
|
|
elif holdertype == 'single tilt':
|
|
holderstr = u'Single Tilt'
|
|
elif holdertype == 'cryo':
|
|
holderstr = u'ST Cryo Holder'
|
|
else:
|
|
raise ValueError('invalid holder type specified')
|
|
|
|
for i in [1,2,3]:
|
|
if self.exposure.SpecimenHolderName(i) == holderstr:
|
|
self.exposure.SetCurrentSpecimenHolder(i)
|
|
return
|
|
|
|
raise SystemError('no such holder available')
|
|
|
|
def getStageStatus(self):
|
|
if adacom is None:
|
|
raise RuntimeError('getStageStatus requires adaExp')
|
|
if self.exposure.GonioLedStatus == adacom.constants.eOn:
|
|
return 'busy'
|
|
elif self.exposure.GonioLedStatus == adacom.constants.eOff:
|
|
return 'ready'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def getTurboPump(self):
|
|
if adacom is None:
|
|
raise RuntimeError('getTurboPump requires adaExp')
|
|
if self.exposure.GetTmpStatus == adacom.constants.eOn:
|
|
return 'on'
|
|
elif self.exposure.GetTmpStatus == adacom.constants.eOff:
|
|
return 'off'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def setTurboPump(self, mode):
|
|
if adacom is None:
|
|
raise RuntimeError('setTurboPump requires adaExp')
|
|
if mode == 'on':
|
|
self.exposure.SetTmp(adacom.constants.eOn)
|
|
elif mode == 'off':
|
|
self.exposure.SetTmp(adacom.constants.eOff)
|
|
else:
|
|
raise ValueError
|
|
|
|
def getColumnValvePositions(self):
|
|
return ['open', 'closed']
|
|
|
|
def getColumnValvePosition(self):
|
|
if self.tecnai.Vacuum.ColumnValvesOpen:
|
|
return 'open'
|
|
else:
|
|
return 'closed'
|
|
|
|
def setColumnValvePosition(self, state):
|
|
position = self.getColumnValvePosition()
|
|
if position == 'open' and state == 'closed':
|
|
self.tecnai.Vacuum.ColumnValvesOpen = 0
|
|
time.sleep(2)
|
|
elif position == 'closed' and state == 'open':
|
|
self.tecnai.Vacuum.ColumnValvesOpen = 1
|
|
time.sleep(3) # extra time for camera retract
|
|
elif state in ('open','closed'):
|
|
pass
|
|
else:
|
|
raise ValueError
|
|
|
|
def getVacuumStatus(self):
|
|
status = self.tecnai.Vacuum.Status
|
|
if status == win32com.client.constants.vsOff:
|
|
return 'off'
|
|
elif status == win32com.client.constants.vsCameraAir:
|
|
return 'camera'
|
|
elif status == win32com.client.constants.vsBusy:
|
|
return 'busy'
|
|
elif status == win32com.client.constants.vsReady:
|
|
return 'ready'
|
|
elif status == win32com.client.constants.vsUnknown:
|
|
return 'unknown'
|
|
elif status == win32com.client.constants.vsElse:
|
|
return 'else'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def getColumnPressure(self):
|
|
if self.pressure_prop is None:
|
|
return 0.0
|
|
return float(self.tecnai.Vacuum.Gauges(self.pressure_prop).Pressure)
|
|
|
|
def getObjectiveExcitation(self):
|
|
return float(self.tecnai.Projection.ObjectiveExcitation)
|
|
|
|
def getFocus(self):
|
|
return float(self.tecnai.Projection.Focus)
|
|
|
|
def setFocus(self, value):
|
|
self.tecnai.Projection.Focus = value
|
|
|
|
def getFilmStock(self):
|
|
return self.tecnai.Camera.Stock
|
|
|
|
def getFilmExposureNumber(self):
|
|
return self.tecnai.Camera.ExposureNumber % 100000
|
|
|
|
def setFilmExposureNumber(self, value):
|
|
self.tecnai.Camera.ExposureNumber = (self.tecnai.Camera.ExposureNumber
|
|
/ 100000) * 100000 + value
|
|
|
|
def getFilmExposureTypes(self):
|
|
return ['manual', 'automatic']
|
|
|
|
def getFilmExposureType(self):
|
|
if self.tecnai.Camera.ManualExposure:
|
|
return 'manual'
|
|
else:
|
|
return 'automatic'
|
|
|
|
def setFilmExposureType(self, value):
|
|
if value == 'manual':
|
|
self.tecnai.Camera.ManualExposure = True
|
|
elif value == 'automatic':
|
|
self.tecnai.Camera.ManualExposure = False
|
|
else:
|
|
raise ValueError('Invalid value for film exposure type')
|
|
|
|
def getFilmExposureTime(self):
|
|
if self.tecnai.Camera.ManualExposure:
|
|
return self.getFilmManualExposureTime()
|
|
else:
|
|
return self.getFilmAutomaticExposureTime()
|
|
|
|
def getFilmManualExposureTime(self):
|
|
return float(self.tecnai.Camera.ManualExposureTime)
|
|
|
|
def setFilmManualExposureTime(self, value):
|
|
self.tecnai.Camera.ManualExposureTime = value
|
|
|
|
def getFilmAutomaticExposureTime(self):
|
|
return float(self.tecnai.Camera.MeasuredExposureTime)
|
|
|
|
def getFilmText(self):
|
|
return str(self.tecnai.Camera.FilmText)
|
|
|
|
def setFilmText(self, value):
|
|
self.tecnai.Camera.FilmText = value
|
|
|
|
def getFilmUserCode(self):
|
|
return str(self.tecnai.Camera.Usercode)
|
|
|
|
def setFilmUserCode(self, value):
|
|
self.tecnai.Camera.Usercode = value
|
|
|
|
def getFilmDateTypes(self):
|
|
return ['no date', 'DD-MM-YY', 'MM/DD/YY', 'YY.MM.DD', 'unknown']
|
|
|
|
def getFilmDateType(self):
|
|
filmdatetype = self.tecnai.Camera.PlateLabelDateType
|
|
if filmdatetype == win32com.client.constants.dtNoDate:
|
|
return 'no date'
|
|
elif filmdatetype == win32com.client.constants.dtDDMMYY:
|
|
return 'DD-MM-YY'
|
|
elif filmdatetype == win32com.client.constants.dtMMDDYY:
|
|
return 'MM/DD/YY'
|
|
elif filmdatetype == win32com.client.constants.dtYYMMDD:
|
|
return 'YY.MM.DD'
|
|
else:
|
|
return 'unknown'
|
|
|
|
def setFilmDateType(self, value):
|
|
if value == 'no date':
|
|
self.tecnai.Camera.PlateLabelDateType \
|
|
= win32com.client.constants.dtNoDate
|
|
elif value == 'DD-MM-YY':
|
|
self.tecnai.Camera.PlateLabelDateType \
|
|
= win32com.client.constants.dtDDMMYY
|
|
elif value == 'MM/DD/YY':
|
|
self.tecnai.Camera.PlateLabelDateType \
|
|
= win32com.client.constants.dtMMDDYY
|
|
elif value == 'YY.MM.DD':
|
|
self.tecnai.Camera.PlateLabelDateType \
|
|
= win32com.client.constants.dtYYMMDD
|
|
else:
|
|
raise ValueError('Invalid film date type specified')
|
|
|
|
def runBufferCycle(self):
|
|
try:
|
|
self.tecnai.Vacuum.RunBufferCycle()
|
|
except pythoncom.com_error, (hr, msg, exc, arg):
|
|
if exc is None:
|
|
raise RuntimeError('no extended error information')
|
|
else:
|
|
wcode, source, text, helpFile, helpId, scode = exc
|
|
if winerror.SUCCEEDED(wcode) and text is None:
|
|
raise RuntimeError('no extended error information')
|
|
else:
|
|
raise RuntimeError(text)
|
|
|
|
def setEmission(self, value):
|
|
self.tom.Gun.Emission = value
|
|
|
|
def getEmission(self):
|
|
return self.tom.Gun.Emission
|
|
|
|
def getExpWaitTime(self):
|
|
try:
|
|
return self.lowdose.WaitTime
|
|
except:
|
|
raise RuntimeError('no low dose interface')
|
|
|
|
def setShutterControl(self, value):
|
|
'''
|
|
If given boolean True, this should set the registers that allow
|
|
camera to control the shutter. Should also behave for other types
|
|
of TEMs that do not have or need these registers.
|
|
'''
|
|
pass
|
|
|
|
|
|
|