TL;DR: Начал с фантазий про телепортацию из рассказа Стивена Кинга, закончил Python-пакетом для управления сканирующим туннельным микроскопом. 41 тест, симулятор вместо оборудования за $500K, замена LabVIEW на asyncio. pip install amrl-transport - и можно тренировать RL-агента для манипуляции отдельными атомами, не выходя из дома.

Как все началось

Есть у Кинга рассказ «Долгий Джонт» (The Jaunt). Там телепортация работает так: объект разбирается в точке A и собирается в точке B. Мгновенно. "Джонт горка" все дела.

Я в очередной раз послушал его (спасибо Влад Копп и МДС) и подумал: а что, если не фантазировать, а посмотреть - насколько мы реально близки? Не в смысле «телепортировать человека», а хотя бы «разобрать объект на атомы и собрать заново».

Оказалось — ближе, чем кажется. Просто инструменты застряли в 90-х.

Сканирующий туннельный микроскоп умеет двигать атомы

В 1989 году дядьки из IBM написали слово «IBM» отдельными атомами ксенона. С тех пор прошло 36 лет. STM (сканирующий туннельный микроскоп) умеет:

  • Сканировать поверхность с атомарным разрешением

  • Двигать отдельные атомы (lateral manipulation)

  • Удалять и ставить атомы (vertical manipulation)

  • Менять химические связи (tip-induced chemistry)

Один атом. За раз. Иголкой толщиной в один атом.

Проблема? Скорость. Один атом - ~10 секунд. Собрать нанострукутру из 100 атомов - полчаса ручной работы ученого за приборной панелью. Масштабирование до «Джонта» - примерно никогда при таком подходе.

RL-агенты: пусть ИИ таскает атомы

В 2018-2020 годах две группы независимо показали, что нейросеть может двигать атомы автономно:

DeepSPM (Krull et al., 2020) - Monash University. Агент на базе deep learning управляет STM: сканирует, оценивает качество поверхности, чистит иглу, повторяет. Опубликовано в Nature Communications.

SINGROUP/Atom_manipulation_with_RL (Aalto University, 2019-2025) - RL-агент (SAC) учится двигать атомы в заданную точку. Обучение на реальном микроскопе.

Все круто, но…

Проблема: каждая лаба пишет свое

DeepSPM работает через LabVIEW-сервер, который общается с контроллером Createc через COM-интерфейс. Windows-only, лицензия ~$3500/год.

SINGROUP написали RealExpEnv — обёртку вокруг того же Createc COM. Тоже Windows, тоже заточено под один бренд.

Если у вас в лабе Nanonis (другой контроллер) — переписывайте все. Если хотите разрабатывать без микроскопа — удачи, симулятора нет. Если хотите запустить несколько микроскопов параллельно — LOL.

Знакомая картина. Я каждый день на работе вижу то же самое, только с бизнес-формулами вместо атомов.

Что я написал

amrl-transport — это три вещи:

1. STMTransport — абстракция над оборудованием

12 методов. Все в физических единицах: нанометры, милливольты, пикоамперы.

from amrl_transport.transport.protocol import STMTransport

class STMTransport(ABC):
    def connect(self) -> None: ...
    def scan_image(self, size_nm, offset_nm, pixel, bias_mv) -> ScanResult: ...
    def lateral_manipulation(self, x_start_nm, y_start_nm, 
                             x_end_nm, y_end_nm, ...) -> ManipResult: ...
    def tip_shape(self, x_nm, y_nm, ...) -> bool: ...
    # ... ещё 8 методов

Реализуешь под свой микроскоп - и все. RL-агент не знает, работает он с Createc, Nanonis или симулятором.

2. Симулятор — микроскоп без микроскопа

Полноценный бэкенд, который эмулирует STM:

  • Поверхность с гауссовыми «атомами» — как реальные изображения, только без шума лаборатории (ну ладно, шум тоже есть — настраиваемый)

  • Lateral manipulation с физикой: атом двигается, если ток достаточный

  • Tip shaping: игла «тупится» и «точится»

from amrl_transport.transport import SimulatorTransport
import numpy as np

with SimulatorTransport(seed=42) as stm:
    img = stm.scan_image(
        size_nm=5.0,
        offset_nm=np.array([0.0, 0.0]),
        pixel=128,
        bias_mv=100,
    )
    # img.img_forward — numpy array 128x128, как с реального прибора

Можно тренировать RL-агента на ноутбуке. Без криогеники, без вакуума, без $500K оборудования.

3. DeepSPM-сервер — убиваем LabVIEW

Это то, чем я горжусь больше всего.

DeepSPM (Nature Communications, 2020) общается с прибором через LabVIEW TCP-сервер. Я разреверсил протокол из исходников и написал замену на чистом Python asyncio.

Протокол оказался простой — 6 команд:

Команда

Формат

Что делает

scan

scan x y size px

Сканирование области

tipshaping

tipshaping x y dip bias timing

