Scripts Python
Nouveauté de Siril 1.4, il est possible d'écrire des scripts plus avancés en utilisant Python.
This page is a documentation for script developers. If you want more information about what scripts are available as a user, see the list of scripts.
Astuce
La programmation en Python est encore EXPÉRIMENTALE et l'API devrait être améliorée au cours du cycle de développement de la version 1.5.
Dans sa forme actuelle, l'utilisation de scripts Python vous permet de :
Exécutez n'importe quelle commande Siril tout en bénéficiant de l'avantage d'utiliser un véritable langage de programmation, ce qui permet aux variables transmises aux commandes d'être le résultat de calculs.
Accéder aux variables et aux structures de données de Siril pour faciliter la rédaction de scripts.
Accéder aux extensions Python.
En utilisant l'interface de script 1.4, il est possible d'écrire un plugin qui enregistre l'image actuelle, l'ouvre à l'aide d'astropy et applique des techniques de traitement fournies par astropy, puis enregistre le résultat et le rouvre comme image principale de Siril.
L'extension Python tk peut être utilisé pour créer des interfaces graphiques pour vos scripts afin de pouvoir recueillir directement les entrées de l'utilisateur.
Avertissement
Dépendances d'exécution
Pour faciliter l'installation et la configuration du module Python Siril et de ses dépendances, un environnement virtuel Python (venv) est configuré.
Linux
Cela nécessite qu'une installation Python fonctionnelle soit présente sur le système, incluant les modules pip et venv. Ceux-ci sont disponibles par défaut dans les distributions flatpak et appimage, mais vous devrez les installer vous-même si vous compilez Siril à partir des sources. Sur les systèmes basés sur Debian, vous avez besoin des paquets python3-pip et python3-venv installés ; les exigences d'installation sur d'autres systèmes peuvent varier.
Windows
Si vous disposez d'une installation Python sur votre système, le script l'utilisera par défaut. Si ce n'est pas le cas, pas de panique. Siril installé via l'installateur officiel est également fourni avec une installation Python légère et tous les modules requis. Ceci concerne les versions officielles. Si vous compilez la version de développement à partir des sources, vous devrez avoir Python installé sur votre système.
macOS
Les dépendances nécessaires sont incluses dans le paquet officiel MacOS. Nous ne fournissons pas de support pour la compilation via homebrew, mais si vous compilez vous-même sur Mac, vous devrez vous assurer de disposer d'une installation Python système fonctionnelle.
Quel est le rapport avec pySiril ?
pySiril est un module distinct, publié par une équipe de développement distincte : c'est un produit établi déjà utilisé pour mettre en œuvre des applications d'aide importantes telles que Sirilic.
Sur le plan philosophique, pySiril et le module Python intégré de Siril sont assez différents : alors que le module intégré est destiné à être appelé depuis un Siril déjà en cours d'exécution pour fournir des fonctionnalités de script et lance un processus python3 pour exécuter le script, pySiril est destiné à construire des applications ayant besoin de faire appel aux fonctionnalités de Siril, et il lance un processus Siril depuis son application Python hôte.
Ces cas d'usage sont assez différents, et il n'est pas prévu de fusionner les deux modules.
Importer les modules
Siril se chargera de configurer un venv (environnement virtuel Python de nouveau style) et d'y installer le module. Dans votre script, vous l'importez à l'aide de import sirilpy.
Par commodité, vous pouvez l'abréger en import sirilpy as s.
Initialisation de la connexion
Une fois le module importé, vous devez établir l'interface avec Siril. Cela se fait comme suit :
import sirilpy as s
siril = s.SirilInterface()
try:
siril.connect()
print("Connected successfully!")
except SirilConnectionError as e:
print(f"Connection failed: {e}")
(La communication d'informations sur l'état d'avancement est facultative, mais constitue une bonne pratique.)
Exécution des commandes Siril
Pour exécuter une commande Siril, une fois l'interface établie, vous utilisez la fonction siril.cmd(). La commande et ses arguments sont fournis sous forme de liste, par exemple :
siril.cmd("findstar", "-maxstars=1000")
exécutera la commande findstar, en définissant une limite maximale de 1000 étoiles.
La véritable puissance de l'utilisation de python pour scripter des commandes réside dans le fait que vous pouvez utiliser des variables python dans la commande à l'aide de la notation de chaîne formatée :
x = 1000
siril.cmd("findstar", f"-maxstars={x}")
Ceci est un exemple simple, mais la possibilité de définir des paramètres à passer aux fonctions de traitement d'image représente un bond en avant considérable pour le scripting Siril par rapport aux anciens fichiers de script Siril.
Astuce
La plupart des commandes Siril exécutent une action (register, stack, asinh, etc.). Elles fonctionneront exactement de la même manière lorsqu'elles sont appelées depuis python.
Cependant, certaines se contentent d'afficher des informations dans le journal de Siril, comme stat. Notez que ces commandes ne se comportent pas différemment lorsqu'elles sont appelées depuis python à l'aide de siril.cmd("stat") ou similaire : elles se contenteront toujours d'afficher des informations dans le journal de Siril et ne renverront aucune donnée utile au script python.
Pour accéder aux valeurs depuis python, vous devez utiliser une méthode qui récupère des informations sur l'image ou la séquence. Ainsi, dans cet exemple, vous appelleriez img = siril.get_image(), puis les statistiques seraient disponibles dans img.stats.
Avertissement
La méthode cmd() n'a pas de valeur de retour mais lèvera une exception si la commande échoue. Cela fournit un comportement par défaut sûr - le script s'arrêtera en cas d'échec d'une commande et affichera un message d'erreur d'exception dans la console Siril. Si vous souhaitez gérer les échecs de manière plus élégante, par exemple en affichant une boîte de message d'erreur, vous devrez utiliser un gestionnaire d'exceptions comme celui-ci :
try:
siril.cmd("requires", "1.5.0")
except:
siril.error_messagebox("This script is not compatible with this version of Siril")
quit()
À des fins de débogage, vous pouvez souhaiter que les commandes renvoient un booléen. Cela peut être fait à l'aide d'un simple wrapper tel que le suivant :
def cmd_with_check(*args):
try:
siril.cmd(*args)
except Exception as e:
err_msg = ' '.join(list(args))
print(f'Exception caught: {e}',)
print(f"Command failed with arguments: {err_msg} but continuing...")
return False
return True
Accès aux variables et aux structures de données de Siril
Le module siril fournit un accès aux variables clés de Siril. Les données disponibles sont les suivantes :
Répertoire de travail actuel de Siril
Répertoire de configuration utilisateur de Siril (destiné à stocker les paramètres spécifiques aux scripts)
Nom de l'image courant dans Siril
Image actuelle dans Siril :
Données de pixels de l'image
Profil ICC de l'image (sous forme d'octets : vous devrez utiliser un module tel que pillow pour convertir ces données brutes en quelque chose d'utilisable)
Métadonnées de l'image : toutes les métadonnées que Siril utilise en interne, y compris les mots-clés pertinents et les statistiques de l'image. L'en-tête FITS complet ainsi qu'une chaîne contenant les mots-clés non reconnus par Siril sont également disponibles.
Séquence Siril actuelle :
Données de pixels d'une image de séquence
Métadonnées de la séquence : toutes les métadonnées de la séquence actuellement chargée sont disponibles, à l'exception de certaines relatives aux détails du format de séquence qui sont abstraits par l'interface python, et de certaines relatives aux séries photométriques qui ne sont pas encore implémentées. Cela inclut les statistiques de chaque canal de chaque image, les données d'alignement des canaux pour lesquelles elles sont disponibles pour chaque image, et les données de qualité d'image pour chaque image.
Les profils ICC des images d'une séquence ne sont pas disponibles, car ils ne sont généralement pertinents qu'après l'étape de traitement de la séquence. Si un cas d'usage convaincant émerge, cela pourrait être révisé lors d'une mise à jour de l'API dans le cycle de développement 1.5.
Les chaînes HISTORY et d'en-tête FITS des images d'une séquence ne sont pas disponibles car elles ne sont pas considérées comme utiles pour les opérations de séquence, cependant les mots-clés d'une image de séquence sont disponibles via la méthode
siril.get_seq_frame(), qui renvoie un objet FFit avec le membre keywords renseigné. Cela fournit suffisamment de métadonnées pour prendre en charge tout cas d'usage actuellement identifié.
Données de modélisation des étoiles. Lorsque des étoiles ont été détectées dans une image, les données de modélisation sont disponibles sous forme d'une liste de paramètres d'étoile pour chaque étoile détectée dans l'image.
Ces données sont stockées dans les structures de données clés FFit représentant la structure de données FITS de Siril, et Sequence représentant la structure de données de séquence de Siril.
# Get the current image
img = siril.get_image()
# Get its dimensions
siril.log(f"Current image dimensions: {img.shape[1]} x {img.shape[0]}, {img.shape[2]} channels.")
Notez que la forme de l'image est stockée dans un ordre python classique : shape[0] = hauteur, shape[1] = largeur, shape[2] = canaux. La largeur, la hauteur et les canaux sont également directement accessibles à l'aide des propriétés img.width, img.height et img.channels une fois que img = get_image() a été appelé.
Lorsque l'image actuelle est obtenue à l'aide de siril.get_image(), les données de pixels sont accessibles sous forme de tableau numpy, ce qui permet d'opérer directement sur les données de pixels.
import siril
import numpy as np
# Set up the interface as above
# ...
# Try to get the current image, do something to it and update it in Siril
with siril.image_lock():
img = siril.get_image()
img.data[:] *= 2
siril.set_image_pixeldata(img.data)
except Exception as e:
raise SirilException(f"Error changing pixel data: {e}")
Nous venons d'accéder au tableau de pixels et de multiplier chaque valeur de pixel par 2 ! Notez que nous devons appeler la fonction siril.set_image_pixeldata() pour renvoyer les données mises à jour à Siril. En utilisant siril.set_image_pixeldata(), vous pouvez même mettre à jour l'image vers une taille ou une forme différente, ou passer de données non signées 16 bits à des données flottantes 32 bits, ou inversement.
Astuce
Pour que siril.set_image_pixeldata() réussisse, vous devez acquérir un verrou sur l'image. Cela garantit que rien d'autre ne peut essayer de mettre à jour l'image en même temps que vous, et garantit également que vous ne pouvez pas mettre à jour l'image pendant qu'autre chose est déjà en train de le faire. Notez que l'exemple ci-dessus utilise le gestionnaire de contexte siril.image_lock() avant de récupérer l'image depuis Siril, et pas seulement avant de la mettre à jour. Cela garantit que l'image reste verrouillée pendant toute la durée de son traitement, jusqu'à ce qu'elle soit renvoyée à Siril et que le verrou soit enfin libéré.
De manière similaire, vous pouvez accéder aux statistiques de l'image, aux informations de l'en-tête FITS, à la profondeur de bits, etc. Vous pouvez également accéder aux informations de la séquence, par exemple si la n-ième image d'une séquence est incluse, quelles sont ses statistiques, etc.
Installation de modules python
Vous avez peut-être remarqué que nous utilisons NumPy dans les exemples précédents. C'est une dépendance du module siril et elle sera récupérée lors de la configuration initiale du venv. D'autres modules python peuvent être importés à l'aide de la commande standard import, par exemple import astropy as ap. Cependant, pour faciliter l'assurance que les dépendances sont installées si un utilisateur ne les a pas déjà, le module fournit également la méthode ensure_installed(). Elle s'utilise comme suit :
s.ensure_installed("astropy")
import astropy
(ou, pour un autre exemple,
s.ensure_installed("tifffile")
import tifffile
Une vérification est d'abord effectuée pour essayer d'importer le module (dans ce cas, astropy ou tifffile). Si le module n'est pas disponible pour l'importation, une tentative d'installation est effectuée. Si l'installation échoue, une exception est levée et le script s'arrête.
Astuce
Si un module nécessite une installation, cela peut prendre un peu de temps, mais le délai ne se produit que lors de la première exécution d'un script. Lors des exécutions suivantes, le modèle est déjà installé, donc la vérification ensure_installed() est presque instantanée. Un message dans le journal informe l'utilisateur qu'une installation de module est en cours.
Si la vérification réussit, le module peut être importé normalement à l'aide de import.
Astuce
Tous les autres modules non essentiels, à l'exception de numpy, devraient être vérifiés avec ensure_installed() car cela automatise le processus d'installation pour les utilisateurs qui n'ont pas encore les modules requis installés.
Avertissement
Tous les scripts Python de Siril partagent le même venv. Lors de l'importation de modules, il est important d'éviter de trop contraindre les exigences de version afin d'éviter les conflits entre les modules requis par différents scripts. Seules les contraintes de version « >= » devraient être utilisées, jamais « == » ou « <= ».
import sirilpy as s
s.ensure_installed("astropy")
import astropy as ap
Cela récupérera également automatiquement toutes les dépendances d'astropy.
Usage de module externe
Astuce
Le type d'objet siril.FFit n'est pas le même que astropy.io.fits. Alors qu'astropy.io.fits fournit une interface générale basée sur des fichiers pour tous les fichiers FITS, siril.FFit fournit une interface vers la structure de données que Siril utilise pour représenter les images FITS. Les deux ne sont pas directement interchangeables ! Chacune des deux méthodes peut être utilisée pour obtenir les données de pixels sous forme de tableau NumPy.
Que vous obteniez les données de pixels directement à partir de l'objet siril.FFit ou à l'aide d'astropy.io.fits, des modules tels qu'astropy, photutils et matplotlib fournissent les briques de base pour un vaste éventail d'analyses d'images, notamment la détection de sources, la segmentation d'images, la déconfusion de sources et la visualisation, et l'écosystème des modules python offre des possibilités illimitées.
import sirilpy as s
s.ensure_installed("astropy")
import astropy
from astropy.io import fits
with fits.open("filename.fit", mode='update') as image:
if isinstance(image[0].data, np.ndarray):
image[0].data *= 2
Cela ressemble beaucoup à notre dernier exemple - nous nous contentons de multiplier les données de pixels par 2 - mais nous avons maintenant utilisé astropy pour l'ouvrir directement à partir d'un fichier FITS.
Référence de l'API
Notez que l'API est très récente. Bien que nous ferons tout notre possible pour éviter les changements cassant les scripts dans l'API publiée avec la 1.4.0 tout au long de la série stable 1.4, certaines parties de l'API pourront évoluer au cours du cycle de développement 1.5.