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)