Формирование иглы

tipclean

tipclean x y

Очистка иглы

getparam

getparam Range|zRange

Получить параметр

approach

approach f

Подвод иглы

movearea

movearea y+

Сдвиг области

Ответ на scan — бинарный: [4B height BE][4B width BE][H*W float32 BE].

# Запуск Python-сервера (вместо LabVIEW)
python -m amrl_transport.deepspm --transport simulator

# Существующий код DeepSPM подключается к localhost:5556
# Без изменений. Вообще без изменений.

Итог: BSD-3 лицензия LabVIEW ($3500/год, Windows-only) → MIT Python asyncio (бесплатно, кроссплатформенно).

4. Очередь задач — для параллельной работы

RabbitMQ + Redis. Отправляешь задачу «собери треугольник из 3 атомов» — воркер с подключённым STM выполняет.

# Воркер
python -m amrl_transport.cli worker --transport simulator --worker-id sim-01

# Задача
python -m amrl_transport.cli submit --atoms '[[0,0],[1,0],[0.5,0.866]]'

Зачем? В лабе может быть 3-5 микроскопов. Пока один сканирует, другой двигает. Параллелизм на уровне задач, а не потоков.

TransportEnv — drop-in для SINGROUP

Вот ради чего все затевалось. У SINGROUP есть RealExpEnv — Gym-совместимый environment для обучения. Мой TransportEnv — точная замена:

from amrl_transport.transport import SimulatorTransport
from amrl_transport.integration import TransportEnv

stm = SimulatorTransport(seed=42)
stm.connect()

env = TransportEnv(
    transport=stm,
    step_nm=0.2,
    max_mvolt=20,
    max_pcurrent_to_mvolt_ratio=2850,
    goal_nm=2.0,
)

# Тот же API что у RealExpEnv
state, info = env.reset()
next_state, reward, done, info = env.step(action)

Обученная модель на симуляторе → подставляешь CreatecTransport → работает на реальном железе. В теории. На практике будет sim-to-real gap, но это уже задача для RL-исследователей, не для инфраструктуры.

Тесты

41 тест. Все проходят без оборудования:

tests/
├── test_protocol.py          # ABC контракты
├── test_simulator.py          # Физика симулятора
├── test_createc.py            # Мок COM-интерфейса  
├── test_deepspm_protocol.py   # Wire protocol парсинг
├── test_deepspm_server.py     # Asyncio server
├── test_queue_models.py       # Pydantic модели
├── test_queue_worker.py       # RabbitMQ consumer
├── test_integration.py        # TransportEnv
└── ...
$ pytest tests/ -v
...
41 passed in 2.34s

Никаких @pytest.mark.skip("needs hardware"). Всё через симулятор и моки.

Архитектура

amrl_transport/
├── transport/
│   ├── protocol.py      # STMTransport ABC (12 методов)
│   ├── createc.py       # Createc COM адаптер (Windows)
│   ├── nanonis.py       # Nanonis TCP адаптер (стаб)
│   ├── simulator.py     # Симулятор с физикой
│   └── factory.py       # config → transport
├── deepspm/
│   ├── protocol.py      # Wire protocol парсер
│   ├── server.py        # asyncio-сервер (замена LabVIEW)
│   ├── client.py        # DeepSPMClient + совместимость
│   └── __main__.py      # python -m amrl_transport.deepspm
├── queue/
│   ├── models.py        # ManipulationTask, AtomTarget (Pydantic)
│   ├── worker.py        # RabbitMQ consumer + backoff + graceful shutdown
│   └── client.py        # submit() → wait_for_result()
├── integration.py       # TransportEnv (drop-in для RealExpEnv)
└── cli.py               # amrl-worker, amrl-submit

Что дальше

Честно — я backend-разработчик, не физик. Атомную физику знаю на уровне «прочитал 20 papers и исходники трёх репозиториев». Поэтому:

  1. Планирую написать issue в DeepSPM — предложить Python-сервер как замену LabVIEW-зависимости. Проект подморожен с 2020, но авторы из Monash University.

  2. Написал в SINGROUP — предложил transport abstraction для их RL-агента. Они активны, последние коммиты в 2025.

  3. Жду фидбек — если кто-то из STM-лабораторий скажет «это полезно» — буду развивать. Если скажут «ты не понимаешь физику» — буду учиться.

Самое крутое, что может произойти: кто-то в лабе с Nanonis возьмёт amrl-transport, напишет NanonisTransport на 200 строк, и запустит SINGROUP'овский агент на своём железе. Без переписывания RL-кода.

Самое реалистичное: пакет полежит на PyPI с 125 скачиваниями, и я напишу в резюме «published open-source scientific tooling».

Оба варианта меня устраивают.

Установка

pip install amrl-transport

Ссылки


Серия audiotools.dev продолжается, но иногда хочется чего-то поинтереснее, чем конвертировать WAV в MP3. Например, двигать атомы.