Metadata-Version: 2.4
Name: nanosurf
Version: 2.0.7
Summary: Control Nanosurf atomic force microscopes from Python
Author-email: Nanosurf AG <scripting@nanosurf.com>
License-Expression: MIT
Project-URL: Homepage, https://www.nanosurf.com
Keywords: nanosurf,afm,atomic-force-microscopy,scripting,automation
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: nanosurf-core==2.0.7
Requires-Dist: nanosurf-utils==2.0.7
Requires-Dist: nanosurf-apps==2.0.7
Dynamic: license-file

# Nanosurf Python Library

This library provides a Python interface for controlling Nanosurf atomic force
microscopes (AFMs), utilities for processing and handling measurement data, and some
simple example applications to get you started.

The library consists of three packages, which can be installed separately:

| Package | Provides |
|---|---|
| `nanosurf-core` | Python API for controlling Nanosurf atomic force microscopes (AFM) |
| `nanosurf-utils` | Data processing, file handling, and device drivers for Nanosurf AFM systems |
| `nanosurf-apps` | Runnable example scripts using the Python API with Nanosurf Studio or Nanosurf MobileS |

## Requirements

- To use the Python interface to remotely control a Nanosurf AFM, a running Nanosurf
  Studio or Nanosurf MobileS session is required.
- Scripting access to low-level Studio functionality can be obtained in different
  tiers. See documentation, or contact Nanosurf sales for more information.

The library installs on Windows, Linux and macOS, but not every feature is
available on every platform:

| | Windows | Linux | macOS |
|---|---|---|---|
| Studio or MobileS functionality via Python | ✅ | – | – |
| Accessory and add-on device control | ✅ | ✅ | – |
| Reading and analysing measurement data | ✅ | ✅ | ✅ |

## Installation and updating

To install the full `nanosurf` library, run the following command from your command
line interface:

```bash
pip install nanosurf
```

To upgrade your `nanosurf` package installation version &ge; 2.0.0 to the newest version, run the
following command from your command line interface:

```bash
pip install -U nanosurf
```

To upgrade from an existing installed library version &lt; 2.0.0:

```bash
pip install -U --force-reinstall nanosurf
```

## Getting started

With a running Studio session:

```python
from nanosurf.studio import Studio, StudioScriptError

studio = Studio()

try:
    session = studio.select_measurement_session()
    print(f"Instrument: {session.workflow.device.scan_head.name} / "
          f"{session.workflow.device.controller.name}")

    laser = session.workflow.laser
    calibration = session.workflow.probe.cantilever_calibration
    imaging = session.workflow.imaging
    storage = session.workflow.data.storage
    approach = session.workflow.approach

    # 1. Laser alignment
    print("Aligning laser...")
    print(laser.alignment.align_all()['message'])

    # 2. Cantilever calibration
    calibration.operation_mode = calibration.operation_mode_enum.non_contact
    print("Running thermal tune...")
    print(calibration.run()['message'])
    calibration.apply()

    # 3. Set imaging parameters
    imaging.scan_range_fast_axis = 2e-6
    imaging.scan_range_slow_axis = 2e-6
    imaging.points_per_line = 256
    imaging.lines_per_frame = 256
    imaging.line_rate = 1.0

    # 4. Where to save
    storage.file_basename = "demo_[DATE]_[INDEX]"

    # 5. Approach and acquire an image
    print("Approaching...")
    print(approach.approach()['message'])

    print("Scanning...")
    print(imaging.acquire()['message'])

    # 6. Withdraw
    approach.withdraw()
    print("Session complete.")

except StudioScriptError as e:
    print(f"Studio error: {e}")
```

With a running MobileS session:

```python
import time
from nanosurf.com_proxy import SPM
# SPM() auto-detects whichever supported control software is running
# (MobileS, C3000, CoreAFM, CX, etc). Use e.g. nanosurf.MobileS() to target one directly.

spm = SPM()
try:
    if not spm.is_connected():
        raise RuntimeError("No running Nanosurf MobileS session found.")
    if not spm.is_scripting_enabled():
        raise RuntimeError("Scripting is not enabled.")

    # configure the measurement
    scan = spm.application.Scan
    scan.ImageWidth  = 2e-6
    scan.ImageHeight = 2e-6
    scan.Points = 200
    scan.Lines  = 200

    # start the measurement
    scan.StartFrameUp()
    while scan.IsScanning:
        time.sleep(0.1)

except Exception as e:
    print(f"Connecting to MobileS or imaging failed: {e}")
```

## Documentation

The full documentation for the library and the Studio scripting interface is bundled with Nanosurf Studio starting from version 18.

## Version History

See `CHANGELOG.txt` in the installed package folder.

## License

[MIT License](https://en.wikipedia.org/wiki/MIT_License)
