0

我得到了一个简短的 Python 2.7 脚本,它监视新的 FITS 文件放入目录中,使用 XPA 命令 DS9 8.0.1(Fedora 30,xpa-devel.x86_64 2.1.18-7.f30)的实例一次显示两个帧。

原始脚本使用一系列Popen()命令启动xpaset以格式化 DS9 窗口并指示要加载的文件。该代码已有十年之久,如果没有它和/或 DS9 崩溃/冻结,则无法通过一夜的观察,部分原因是网络延迟影响了 XPA。

我使用 Python 3.7 和 pyds9 (pyds9.noarch 1.8.1-3.2) 从头开始​​重新实现了脚本。当输入 6.5MB 聚焦图像时,新代码和 DS9 将运行一整夜。但是,在加载前两个全尺寸 85MB 图像后,DS9 锁定并需要“kill -9”才能摆脱它。

操作系统、xpa 和 DS9 版本相同,这表明错误出在我的脚本中。复杂情况一直在等待写入 FITS 文件的进程完成并关闭文件。

为简洁起见,我希望 DS9 在使用 pyds9 时冻结的原因从下面的精简样本中可以明显看出。否则,我将对其进行编辑以包含功能代码。

编辑:针对@Iguananaut 的评论,我整合了 DS9 启动等待时间,并将新文件搜索和 wait_til_file_is_stable 函数添加到较新的代码示例中。

原始的基于 Popen() 的指令:

#!/bin/env python
from subprocess import Popen
from time import sleep
import uuid

new_fits_filename = ""
old_fits_filename = ""

display_id='This_Script-' + uuid.uuid4().hex[:6].upper()
ds9_pid = Popen(['ds9','-geometry','940x1200','-title',display_id]).pid
if Popen(['xpaget',display_id,'blink'],stdout=DEVNULL,stderr=DEVNULL).wait() == 0: 
    break
sleep(.5)
Popen(['xpaset','-p',display_id,'scale','mode','zscale'])
Popen(['xpaset','-p',display_id,'frame','1'])
Popen(['xpaset','-p',display_id,'cmap','cool'])
Popen(['xpaset','-p',display_id,'frame','2'])
Popen(['xpaset','-p',display_id,'cmap','bb'])
Popen(['xpaset','-p',display_id,'tile'])
while True:
    [detect new FITS file in NFS target directory]
    Popen(['xpaset','-p',display_id,'frame','1'])
    Popen(['xpaset','-p',display_id,'file','mosaicimage','wcs',directory+'/'+new_fits_filename])
    sleep(1)  # Sleep again to avoid DS9 crashing
    Popen(['xpaset','-p',display_id,'zoom','to','fit'])
    if old_fits_filename != "":
        Popen(['xpaset','-p',display_id,'frame','2'])
        Popen(['xpaset','-p',display_id ,'file','mosaicimage','wcs',directory+ '/'+ old_fits_filename])
        sleep(1)  # Sleep again to avoid DS9 crashing
        Popen(['xpaset','-p',display_id,'zoom','to','fit'])
    old_fits_filename = new_fits_filename

新的基于 pyds9 的指令:

#!/bin/env python3
import glob
import os
from pathlib import Path
import pyds9
from time import sleep
import uuid

def wait_til_file_is_stable(filename):
    the_file = Path(filename)
    the_current_size = 0
    the_previous_size = -1
    while the_current_size != the_previous_size:
        the_previous_size = the_current_size
        the_current_size = the_file.stat().st_size
        sleep(0.5)


global_d = None
fits_folder = Path("/data/fits/new/") # an NFS mount
fits_file_prefix = "image"
fits_file_pattern = fits_file_prefix + "*.fits"
fits_full_path = str(fits_folder.resolve() / fits_file_pattern)
new_fits_filename = ""
old_fits_filename = ""
wait_time_launch = 70

display_id = 'This_Script-' + uuid.uuid4().hex[:6].upper()
global_d = pyds9.DS9(display_id, start="-geometry 940x1200", wait=wait_time_launch, verify=True)
global_d.set('scale mode zscale')
global_d.set('frame 1')
global_d.set('cmap cool')
global_d.set('frame 2')
global_d.set('cmap bb')
global_d.set('tile')
while True:
    sleep(0.5)
    # detect new FITS file in NFS target directory
    dirlisting = glob.glob(fits_full_path)
    if len(dirlisting) > 0:
        new_fits_filename = max(filter(lambda fname: fits_file_prefix in fname, dirlisting), key=os.path.getctime)
    wait_til_file_is_stable(new_fits_filename)

    global_d.set('frame 1')
    global_d.set('file mosaicimage wcs ' + str(new_fits_filename))
    global_d.set('zoom to fit')
    if old_fits_filename != "":
        global_d.set('frame 2')
        global_d.set('file mosaicimage wcs ' + str(old_fits_filename))
        global_d.set('zoom to fit')
    old_fits_filename = new_fits_filename
4

0 回答 0