pyds9: DS9 GUI зависает после отображения двух больших изображений - PullRequest
0 голосов
/ 07 февраля 2020

Мне дали короткий 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). Новый код и DS9 будут работать всю ночь при подаче фокусирующих изображений 6,5 МБ. Но после загрузки первых двух полноразмерных образов размером 85 МБ DS9 блокируется и требует «kill -9», чтобы избавиться от него.

Версии OS, xpa и DS9 совпадают, предполагая, что ошибка лежит в моем сценарии. Сложность в ожидании процесса, который записывает файлы FITS в fini sh и закрывает файлы.

В интересах краткости, я надеюсь, что причина замораживания 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
...