PRESTO 是一款由 Scott Ransom 主导开发的开源脉冲星搜索与分析工具套件,主要用于高效处理天文观测数据,特别是射电望远镜捕获的脉冲星信号,可以从球状星团的长期观测中高效搜索双毫秒脉冲星(尽管此后它已用于几次短时间积分调查,并用于处理大量 X 射线数据)。它主要用 ANSI C 编写,许多最新例程都用 Python 编写。
目前,PRESTO 已经发现了超过 1000 颗脉冲星,其中包括约 400 颗再生脉冲星和/或双脉冲星。
核心功能
- 数据准备:支持干扰检测(
rfifind
)、去散射(prepdata
)、天文时标校准等预处理。 - 搜索算法:采用傅里叶加速搜索(
accelsearch
)、单脉冲搜索(single_pulse_search.py
)及相位调制搜索(search_bin
)。 - 折叠与分析:优化候选信号(
prepfold
)并生成到达时间(TOA)数据(get_TOAs.py
)。 - 多格式支持:兼容 PSRFITS、SIGPROC 滤波器银行、光子到达时间等多种数据格式。
应用领域
- 脉冲星搜寻:适用于各类望远镜数据,尤其擅长处理球状星团的长期观测数据。
- 双星系统研究:对毫秒脉冲星的双星伴星进行精确分析。
- 高能天体物理:处理 X 射线等高能数据,探测隐藏的脉冲信号。
- 引力波探测:通过脉冲星计时阵列分析引力波效应。
下面是PRESTO的本地部署教程,希望能帮助到大家~
一、更新基础软件包
1. 直接安装大部分依赖包
在类似 Debian/Ubuntu 的系统上执行此操作:
# 更新 apt-get
apt-get update -y
apt-get upgrade -y
# 安装 sudo
apt-get install -y sudo
# 安装其他必要的软件包
sudo apt-get install -y git build-essential libfftw3-bin libfftw3-dev pgplot5 libglib2.0-dev libcfitsio-bin libcfitsio-dev libpng-dev latex2html gfortran tcsh autoconf libx11-dev python3-dev python3-numpy python3-pip mpich openmpi-common libmpich-dev
2. 编译安装 TEMPO
- 下载编译安装
cd /usr/local
sudo git clone git://git.code.sf.net/p/tempo/tempo
cd tempo/
sudo sh prepare
sudo ./configure --prefix=/usr/local/tempo
sudo make
sudo make install
sudo make clean
- 加入全局变量
sudo vim /etc/profile
- 末尾添加
# TEMPO
export TEMPO=/usr/local/tempo
export PATH=$PATH:/usr/local/tempo/bin
- 然后激活环境变量
source /etc/profile
source ~/.bashrc
tempo -v
二、环境配置
1. 从 github 仓库 获取项目
PRESTO 源代码采用 GPL 发布,可以通过多种方式浏览或获取(包括压缩文件或 tar 文件,或通过 git)。 如果你懒得读取如何获取,但系统中安装了 git,请执行:
cd ~
git clone https://github.com/scottransom/presto.git
2. 创建并激活 Python 虚拟环境
- 创建并激活虚拟环境
conda create -n presto python=3.9 -y
conda activate presto
- 安装部分依赖
conda install meson meson-python ninja -y
- 添加环境变量
vim ~/.bashrc
- 添加环境变量,注意修改根目录
# presto
export PRESTO=/root/presto
export LIBRARY_PATH=/root/miniconda3/envs/presto/lib/x86_64-linux-gnu:$LIBRARY_PATH
export LD_LIBRARY_PATH=/root/miniconda3/envs/presto/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
- 重启终端
source .bashrc
3. 配置 meson 构建
- 配置
meson
方式:
cd $PRESTO
conda activate presto
meson setup build --prefix=$CONDA_PREFIX
4. 根据配置检查环境变量
cd $PRESTO
python check_meson_build.py
- 如果一切看起来都很好,它会告诉你。
5. 构建并安装所有 C/Fortran 代码和 PRESTO 共享库
meson compile -C build
meson install -C build
6. 编译并安装 PRESTO Python 代码和库
cd $PRESTO/python
pip install --config-settings=builddir=build .
7. 运行 makewisdom 以获得(稍微)快速的 FFT
- 只需运行 $PRESTO/build/src/makewisdom。
cd $PRESTO/build/src/
./makewisdom
mv fftw_wisdom.txt $PRESTO/lib/
运行大约需要10-20 分钟,所以请耐心等待。请注意,fftw_wisdom.txt 文件将位于 $PRESTO/build/src,因此您需要将其移动到 $PRESTO/lib,以便 PRESTO 可以找到它。运行大约需要 10-20 分钟,所以要有耐心。请注意,fftw_wisdom.txt 文件将位于 $PRESTO/build/src 中,因此您需要将其移动到 $PRESTO/lib 以便 PRESTO 可以找到它。
三、运行测试
1. 运行一些基本测试
cd $PRESTO
prepfold
python tests/test_presto_python.py
python examplescripts/ffdot_example.py
python python/fftfit_src/test_fftfit.py
2. 定位需要修改的脚本
根据错误日志,问题出现在文件 /root/presto/examplescripts/ffdot_example.py
的第 62 行:
ppgplot.pgopen(device)
device
是 PGPLOT 图形库的输出设备。- 默认值为
"/xw"
,表示输出到 X11 窗口。
3. 修改图形输出方式
我们可以将输出设备从 "/xw"
修改为文件输出,例如 PostScript(".ps"
)或 PNG(通过 pgplot
配置支持)。
- 修改示例
打开并编辑 /root/presto/examplescripts/ffdot_example.py
:
- 使用文本编辑器(如
nano
或vim
)打开脚本:
vim /root/presto/examplescripts/ffdot_example.py
- 找到
ppgplot.pgopen
调用,并将device
参数修改为输出到文件:
ppgplot.pgopen("output.ps") # 将图形保存为 PostScript 文件
或:
ppgplot.pgopen("/png") # 如果支持 PNG 输出
- 保存并退出编辑器。
- 以下是经过整理和优化后的完整代码,针对脚本进行了调整,支持输出到 PNG 文件,设置了更直观的错误处理,并保留了原始绘图逻辑:
import numpy as num
from presto import presto
import presto.ppgplot as ppgplot
from presto.Pgplot import pgpalette
from numpy.random import standard_normal as norm
import time
import os
# 设置默认 PGPLOT 设备
os.environ['PGPLOT_DEV'] = '/PNG'
# 参数定义
N = 2**14
r = N / 4.0 # 平均频率
rint = num.floor(r)
dr = 1.0 / 32.0
dz = 0.18
np = 512 # 图像分辨率
z = 10.0 # 平均傅里叶频率导数
w = -40.0 # 二次导数
noise = 1.0 * norm(N)
# 时间坐标
us = num.arange(N, dtype=num.float64) / N # 归一化时间坐标
r0 = r - 0.5 * z + w / 12.0
z0 = z - 0.5 * w
phss = 2.0 * num.pi * (us * (us * (us * w / 6.0 + z0 / 2.0) + r0))
ft = presto.rfft(num.cos(phss) + noise)
# F-Fdot 平面计算
ffdot = presto.ffdot_plane(ft, rint - np / 2 * dr, dr, np, 0.0 - np / 2 * dz, dz, np)
pffdot = presto.spectralpower(ffdot.flat)
theo_max_pow = N**2.0 / 4.0
frp = max(pffdot) / theo_max_pow
print(f"Recovered {frp:.3f} of theoretical signal power in F-Fdot plane")
# 优化计算
a = time.perf_counter()
[maxpow, rmax, zmax, rd] = presto.maximize_rz(ft, r + norm(1)[0] / 5.0, z + norm(1)[0], norm=1.0)
print(f"Time for rz optimization {time.perf_counter() - a:.3g} s")
print(f" Optimization recovered {maxpow / theo_max_pow:.3f} of theoretical signal power")
a = time.perf_counter()
[maxpow, rmax, zmax, wmax, rd] = presto.maximize_rzw(ft, r + norm(1)[0] / 5.0, z + norm(1)[0],
w + norm(1)[0] * 5.0, norm=1.0)
print(f"Time for rzw optimization {time.perf_counter() - a:.3g} s")
print(f" Optimization recovered {maxpow / theo_max_pow:.3f} of theoretical signal power")
# F-Fdot 图像准备
pffdot = pffdot / theo_max_pow
pffdot.shape = (np, np)
rs = num.arange(np) * dr - np // 2 * dr
zs = num.arange(np) * dz - np // 2 * dz
rgx = num.asarray([rs[0], rs[np - 1]])
rgy = num.asarray([zs[0], zs[np - 1]])
freqcut = pffdot[np // 2, :]
fdotcut = pffdot[:, np // 2]
# 绘图部分
device = 'ffdot_combined.png/PNG' # 输出为 PNG 文件
image = 'antirainbow'
labx = 'Fourier Frequency Offset (bins)'
laby = 'Fourier Frequency Derivative (bins)'
contours = num.asarray([0.1, 0.3, 0.5, 0.7, 0.9])
imfract = 0.65
margin = 0.08
try:
ppgplot.pgopen(device)
except Exception as e:
print(f"Error opening device: {e}")
device = 'output.ps/PS' # 回退到 PostScript 输出
ppgplot.pgopen(device)
ppgplot.pgpap(0.0, 1.0)
ppgplot.pgpage()
# 绘制文字信息
ppgplot.pgsvp(margin + imfract, 1.0 - margin / 2, margin + imfract, 1.0 - margin / 2)
ppgplot.pgswin(0.0, 1.0, 0.0, 1.0)
ppgplot.pgtext(0.1, 0.8, f"Frac Recovered: {frp:.3f}")
ppgplot.pgtext(0.1, 0.6, f"Signal Power: {frp:.3f}")
ppgplot.pgtext(0.1, 0.4, f"Signal z = {z:.1f}")
ppgplot.pgtext(0.1, 0.2, f"Signal w = {w:.1f}")
# 绘制频率切片
ppgplot.pgsvp(margin, margin + imfract, margin + imfract, 1.0 - margin / 2)
ppgplot.pgswin(min(rs), max(rs), -0.1, 1.1)
ppgplot.pgbox("BCST", 0.0, 0, "BCNST", 0.0, 0)
ppgplot.pgline(rs, freqcut)
ppgplot.pgmtxt("L", 2.0, 0.5, 0.5, "Relative Power")
# 绘制导数切片
ppgplot.pgsvp(margin + imfract, 1.0 - margin / 2, margin, margin + imfract)
ppgplot.pgswin(-0.1, 1.1, min(zs), max(zs))
ppgplot.pgbox("BCNST", 0.0, 0, "BCST", 0.0, 0)
ppgplot.pgline(fdotcut, zs)
ppgplot.pgmtxt("B", 2.4, 0.5, 0.5, "Relative Power")
# 绘制 F-Fdot 图像
ppgplot.pgsvp(margin, margin + imfract, margin, margin + imfract)
ppgplot.pgswin(min(rs), max(rs), min(zs), max(zs))
ppgplot.pgmtxt("B", 2.4, 0.5, 0.5, labx)
ppgplot.pgmtxt("L", 2.0, 0.5, 0.5, laby)
lo_col_ind, hi_col_ind = ppgplot.pgqcol()
lo_col_ind = lo_col_ind + 2
ppgplot.pgscir(lo_col_ind, hi_col_ind)
pgpalette.setpalette(image)
ppgplot.pgctab(pgpalette.l, pgpalette.r, pgpalette.g, pgpalette.b)
ppgplot.pgimag_s(pffdot, 0.0, 0.0, rgx[0], rgy[0], rgx[1], rgy[1])
ppgplot.pgsci(1)
ppgplot.pgcont_s(pffdot, len(contours), contours, rgx[0], rgy[0], rgx[1], rgy[1])
ppgplot.pgbox("BCST", 0.0, 0, "BCST", 0.0, 0)
# 灰色轴线
ppgplot.pgscr(1, 0.5, 0.5, 0.5)
ppgplot.pgsci(1)
ppgplot.pgslw(2)
ppgplot.pgline(rgx, num.asarray([0.0, 0.0]))
ppgplot.pgline(num.asarray([0.0, 0.0]), rgy)
ppgplot.pgclos()
print("Plot saved to:", device)
4. 主要改动
- 默认输出设备改为 PNG 文件。
- 增加对设备错误的处理,自动回退到 PostScript 输出。
- 简化和整理了注释,使代码更易读。
- 添加了可调整的调色板和文件路径。
运行代码后,结果将保存为 ffdot_combined.png
,可以直接查看。
四、如果你想卸载所有东西,你可以这样做:
cd $PRESTO/build
ninja uninstall
pip uninstall presto