Gonimeter calibration
Added by Anonymous about 15 years ago
I was doing the Modeled Stage Position calibration, but whenever I run the Goniomodeling "Measure" button after entering in my settings, the node would begin to "Aquire Point 0" and remain 'stuck' there with no updates on the log. I set it to collect 25 points but it's been running for 25 minutes without any sign of progress. It did invoke the correction node right before it began measuring, but there were no errors from it. Also, the stage hasn't moved at all.
I guess I should mention that I didn't do the Stage Posittion matrix calibration because the manual mentioned it was optional and that there might be some redundancy if I were to do the Modeled Stage Position calibration after that. Should I go ahead and do that?
If not, do you have any suggestions on how to get the Goniometer calibrated?
Thank you for the help!
Replies (15)
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
I was revisiting the stage calibration, but when I tried to calibrate that, it also failed (the stage shift is almost zero, so it aborts). We are beginning to think the problem might be that Leginon is unable to control the stage like it does the other settings; under the navigation node, we got the error "Set Instrument failed: unable to set instrument," so this seems to imply that that's why the gonionmeter and the stage calibration under the Matrix tool are failing. We can control everything else (lenses, current, camera, etc.), it just seems that we can't control the stage using Leginon.
Any help solving this problem would be greatly appreciated!
Re: Gonimeter calibration - Added by Jim Pulokas about 15 years ago
Here is a quick test you can do on your Tecnai PC. Start the Python command line and run the following commands:
from pyScope import tecnai t = tecnai.Tecnai() t.setStagePosition({'x': 0, 'y': 0, 'z': 0})That is a short script to center the stage x,y,z to 0,0,0, and you can try it with different values. The units are meters, so to set x = 20 micron, you would say 'x': 2e-5.
Let me know if running this script gives you an error message.
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
Thanks for the response; this is what I got after I tried running that script:
C:\>python Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from pyScope import tecnai >>> t = tecnai.Tecnai() >>> t.setStagePosition({'x':0,'y':0,'z':0}) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python25\lib\site-packages\pyScope\tecnai.py", line 114, in setStageP osition self._setStagePosition(prevalue) File "C:\Python25\lib\site-packages\pyScope\tecnai.py", line 603, in _setStage Position axes |= getattr(win32com.client.constants, 'axis' + key.upper()) File "C:\Python25\Lib\site-packages\win32com\client\__init__.py", line 170, in __getattr__ raise AttributeError(a) AttributeError: axisY >>> t.setStagePosition({'x':0, 'y':0, 'z':0}) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python25\lib\site-packages\pyScope\tecnai.py", line 114, in setStageP osition self._setStagePosition(prevalue) File "C:\Python25\lib\site-packages\pyScope\tecnai.py", line 603, in _setStage Position axes |= getattr(win32com.client.constants, 'axis' + key.upper()) File "C:\Python25\Lib\site-packages\win32com\client\__init__.py", line 170, in __getattr__ raise AttributeError(a) AttributeError: axisY >>>
I should mention that the updatecom.py script never did work properly during installation--the error that I got for that is in another thread I posted in under PyScope (viewtopic.php?f=8&t=286 ). Another thing I should mention is that the Tecnai microscope (in this case TF20) has been updated to Tecnai version 4.0; it can get images and we've calibrated the beam and image shifts, it's just the stage we can't move using Legion. Though I tried this on the TF20, I originally experienced these problems on the Tecnai T12 (both updatecom.py errors are the same). The tecnai.py script is reproduced here below:
# COPYRIGHT: # The Leginon software is Copyright 2003 # The Scripps Research Institute, La Jolla, CA # For terms of the license agreement # see http://emg.nysbc.org/software/leginon-license import tem import time import sys try: import pythoncom import win32com.client import winerror try: try: import tecnaicom except ImportError: from pyScope import tecnaicom except ImportError: pass try: try: import ldcom except ImportError: from pyScope import ldcom except ImportError: pass try: try: import adacom except ImportError: from pyScope import adacom except ImportError: adacom = None except ImportError: pass # 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, } 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) try: self.tecnai = win32com.client.Dispatch('Tecnai.Instrument') except pythoncom.com_error, (hr, msg, exc, arg): raise RuntimeError('unable to initialize Tecnai interface, %s' % msg) 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 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'): 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 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): return float(self.tecnai.Illumination.Intensity) def setIntensity(self, intensity, relative = 'absolute'): if relative == 'relative': intensity += self.tecnai.Illumination.Intensity elif relative == 'absolute': pass else: raise ValueError self.tecnai.Illumination.Intensity = 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) value['y'] = float(self.tecnai.Illumination.RotationCenter.Y) return value def setBeamTilt(self, vector, relative = 'absolute'): if relative == 'relative': try: vector['x'] += self.tecnai.Illumination.RotationCenter.X except KeyError: pass try: vector['y'] += self.tecnai.Illumination.RotationCenter.Y except KeyError: pass elif relative == 'absolute': pass else: raise ValueError vec = self.tecnai.Illumination.RotationCenter try: vec.X = vector['x'] except KeyError: pass try: vec.Y = vector['y'] except KeyError: pass self.tecnai.Illumination.RotationCenter = vec def getBeamShift(self): value = {'x': None, 'y': None} value['x'] = float(self.tecnai.Illumination.Shift.X) value['y'] = float(self.tecnai.Illumination.Shift.Y) return value def setBeamShift(self, vector, relative = 'absolute'): if relative == 'relative': try: vector['x'] += self.tecnai.Illumination.Shift.X except KeyError: pass try: vector['y'] += self.tecnai.Illumination.Shift.Y except KeyError: pass elif relative == 'absolute': pass else: raise ValueError vec = self.tecnai.Illumination.Shift try: vec.X = vector['x'] except KeyError: pass try: vec.Y = vector['y'] except KeyError: pass self.tecnai.Illumination.Shift = 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) 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(): setattr(pos, key.upper(), value) axes |= getattr(win32com.client.constants, 'axis' + key.upper()) 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 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): if state == 'closed': self.tecnai.Vacuum.ColumnValvesOpen = 0 elif state == 'open': self.tecnai.Vacuum.ColumnValvesOpen = 1 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): # return float(self.tecnai.Vacuum.Gauges('P4').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)
Thanks for the help!
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
Another quick question (not related to the problem directly, but with the board in general):
When will the workshop you are having end? I appreciate the helpful responses you have provided so far (I really do!), but they have been few and far between, understandably so because of the workshop.
Right now, we are just stuck on this stage calibration step which is probably related to the pyScope issue I mentioned earlier. I just wish to know when you will be back to a normal schedule since we have to share the microscope with other groups in our department, and I don't want to keep them from using the microscope because we are stuck on Leginon. I feel that knowing when we can get more timely responses for our problems will allow us to better use our limited time on the microscope.
Again, thank you very much for your assistance!
Re: Gonimeter calibration - Added by Jim Pulokas about 15 years ago
The workshop will be over on Friday, so you should be getting more attention after that. The stage movement problem is related to the updatecom.py problem. I will go over to the pyScope thread to respond to that now...
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
Now that I have the pyScope stuff sorted out, I revisited the Goniometer calibration. The stage is now moving and it's not longer stuck on the 0th point, but when I tried running the calibration, every single point out of 25 was rejected. I didn't get too much time to figure out how to fix it, but I thought a 25% tolerance was fairly generous and was wondering if there is something I should be looking into (some underlying problem). I don't want to 'fix' it by just increasing the tolerance (if possible).
The manual says that some valid points are rejected if the tolerance is too low--how can I determine if the sift are well-correlated?
Re: Gonimeter calibration - Added by Anchi Cheng about 15 years ago
Carlos,
You can display the correlation map as well as the peak Leginon finds in your "GonioModeling" node. Same function is available in all
calibration nodes. Switching between what the imageviewer display is controled by tools on the left of the display area. Select from "Image", "Correlation" which to display by clicking on the computer display icon.
Add the correlation peak position the program finds by pressing the orange "+" down. Note that the correlation map origin is at the top-left corner,
which means that if the two images it correlates are identical, you get a peak at the top-left corner, not the center of the image.
Anchi
Re: Gonimeter calibration - Added by Jim Pulokas about 15 years ago
Here is a more detailed description of why calibration measurements are rejected:
The stage calibration (and many others) depend on already having done the pixel size calibration. This means that for every magnification, we already have a pixel size stored in the database. In our case, we measure pixel size by observing the diffraction pattern of a catalase crystal. We only directly measure this for a few of our higher magnifications, like 50,000 and 80,000. Then we extrapolate the other pixel sizes for other magnifications.
During stage calibration, the stage is requested to move a certain distance, then the resulting pixel shift is measured using image correlation. For example, the stage may move 5 um, then the correlation finds that the image shifted 100 pixels. This results in a measured pixel size of 5um / 100 pixels = 0.05 um/pixel. Rather than using catalase crystal, we are now using the stage movement as the basis for the measure. The stage measurement is compared with the catalase measurement and if they are not close enough within the specified tolerance, then the measurement is rejected.
Therefore, these are two possible reasons why this is failing:
1. The image correlation is not working. As Anchi stated, you can view the correlation image, and display the peak that Leginon found on this image. If it is finding something other than the true peak, then that is the problem. It could be that the stage movement is too far to make a correlation between the two images (no overlapping area between the two images). It could also be that there is not enough contrast in the image to get a good correlation peak (try more defocus).
2. The pixel size calibration stored in the database it not very good. This is frequently the case for lower magnifications where we did not directly measure from a catalase crystal, we just extrapolated using the nominal magnification. If you confirmed that the correlation is working, and the peak that is detected is true, then you can fully trust the measurement. Then all you have to do is make Leginon trust it. You can either set a very high tolerance until the measurements are accepted, or you can edit the pixel size calibration to a more realistic value, based on your new measurements of stage position.
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
I think I found what the problem was; for some reason, it's not detecting the peak properly. As I understand it, the peak is supposed to move, and the difference between the new and previous peak positions are measured to get the shift in pixels. However, the peak in the images (signified by an orange + sign) stays in the top left in the exact same spot, almost on the top edge, giving a measured pixel size of "0.0". This results in the point being rejected (gives "Error 1.0").
I'm not sure why it thinks the peak is up there. The "bad pixels" are at the bottom left, not the top right, and the area seems to be perfectly normal when we take images (no dead pixels, etc). What would you suggest I do to make Leginon read the correct peak? I already tried changing between phase and cross correlation.
(Note: we didn't have this problem on the TF20, just the T12).
Re: Gonimeter calibration - Added by Jim Pulokas about 15 years ago
When you view the images during the calibration, you should see that the sample is moving between consecutive images. If you view the correlation image, the peak should show up in a location that indicates how far consecutive images have moved. There is one correlation image produced for every two images acquired. Here is simple graphic that shows what you might expect to see. First time I have tried linking to an image, so hope this works...
Notice that the stage is shown to move in one direction for the entire series of images, for example the stage X axis direction. Then another series is done by moving only in the Y axis direction. The position of the peak relative to the corner of the image indicates the direction and distance of the shift between the two consecutive images. Therefore, you expect the peak to be in roughly the same direction and distance for each movement. However, the reason we are trying to model this behavior is because the distance is actually not always the same, so you will notice a slight variation in the position of the peak.
The peak should not always show up at the corner of the image, which indicates a 0,0 shift between consectutive images. If you see that the stage is shifting in the images, but the peak shows up at the corner, then the images are not getting corrected properly. When you say that the peak is shown in the corner of the image, do you mean that the marker shows up at the corner of the image, and this is where you actually see the peak (bright spot) in the correlation image. Or does that mean you can see a real peak somewhere else on the correlation image even thought the marker shows up at the corner. If the images are not properly normalized, then you can get a false peak at the corner, and sometimes still see the real peak elsewhere in the correlation. Try again doing the correction dark/bright images for both channels. The reason we have the two channels is to prevent this false peak.
Re: Gonimeter calibration - Added by Jim Pulokas about 15 years ago
Additionally, you can send us your dark and bright images and we can see if they look ok. Try redoing your dark/bright images, just for whatever image size and binning you are using in your calibration. Then go into the directory where images are stored for your sesssion and find the most recent dark/bright images. This will be in whatever image path you set up for your session and the file names will be for example:
09nov18a_Corrector_dark_00013.mrc
09nov18a_Corrector_bright_00013.mrc
Just find the most recent dark and bright and send them as email attachment, or put them somewhere we can download them from you.
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
Thanks Jim; we retook the reference images like you suggested, and they seem to fine. The corrected images we're getting seem good (free of artifacts, good contrast). The problem we seem to be encountering then (that we didn't get with the TF20) is that the calibrated pixel size doesn't seem to be used during the goniomodeling step. The peak actually is moving now (slightly) and Leginon detects the shift in the peak by moving orange corsair, and the correlation display shows a white peak where the corsair is, but it's not recording the change in position itself. What we get is something like this:
Acquiring Point 18...
Position 0.0, 0.0
Delta 0.0
Correlation shift -11.7631921935, 227.299208071
Measured pixel size 0.0
Error 1.0
Rejected...
Acquiring Point 19...
And so on.
We think it had something to do with the pixel size not being calibrated properly. We followed the procedure on the manual on how to do it, and we also followed the same procedure for the TF20 (where it worked), although the magnifications are slightly different in the T12 (e.g. T12 uses 560x instead of 550x). We're worried that Leginon is not using the pixel sizes we put in and that's why the calibrated pixel size is showing up as zero... What do you think?
Thanks for all your help so far--I was thinking I would skip this step for now and work on the other calibrations if I could, though it's a very important calibration that I definitely need to fix sooner rather than later...
I'll see if I can get some screen caps to show you exactly what I mean.
Re: Gonimeter calibration - Added by Anchi Cheng about 15 years ago
I have some guesses on what your problem is.
Frist, the pixelsize you enter is the actual pixelsize you get on CCD which normally
has a post magnification factor. For example, if the magnification on the FEI GUI is 500 x, it means that 1um at the
sample would be shown as 500 um at the film camera. If you scan the film at 15 um per pixel, you get a pixelsize of
15/500 um per pixel or 0.03 um/pixel = 3e-8 m/pixel. CCD is normally further down in the column which means the image
is further magnified. Let's say that the post mag is 1.5. Then the pixelsize you need to put in Leginon for 500 x is
3e-8/1.5 = 3e-8 m/pixel. If your F20 and T12 camera have different postmag, the two pixel sizes would be even more
different than 550x to 560x.
Go to your "Pixel Size" node in your Calibration application and check the pixelsize value saved
by clicking on the green arrow which opens the list of all pixel size calibrations for your instrument.
Second, It might be that for some reason it is recorded at 0 m/pixel when you extract the values from higher mags.
You can redo the extrapolation or enter a number you know is closer to the true value for your instrument and mag.
Anchi
Re: Gonimeter calibration - Added by Anonymous about 15 years ago
Hi Anchi and Jim,
I think I found out what was wrong. After skipping ahead to the navigation section to test the other calibrations, I tried doing the stage calibration anyway to see what type of errors I would get -- anything to help me troubleshoot.
The error that came up said that I had not calibrated the simCCDcamera and the simTEM correctly, so it aborted the navigation step (image shift worked correctly). I thought that maybe the calibrations of the real instruments were being disrupted by the simulated instruments somehow. I checked the settings to make sure that the real instruments were being selected for each of the calibrations (they were). I tried again and got the same types of errors on the goniomodeling node.
I decided to test my theory for sure by commenting out the two simulated instruments in the pyScope config file. This did the trick--when I went back to the goniomodeling step, the peak shifts started getting detected and the points were being saved to the database. I didn't get a chance to test the quality of the calibration by using navigation mode (ran out of scheduled time on the microscope), but I did get a rough curve in the goniomedeling admin tools, so things are starting to look more promising.
I'm curious as to why we didn't have this problem on the TF20; we did not (for the most part) have any problems with the simulated instruments, but still--it might useful to know in case anyone else in the future runs into the same problems! I would suggest just having the two instruments that you are going to calibrate as the only ones enabled, as I also had to keep checking to make sure they were selected.
Thanks for the help! I will undoubtedly need it again when I return to this tomorrow. <img src="{SMILIES_PATH}/icon_lol.gif" alt=":lol:" title="Laughing" />
Re: Gonimeter calibration - Added by Anchi Cheng about 15 years ago
Carlos,
In general, you want to send a preset to scope before calibration. Default in Leginon listens to what the microscope and ccd was last sent to and use it to aquire images and to do calibration. We did that so that you can calibrate at only the mags required for your real experiment. Unless you've changed the settings to "Overwrite Preset", Leginon should not use the camera and tem settings in the calibration or navigation nodes. It might be that you have a mixture of instrument in your presets, some using SimTEM/SimCAM and some using real ones. The database was confused because of it. Even though the problem is fixed, I still encourage you to make a copy of your current database and tell Jim and I where to get it (in e-mail for privacy). We can look through it to tell you when and what has gone wrong since the database records the history of all these changes. It will help us to create better error catching mechanism in the future.
Anchi