Bluesky是一个用于实验控制和科学数据和元数据采集的库。它强调以下特点:
1、实时,流式数据:可用于嵌入可视化和处理。
2、丰富元数据:获取和组织来方便复制性和可检索性。
3、实验通用性:对完全不同的硬件无缝地重新使用一个过程。
4、中断恢复:实验是可倒带的,从中断中干净的恢复。
5、自动化的暂停/继续:实验可以无值守地运行,根据需要,自动地暂停和继续。
6、可插拔I/O:导出数据(实时)到任何所需格式或数据库。
7、自定义:自由地集成自定义实验过程和命令,并且获取I/O和中断特性。
8、集成科学Python:自然地连接了numpy和Python科学栈。
如何使用本文档
从本教程开始。这是对任何人开始的好地方,它用叙述的方式概况了本项目。根据你的需要阅读来解决你的问题,并且如果你需要更改,再次回来。本教程的每一章为了深入的自定义添加了一段综合性。
余下章节用较少叙述风格记录了bluesky的行为,提供清楚的API文档,内部混合了一些示例和设计和目的的解释。
索引
用户文档
1、教程
2、计划
3、文档
Bluesky教程
在你开始前
注意:NSLS-II部署了一个免费,公开的"沙盒",用于在浏览器中使用Jupyter notebooks尝试这个软件。将不需要安装任何软件,并且你可以跳过本章余下部分。转到Jupyter Server。
你将需要Python 3.8或者更新的。从一个shell,检查你当前Python的版本。
(bluesky-tutorials) [blctrl@localhost ~]$ python3 --version
Python 3.8.18
如果那个版本低于3.8,你必须升级它。
我们推荐安装bluesky到"虚拟环境",因此这个安装将不干扰任何已有的Python软件:
python3 -m venv ~/bluesky-tutorial
source ~/bluesky-tutorial/bin/activate
另外,如果你是一个conda用户,你可以创建一个conda环境:
conda create -n bluesky-tutorial "python>=3.8"
conda activate bluesky-tutorial
安装最新版本的bluesky和ophyd。除非你打算跳过有关访问保存数据的章节,也安装databroker。如果你想要跟随可视化示例,安装matplotlib和PyQt5。最后安装IPython(由科学家为科学家设计的一款Python解析器)。
python3 -m pip install --upgrade bluesky ophyd databroker matplotlib pyqt5 ipython pyepics
另外,如果你是一个conda用户以及你首选conda包,你可以使用:
conda install -c nsls2forge bluesky ophyd databroker matplotlib pyqt=5 ipython
启动IPython:
(bluesky-tutorials) [blctrl@localhost miniconda3]$ ipython --matploblib=qt5
[TerminalIPythonApp] WARNING | Unrecognized alias: 'matploblib', it will have no effect.
Python 3.8.18 (default, Sep 11 2023, 13:40:15)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.12.3 -- An enhanced Interactive Python. Type '?' for help.
In [1]:
标记--matploblib=qt5是对于实时更新绘图运行是必需的。
或者,如果你从一个Jupyter notebook使用bluesky,向如下安装一个内核:
ipython kernel install --user --name=bluesky-tutorial --display-name "Python (bluesky)"
你可能从已经安装它的任何环境启动Jupyter,或者在和bluessky一起在这个环境中安装它并且从那里运行它:
jupyter notebook
如果你迷惑或者困惑...
...则我们想要知道。我们有一个友好的聊天通道,或者你可以提交一个bug让我们知道我们的文档在哪里能够变得更加清晰。
RunEngine
Bluesky编码一个实验过程成为一个计划(plan),一个原子指令的序列。这个RunEngine是一个用于计划(plans)的解析器。它让我们聚焦我们实验过程的逻辑,而它一致地处理重要的技术细节:它与硬件通信,监视中断,组织元数据和数据,协调I/O并且确保硬件在退出时留在了一个安全状态。
从指令集分离执行器(RunEngine)从若干方面得到了回报,如我们将在以下示例中见到的。
注意:如果你是一个在运行了bluesky的设施的访问用户,你可以跳过本章并且直接到公共实验("plans")。一个RunEngine将已经为你配置了。如果你忽略这个并且定义你自己的,你可以重写预配置的默认值,这可能导致数据丢失。
要检查,输入RE。如果一个RunEngine已经被配置了,你应该看到像以下的内容:
并且你应该跳过本章剩下部分。但如果这给你一个NameError,你将需要完成本章。
创建一个RunEngine:
这个RunEngine已经准备使用,但如果你关心可视化或者保存你的数据,首先有更多要做的...
在数据采集过程中,RunEngine分派一个元数据和数据的实时流到一个或多个消费者("回调"),用于内联数据处理和可视化以及长期存储。示例消费者包括一个实时更新的绘图,一个曲线拟合算法,一个数据库,一个消息队列或者一个按你首选格式的文件。详细见实时可视化和处理。
准备实时可视化
要开始,让我们使用通用的BestEffortCallback。
BestEffortCallback将实时接收元数据/数据并且产生绘图和文本,尽最大可能在"综合性"和"压倒性"之间提供达到正确平衡的实时反馈。
对于更针对性的反馈,自定义一个特定实验,你可以配置自定义回调。通过阅读到文档开始,bluesky在实验中组织捕获的元数据和数据到这个结构体。但对于本教程和对于很多真实实验,BestEffortCallback将足够。
准备数据存储
databroker,一个与bluesky一起开发的库,是一个用于由bluesky产生的元数据和数据的可搜索存储的接口。对于本教程,我们将逐步讲述一个由临时文件支持的databroker。
警告:本实验产生了一个临时数据库。不要对重要数据使用它。一旦Python退出或者变量db被删除,数据访问将变得困难。第二次运行Broker.named('temp'),创建一个全新的,单独的临时数据库。
添加一个进度栏
你可以可选地配置一个进度栏。
更详细和配置见进度栏。
让我们采集一些数据!
公共实验("Plans")
读取一些探测器
从一个非常简单实验开始:触发并且读取一些探测器。Bluesky称这位"计数",一个从光谱学社区继承地术语。
对于本教程,我们将不认为你使用了真实地探测器或电机。在以下示例中,我们将使用来自ophyd的仿真硬件,一个与bluesky一起开发的库。在之后章节,我们将看到用ophyd配置真实硬件看起来像什么。
使用RunEngine,RE, "计数"这些探测器:
bluesky一个重要特性是这些探测器可以是简单的光电二极管或复杂的CCDs。所有那些细节在Device的实现中被捕获。从bluesky的视角,探测器只是具有某些方法的Python对象。
更多选项见count()。你也可以在IPython中输入count?查看这个文档。
尝试以下变体:
1、连续5此读取
2、5次顺序读取,每次之间延时1秒钟
3、一个延时变体
count()函数(更准确,Python生成器函数)是一个plan的示例,一个编码了实验过程的指令序列。我们将随着我们继续更加理解这种设计为什么有用。简要的,它赋予我们能够:
1、在我们执行指令前检查它们,检查精度,安全性,估计持续时间灯。
2、中断和"重新开始"这些指令到一个安全点继续,交互的和自动的(例如在午夜)。
3、对不同硬件再次使用一个通用指令集合。
4、以编程方式修改指令,诸如在每次实验前插入一个要被自动执行的基线读取集合。
警告:
注意通过它自己输入一个计划不做任何事情:
如果我们打算执行这个计划,我们必须使用RunEngine:
扫描
使用scan()以10等分步长从-1到1扫描motor,等待它到达每一步,接着触发并且读取某个探测器det。
bluesksy的一个重要特性是motor可以是任何"可移动的"设备,包括一个温度控制器,一个样品更换器或者某个伪轴。从bluesky和RunEngine的视角,所有这些只是Python中带有某个方法的对象。
另外,产生一个表格和绘图,BestEffortCallback计算基本的峰统计数据。在绘图区域上点击并且按Shift+P("peak")来在数据上可视化它们。数值(质心,最大值灯)以bec.peaks隐藏在一个字典中。这是在每次运行结束时被更新。当然,如果峰统计不可用,你只需忽略这个特性。
使用rel_scan()相对于当前位置从-1扫描到1。
from bluesky.plans import rel_scan
RE(rel_scan(dets, motor, -1, 1, 10))
使用list_scan()扫描某个任意间隔的点。
from bluesky.plans import list_scan
points = [1, 1, 2, 3, 5, 8, 13]
RE(list_scan(dets, motor, points))
扫描变体和其他计划的完整列表,见Plans。
一起扫描多个电机
通过语句"一起扫描多个电机",我们可能是说两种不同的东西。在这种情况下,我们表示我们用M步沿一条线移动N个电机,就像沿对角线移动X和Y电机。在另一种情况,我们通过一个(M_1 * M_2 * ... * M_N)网格移动N个电机。
SPEC用户会类似一个"a2scan"或"d2scan"识别这种情况,但任意维度,不限于2维。
我们将使用我们在先前章节中使用相同的计划。(如果你经导入它们,不需要再次做这件事)。
from bluesky.plans import scan, rel_scan
我们将使用两个新电机和一个新探测器,通过一个仿真耦合这个探测器跟电机。它模拟一个峰中心在(0,0)的2D高斯峰。我们再次强调这些"电机"可以是能被设置的任何东西(温控器,伪轴,换样装置)。
from bluesky import RunEngine
from bluesky.plans import scan, rel_scan
from ophyd.sim import det4, motor1, motor2
from bluesky.callbacks.best_effort import BestEffortCallback
RE = RunEngine({})
bec = BestEffortCallback()
RE.subscribe(bec)
dets = [det4] # just one in this case, but it could be more than one
RE(scan(dets,
motor1, -1.5, 1.5, # scan motor1 from -1.5 to 1.5
motor2, -0.1, 0.1, # ...while scanning motor2 from -0.1 to 0.1
11)) # ...both in 11 steps
这对任意数目电机有效,不限于2个。尝试从opyd.sim导入motor3并且运行一个3-motor扫描。
要沿着任何轨迹而不是等间隔点移动电机,使用list_scan()和rel_list_scan()。
from bluesky.plans import list_scan
# Scan motor1 and motor2 jointly through a 5-point trajectory.
RE(list_scan(dets, motor1, [1, 1, 3, 5, 8], motor2, [25, 16, 9, 4, 1]))
在网格中扫描多个电机
在这种情况中,扫描N个电机通过一个N维矩形网格。我们将使用在先前章节中相同的仿真硬件。我们将使用一个新计划,名为grid_scan()。我们用3*5的网格开始。
from ophyd.sim import det4, motor1, motor2
from bluesky.plans import grid_scan
dets = [det4] # just one in this case, but it could be more than one
RE(grid_scan(dets,
motor1, -1.5, 1.5, 3, # scan motor1 from -1.5 to 1.5 in 3 steps
motor2, -0.1, 0.1, 5, # scan motor2 from -0.1 to 0.1 in 5 steps
))
电机的顺序控制了如何遍历网格。"最慢的"轴首先出现。Numpy用户将感激这与numpy的索引多维数组的规则一致。
可选参数snake_axes可以用于控制哪个电机的轨迹来回"蛇形"。一个蛇形路径通常更加高效,但它不适合某种硬件,因此默认它被禁用。要对特定轴启用蛇形,传一个像snake_axes=[motor2]的列表。由于第一个(最慢)轴通常只被遍历一次,在snake_axes中包括它是不合理的。为了方便,你可以使用snake_axes=True为除第一个轴外的所有轴启动蛇形。
要沿任意轨迹移动电机而不是等分点,使用list_grid_scan()和rel_list_grid_scan()。
from bluesky.plans import list_grid_scan
RE(list_grid_scan(dets,
motor1, [1, 1, 2, 3, 5],
motor2, [25, 16, 9]))
见多维扫描来处理更特定的情况,包括组合像scan()和像grid_scan()的移动。
更一般,Plans文档包括了更奇特的轨迹,诸如螺旋,以及带有自适应逻辑的计划,注入搞笑寻峰工具。