Instruction for AEcroscoPy Cypher Interface#
\(_{Yongtao}\) \(_{Liu,}\) \(_{liuy3@ornl.gov}\)
\(_{February}\) \(_{2026}\)
Overview#
PyCypher is the AEcroscoPy interface for communicating with the Asylum Research Cypher AFM (and VERO) via Igor Pro. It allows Python scripts to send commands, set scan parameters, engage/withdraw the tip, and move the tip to specified locations — all without manually interacting with the Igor Pro GUI.
The interface uses COM/ActiveX communication on Windows. Ensure Igor Pro and the Cypher AFM software are running before initializing PyCypher.
Import#
from aecroscopywave.interfaces import Cypher
Initialize PyCypher#
Creates an instance of PyCypher, which connects to the running Igor Pro application via COM. This must be called before any other Cypher commands.
pycy = Cypher.PyCypher()
Send Commands#
Execute() sends an Igor Pro command string directly to the AFM software. ARExecuteControl() sets a specific GUI control (e.g., a dropdown menu) in a named Igor Pro panel by index or string value.
pycy.Execute("Print \"Hello from Igor Pro!\"")
pycy.ARExecuteControl("ImagingModePopup_0", "MasterPanel", 0, "Contact")
Set Parameters#
Pass a dictionary of parameter names and values to PV(). Common parameters include ScanSize (meters), PointsLines (pixels per line), and ScanRate (lines/second).
# Set parameters
parameters = {"ScanSize": 1e-6, "PointsLines": 64, "ScanRate": 1}
# Send parameters to Igor Pro
pycy.PV(parameters)
Set Master Panel#
set_Master_Panel() provides a higher-level interface for configuring the AFM scan. It accepts the imaging mode (e.g., "Contact"), scan mode (e.g., "Continuous Mode"), a parameter dictionary, and an optional do_scan action (e.g., "Frame Up" to start scanning).
pycy.set_Master_Panel(imaging_mode="Contact", scan_mode="Continuous Mode", parameters={'ScanSize': 2e-6, 'PointsLines':228, 'ScanRate':1})
Get Metadata#
Returns a dictionary of all current AFM system variables — scan size, offsets, gains, drive frequency, setpoint, and more. Useful for logging experimental conditions or reading current state before making changes.
pycy.get_MasterVariables()
{'ScanSize': 2e-06,
'FastScanSize': 1.9999999999999998e-05,
'SlowScanSize': 1.9999999999999998e-05,
'ScanRate': 1.0,
'ScanSpeed': 4.9999999999999996e-05,
'XOffset': 0.0,
'YOffset': 0.0,
'ScanPoints': 256.0,
'ScanLines': 256.0,
'RoundFactor': 0.04,
'IntegralGain': 10.0,
'ProportionalGain': 0.0,
'ScanAngle': 0.0,
'ScanAngleFactor': 1.0,
'AmplitudeSetpointVolts': 0.8,
'AmplitudeSetpointMeters': 1e-08,
'DriveAmplitude': 0.1,
'DriveFrequency': 74999.99832361937,
'SweepWidth': 5000.0,
'SlowScanEnabled': 1.0,
'DeflectionSetpointVolts': -10.0,
'DeflectionSetpointMeters': 0.0,
'DeflectionSetpointNewtons': 5e-09,
'ImagingMode': 0.0,
'MaxScanSize': 9e-05,
'InvOLS': 1e-07,
'SpringConstant': 1.0,
'DisplaySpringConstant': 1e-09,
'ScanStateChanged': 1.0,
'ScanDown': 0.0,
'XLVDTSens': 8.558168e-06,
'YLVDTSens': 8.435736e-06,
'ZLVDTSens': 1.3078e-06,
'XLVDTOffset': -2.45,
'YLVDTOffset': -3.17,
'ZLVDTOffset': 0.0,
'YIgain': 3.24,
'YPgain': -inf,
'XIgain': 3.8031,
'XPgain': -inf,
'LastScan': 0.0,
'XPiezoSens': 5.080146e-07,
'YPiezoSens': 5.0769e-07,
'ZPiezoSens': 7.8658e-08,
'XDriveOffset': 0.0,
'YDriveOffset': 0.0,
'SweepPoints': 480.0,
'SecretGain': 0.0,
'YSgain': 5.79,
'XSgain': 5.8,
'DIsplayLVDTTraces': 0.0,
'PhaseOffset': 0.0,
'BaseSuffix': 0.0,
'SaveImage': 2.0,
'ParmChange': 0.0,
'ADCgain': 0.0,
'OldADCgain': 12.0,
'OldScanSize': 5e-09,
'OldYOffset': 0.0,
'OldXOffset': 0.0,
'ZIgain': 4.0,
'ZPgain': -inf,
'ZSgain': 0.0,
'AmpInvOLS': 1.09e-07,
'UpdateCounter': 106.0,
'DoMunge': 0.0,
'XMungeAlpha': 1.0,
'YMungeAlpha': 1.0,
'ZMungeAlpha': 1.0,
'StartHeadTemp': 1.3041665976984393,
'StartScannerTemp': -1.6667416569572848,
'Has1xACDeflGain': 1.0,
'DontChangeXPT': 0.0,
'LowNoise': 0.0,
'ScreenRatio': 0.75,
'XDriftRate': 0.0,
'YDriftRate': 0.0,
'XDriftTotal': 0.0,
'YDriftTotal': 0.0,
'DriftBIts': 0.0,
'DriftCount': 0.0,
'Setpoint': 0.0008,
'FastRatio': 1.0,
'SlowRatio': 1.0,
'TopLine': 255.0,
'BottomLine': 0.0,
'ScanStatus': 0.0,
'Is1DPlus': 0.0,
'DelayUpdate': 0.0,
'MarkerRatio': 0.0,
'StartLineCount': 5.042682536581311,
'OldAmplitudeSetpointVolts': 0.8,
'OldDeflectionSetPointVolts': 0.0,
'ScanMode': 0.0,
'Interpolate': -1248.0,
'TipVoltage': 0.0,
'SurfaceVoltage': 0.0,
'FreqIgain': 5.0,
'FreqPgain': 0.0,
'FreqSgain': 0.0,
'OrcaGain': nan,
'FreqGainOn': 0.0,
'UserIn0Gain': 1.0,
'UserIn1Gain': 1.0,
'UserIn2Gain': 1.0,
'LateralGain': 1.0,
'IsBipolar': 0.0,
'FrequencyHack': 0.0,
'MagneticField': nan,
'DriveGainOn': 0.0,
'DriveIGain': 50.0,
'DrivePGain': 0.0,
'DriveSGain': 0.0,
'UserIn0Offset': 0.0,
'UserIn1Offset': 0.0,
'UserIn2Offset': 0.0,
'LateralOffset': 0.0,
'LastImage': 0.0,
'ZoomSize': 0.0,
'ZoomXOffset': 0.0,
'ZoomYOffset': 0.0,
'User0Voltage': 0.0,
'User1Voltage': 0.0,
'ExtendedZ': 0.0,
'DriveAmplitude1': 0.1,
'DriveFrequency1': 450000.0,
'SweepWidth1': 5000.0,
'PhaseOffset1': 0.0,
'Amp2InvOLS': 2e-08,
'VoltageParm': 0.0,
'MicroscopeID': 0.0,
'CapacitanceSens': 1.0,
'CapacitanceOffset': 0.0,
'CapPhaseOffset': 0.0,
'TipBiasOffset': 0.0,
'TipHeaterOffset': 0.0,
'SurfaceBiasOffset': 0.0,
'UseCantHolder': 0.0,
'CurrentCantHolder': 0.0,
'HasClickRing': 0.0,
'XScanDirection': 1.0,
'YScanDirection': 1.0,
'SaveImageCount': 0.0,
'SaveImageLines': 128.0,
'OrcaGain2': nan,
'UpdateSlowWave': 0.0,
'FBFilterBW': 1500.0,
'CurrentSetpointAmps': 1.0,
'CurrentSetpointVolts': 1.0,
'OldCurrentSetpointVolts': 1.0,
'OldCurrentSetpointAmps': 1.0,
'HasFM': 1.0,
'LastScanWithdraw': 0.0,
'HasLaserRelay': 0.0,
'ToggleLaserRelay': 0.0,
'Decimation': 0.0,
'DARTIGain': 5.5,
'DARTPGain': 0.0,
'SampleHolder': 1.0,
'ManualSampleHolder': 0.0,
'CypherXPTLock': 0.0,
'XPTLock': 0.0,
'LogFeedback': 0.0,
'ARSysScanBusy': 0.0,
'SimpleControls': 0.0,
'PointsLines': 228.0,
'FreeAirAmplitude': nan,
'FreeAirPhase': nan,
'FreeAirDeflection': nan,
'FreeAirDriveAmplitude': 0.0,
'ContinualRetune': 0.0,
'ForceFilter': 0.0,
'TemperatureSens': 1.0,
'TemperatureOffset': 0.0,
'OffsetBehavior': 0.0,
'InputRange': 10.0,
'XLVDTSensSlope': 0.0,
'YLVDTSensSlope': 0.0,
'XLVDTSensIntercept': 0.0,
'YLVDTSensIntercept': 0.0,
'HaveWeKilledTheProgressBar': 0.0,
'PreScanSetting': 0.0,
'ImageFrameTime': 0.0,
'FBFilterSelectivity': 0.0,
'HasDriveChoke': 0.0,
'DriveChokeOn': 0.0,
'CFCWFOS': 0.0,
'SkewAngle': 0.0,
'ContinualRetuneTime': 60.0,
'DRTimeStamp': 0.0,
'CRTimeStamp': 0.0,
'Cypher15VPower': 0.0,
'HasBlueDrive': 0.0,
'BlueDriveOn': 0.0,
'blueDriveOffset': 5.0,
'blueDriveMaxAmplitude': 0.0,
'bDDriveAmplitude': 0.002,
'bDDriveAmplitude1': 0.002,
'bDDiffEfficiencyV': 0.004475,
'BackPackIn0Gain': 1.0,
'BackPackIn0Offset': 0.0,
'BackPackIn1Gain': 1.0,
'BackPackIn1Offset': 0.0,
'BackPackIn2Gain': 1.0,
'BackPackIn2Offset': 0.0,
'BackPackIn3Gain': 1.0,
'BackPackIn3Offset': 0.0,
'BackPackIn4Gain': 1.0,
'BackPackIn4Offset': 0.0,
'bdReCalibrateTime': 0.0,
'bdMotorError': 0.0,
'ScanModeGUI': 0.0,
'FastMapSetpointVolts': 1.0,
'FastMapSetpointNewtons': 1e-07,
'OldFastMapSetpointVolts': 1.0,
'OldFastMapSetpointNewtons': 1.0,
'FastMapZRate': 300.0,
'FastMapAmplitude': 4e-07,
'FastMapFBPhase': 0.0,
'FastMapFBWindow': 10.0,
'FastMapAmpSetpointVolts': 0.8,
'FastMapAmpSetpointMeters': 8.72e-08,
'FastMapIndex': 0.0,
'QueueProgress': 0.0,
'QueueEstimate': 0.0,
'QueueExpand': 0.0,
'FastMapIGain': 10.0,
'FastMapScanRate': 0.46781437125748504,
'FastMapBaseLine': 0.0,
'blueThermOn': 0.0,
'FMapFreqSetpointHertz': 100.0,
'FMapDispSetpointVolts': 0.5,
'OldFMapFreqSetpointHertz': 100.0,
'OldFMapDispSetpointVolts': 0.5,
'OldFastMapAmpSetpointVolts': 0.8,
'OldFastMapAmpSetpointMeters': 1e-08,
'FastMapScanPoints': 256.0,
'FastMapScanLines': 256.0,
'FastMapOptScanPoints': 256.0,
'FastMapOptScanLines': 256.0,
'DisplaySpringConstant2': 1.0000000000000001e-07,
'Springconstant2': 100.0,
'FreqDGain': 0.0,
'DriveDGain': 0.0,
'ImageSaveExpand': 0.0,
'Saturated': 0.0,
'FreeAirDissipation': nan,
'IlluminatePercent': 86.0,
'ImageFormatMode': 0.0,
'ScanDirMode': 0.0,
'SinusoidalOn': 0.0,
'FrameCount': 0.0,
'ScanShape': 0.0,
'FastReturnLines': 8.0,
'FastSkipLines': 4.0,
'TimeShift': 0.0,
'FastInputFilter': 0.0,
'IMSScanStateChanged': 0.0,
'FastZPiezoSens': 3.6124e-08,
'UpdateFrameOnly': 0.0,
'FastScopeLine': 128.0,
'TimeShiftDisplay': 0.0,
'TimeShiftTotal': 0.0,
'ShouldSSCBeSet': 0.0,
'FastMapCaptureRate': 0.0,
'bDMaskGain': 1.0,
'BlueDriveMaxAmplitudeWatts': 0.009,
'FMapDispSetpointWatts': 0.5,
'OldFMapDispSetpointWatts': 0.5,
'FMFBFilterBW': 1500.0,
'IsLDV': 0.0,
'FastMapAmpRelativeSetpointVolts': 0.8,
'FastMapAmpRelativeSetpointMeter': 8.72e-08,
'FastMapAbsoluteSetpointNewtons': 1e-07,
'FastMapAbsoluteSetpointVolts': 1.0,
'OldFastMapAmpRelativeSetpointVo': 0.8,
'OldFastMapAmpRelativeSetpointMe': 8.72e-08,
'OldFastMapAbsoluteSetpointNewto': 1e-07,
'OldFastMapAbsoluteSetpointVolts': 1.0,
'FFMapRelativeTrigger': 0.0,
'FlipBiasSignWithdrawDist': 5e-09,
'ZMaxScanSize': 9e-05,
'bdMaskHomed': 0.0,
'FreeAirAmplitude2': nan,
'FreeAirPhase2': nan}
Tip Engage and Withdraw#
engage() brings the tip into contact with (or close to) the sample surface. withdraw() lifts the tip away. Always withdraw before moving the sample stage.
pycy.engage()
pycy.withdraw()
Move Tip#
Call initialize_move_tip() once to set up the tip movement system. Then use move_tip() to position the tip at a target location. Coordinates can be specified in pixel units (0–255) relative to the current scan frame.
# Initialize move tip, only need to call once at the beginning of the move tip process
pycy.initialize_move_tip()
# Move the tip to the specified pixel coordinates (0, 0) with a transit time of x seconds
# Coordinates are in pixel units, and the transit time is in seconds
pycy.move_tip(pixel_coordinates = [0, 0], transit_time = 0.5)