JSol’Ex utilise GraalPy pour exécuter du code Python. Les scripts Python peuvent être utilisés de deux manières :
-
Fichiers
.pyautonomes : Utilisez Python directement comme langage de script -
Intégrés dans ImageMath : Utilisez les fonctions
python()oupython_file()dans les scripts.math
Les deux approches vous donnent accès aux structures de contrôle de Python (boucles, conditions, gestion des exceptions) tout en pouvant appeler toutes les fonctions ImageMath via le module jsolex.
Utilisation de base
Le code Python peut être intégré dans les scripts ImageMath sous forme de chaîne multi-lignes :
[outputs]
result = python("""
img = jsolex.funcs.img(0)
result = jsolex.funcs.sharpen(img, 1.5)
""")
Ou en référençant un fichier Python externe :
[outputs]
result = python_file("scripts/process.py")
Par défaut, seul Python pur avec la bibliothèque standard est supporté. Pour les bibliothèques externes comme NumPy, voir Utiliser des bibliothèques externes (NumPy, etc.).
Utiliser des bibliothèques externes (NumPy, etc.)
Pour utiliser des bibliothèques externes comme NumPy, configurez un environnement virtuel GraalPy.
Pour de meilleures performances, installez NumPy et PyArrow ensemble. PyArrow permet un transfert de données efficace sans copie entre Java et Python, accélérant significativement les opérations toNumpy() et fromNumpy() sur les grandes images.
|
Support par plateforme
| Windows ne supporte pas NumPy ni les autres extensions natives. GraalPy sous Windows ne peut installer que des packages Python purs (pas d’extensions C, pas de compilation depuis les sources). NumPy, PyArrow et les bibliothèques similaires nécessitant du code natif ne fonctionneront pas. Si vous avez besoin de ces bibliothèques, utilisez Linux ou macOS. |
Sous Windows, vous pouvez tout de même utiliser GraalPy pour du scripting Python pur (sans import numpy). Pour mettre cela en place, passez directement à [graalpy-venv-windows].
Étape 1 : Installer GraalPy
Téléchargez et installez GraalPy depuis la page officielle de GraalPy.
Étape 2 : Installer les prérequis (Linux / macOS uniquement)
NumPy peut nécessiter une compilation depuis les sources sous GraalPy, ce qui requiert un compilateur C et l’utilitaire patch.
Linux
Installez un compilateur C et patch s’ils ne sont pas déjà disponibles :
# Debian/Ubuntu
sudo apt install build-essential patch
# Fedora
sudo dnf install gcc gcc-c++ patch
macOS
Installez les outils en ligne de commande Xcode s’ils ne sont pas déjà installés :
xcode-select --install
Étape 3 : Créer un environnement virtuel et installer les packages
Choisissez un répertoire pour votre environnement virtuel, par exemple graalpy-venv dans votre dossier personnel.
Linux / macOS
graalpy -m venv ~/graalpy-venv
~/graalpy-venv/bin/pip install numpy pyarrow
| L’installation peut prendre plusieurs minutes si NumPy doit être compilé depuis les sources. |
Windows (Python pur uniquement, sans NumPy)
graalpy -m venv C:\Users\<votre-utilisateur>\graalpy-venv
Sous Windows, l’environnement virtuel place les exécutables dans le dossier Scripts (et non bin). Pour installer des packages Python purs, utilisez le python.exe de l’environnement virtuel avec le flag --no-cache-dir : C:\Users\<votre-utilisateur>\graalpy-venv\Scripts\python.exe -m pip --no-cache-dir install <package>.
|
Étape 4 : Configurer JSol’Ex
Dans JSol’Ex, allez dans Fichier → Paramètres avancés → Scripting Python et naviguez vers l’exécutable GraalPy dans votre environnement virtuel :
-
Windows :
C:\Users\<votre-utilisateur>\graalpy-venv\Scripts\graalpy.exe -
Linux / macOS :
~/graalpy-venv/bin/graalpy
Redémarrez JSol’Ex pour que le changement prenne effet.
Dépannage
pip n’est pas reconnu (Windows) — N’appelez pas pip ou pip.exe directement. Utilisez Scripts\python.exe -m pip --no-cache-dir install … depuis l’environnement virtuel.
L’installation de NumPy échoue sous Windows — GraalPy sous Windows ne supporte pas les extensions natives. NumPy ne peut pas être installé. Utilisez Linux ou macOS si vous avez besoin de NumPy.
GraalPy needs the 'patch' utility (Linux / macOS) — Installez la commande patch via le gestionnaire de packages de votre système (voir les prérequis ci-dessus).
Avertissements de certificats SSL (Windows) — L’avertissement unable to enumerate Windows certificate store peut être ignoré sans risque ; il n’empêche pas l’installation des packages.
Une fois configuré :
import numpy as np
img = jsolex.funcs.img(0)
data = jsolex.toNumpy(img)
enhanced = np.clip(data * 1.5, 0, 65535).astype(np.float32)
result = jsolex.fromNumpy(enhanced)
Le module jsolex
Les scripts Python ont accès au module jsolex, qui fournit le pont vers les fonctionnalités ImageMath.
# Disponible comme global dans les scripts en ligne
img = jsolex.funcs.img(0)
# Ou via import dans les fichiers externes
import jsolex
img = jsolex.funcs.img(0)
# Import sélectif
from jsolex import funcs, vars
img = funcs.img(0)
Appeler des fonctions ImageMath (jsolex.funcs)
Toutes les fonctions ImageMath sont disponibles via jsolex.funcs :
img = jsolex.funcs.img(0) # Obtenir l'image au décalage 0
sharpened = jsolex.funcs.sharpen(img, 3) # Accentuer l'image
enhanced = jsolex.funcs.clahe(sharpened, 8, 2, 1) # Appliquer CLAHE
colorized = jsolex.funcs.colorize(enhanced, "H-alpha")
# Les fonctions peuvent être appelées avec des arguments positionnels ou nommés
result = jsolex.funcs.crop(img, x=100, y=100, width=500, height=500)
Les noms de fonctions sont insensibles à la casse :
img1 = jsolex.funcs.IMG(0) # Fonctionne
img2 = jsolex.funcs.img(0) # Fonctionne aussi
Les fonctions ImageMath définies par l’utilisateur sont également accessibles :
[fun:enhance img]
result = sharpen(clahe(img, 8, 2.0), 1.5)
[outputs]
processed = python("""
img = jsolex.funcs.img(0)
result = jsolex.funcs.enhance(img) # Appeler la fonction utilisateur
""")
Accéder aux variables (jsolex.vars)
Les variables ImageMath sont accessibles via jsolex.vars :
# Lire les variables définies dans ImageMath
continuum = jsolex.vars.continuum
doppler = jsolex.vars.doppler
# Écrire des variables (pour utilisation dans ImageMath)
jsolex.vars.my_result = processed_image
Fonctions utilitaires
| Fonction | Description |
|---|---|
|
Charge une image depuis un fichier |
|
Sauvegarde une image en fichier FITS |
|
Émet une image vers l’interface JSol’Ex pendant l’exécution |
|
Récupère un paramètre de script ou une variable par son nom |
|
Récupère les paramètres de traitement courants |
|
Retourne |
|
Convertit l’image en tableau NumPy (nécessite NumPy) |
|
Crée une image à partir d’un tableau NumPy (nécessite NumPy) |
|
Copie les métadonnées (ellipse, paramètres solaires) entre images |
Émettre des images
Les scripts peuvent émettre des images vers l’interface JSol’Ex pendant l’exécution :
jsolex.emit(img, "Mon Image")
# Avec des paramètres optionnels
jsolex.emit(img, "Améliorée",
name="amelioree_v1",
category="Traitement",
description="Luminosité x1.5")
Scripts Python autonomes
Les fichiers Python (.py) peuvent être utilisés directement comme scripts, comme les fichiers ImageMath (.math).
Ouvrez un fichier .py dans l’éditeur ImageMath ou sélectionnez "Python" comme langage de script.
Métadonnées du script
Les scripts autonomes doivent inclure des commentaires de métadonnées en début de fichier :
# meta:title = "Mon Script d'Analyse"
# meta:title:en = "My Analysis Script"
# meta:author = "Votre Nom"
# meta:version = "1.0"
# meta:requires = "4.6.0"
# meta:description = "Effectue une analyse d'image avancée"
import jsolex
img = jsolex.funcs.img(0)
result = jsolex.funcs.sharpen(img, 1.5)
| Métadonnée | Description |
|---|---|
|
Titre du script (requis pour les dépôts) |
|
Titre localisé (ex: |
|
Nom de l’auteur (requis pour les dépôts) |
|
Version du script (requis pour les dépôts) |
|
Version minimale de JSol’Ex requise |
|
Description du script |
Paramètres du script
Les scripts peuvent déclarer des paramètres affichés dans une boîte de dialogue :
# meta:title = "Script d'accentuation"
# meta:author = "Votre Nom"
# meta:version = "1.0"
# param:strength:type = number
# param:strength:default = 1.5
# param:strength:min = 0.5
# param:strength:max = 3.0
# param:strength:name = "Force d'accentuation"
# param:strength:description = "Quantité d'accentuation à appliquer"
import jsolex
strength = jsolex.getVariable('strength')
img = jsolex.funcs.img(0)
result = jsolex.funcs.sharpen(img, strength)
Types de paramètres :
-
number- Valeur numérique avec bornes min/max optionnelles -
string- Saisie de texte -
choice- Sélection dans une liste (utilisez# param:nom:choices = "option1,option2,option3")
Points d’entrée : single() et batch()
Les scripts autonomes peuvent définir des fonctions spéciales pour le traitement par lots :
single() - Appelée une fois pour chaque fichier d’entrée. Définissez les sorties avec la variable outputs.
batch(results) - Appelée une fois après tous les fichiers. Reçoit les sorties collectées de tous les appels single().
# meta:title = "Analyse de netteté"
# meta:author = "Votre Nom"
# meta:version = "1.0"
import jsolex
import numpy as np
def single():
"""Appelée pour chaque fichier"""
img = jsolex.funcs.img(0)
data = jsolex.toNumpy(img)
# Calculer la métrique de netteté
gy, gx = np.gradient(data.astype(np.float64))
sharpness = float(np.var(np.sqrt(gx**2 + gy**2)))
# Définir les valeurs de sortie
outputs.sharpness = sharpness
outputs.filename = jsolex.getSourceInfo()["fileName"]
def batch(results):
"""Appelée une fois après tous les fichiers"""
sharpness_values = results.sharpness
filenames = results.filename
best_idx = np.argmax(sharpness_values)
print(f"Meilleur : {filenames[best_idx]} (netteté={sharpness_values[best_idx]:.1f})")
outputs.best_sharpness = max(sharpness_values)
Si vous ne définissez que single(), chaque fichier est traité indépendamment.
Si vous ne définissez que batch(), le script s’exécute une seule fois après tous les fichiers.
Si aucune n’est définie, le code de niveau supérieur s’exécute pour chaque fichier en utilisant la variable result.
Publication dans les dépôts
Les scripts Python peuvent être publiés dans les dépôts de scripts aux côtés des scripts ImageMath.
Pour les archives zip, créez un fichier main.txt référençant votre script principal :
mon-script.py
Si aucun main.txt n’existe et que le zip contient exactement un fichier .py (sans fichiers .math), ce fichier est utilisé automatiquement.
Intégrer Python dans ImageMath
Lors de l’intégration de Python dans les scripts ImageMath, utilisez python() ou python_file().
Retourner des valeurs
La variable result détermine ce que Python retourne à ImageMath :
# Retourner une image
img = jsolex.funcs.img(0)
result = jsolex.funcs.sharpen(img, 1.5)
# Retourner un nombre
import numpy as np
data = jsolex.toNumpy(jsolex.funcs.img(0))
result = float(np.mean(data))
# Retourner une chaîne
result = jsolex.getSourceInfo()['fileName']
Pour retourner plusieurs valeurs, définissez des variables ImageMath :
jsolex.vars.processed = jsolex.funcs.sharpen(img, 1.5)
jsolex.vars.quality = 0.95
result = jsolex.vars.processed
Mode batch
En mode batch ImageMath, les valeurs de la section [outputs] sont collectées pour tous les fichiers et deviennent des listes dans la section batch :
[outputs]
# Calculé pour chaque fichier - devient une liste dans [[batch]]
sharpness = python("""
import jsolex
import numpy as np
img = jsolex.funcs.img(ps=0)
data = jsolex.toNumpy(img)
gy, gx = np.gradient(data.astype(np.float64))
result = float(np.var(np.sqrt(gx**2 + gy**2)))
""")
[[batch]]
[outputs]
# Exécuté une fois après tous les fichiers - sharpness est maintenant une liste
summary = python("""
import jsolex
sharpness_values = list(jsolex.vars.sharpness)
print(f"Meilleure netteté : {max(sharpness_values):.1f}")
print(f"Moyenne : {sum(sharpness_values)/len(sharpness_values):.1f}")
result = max(sharpness_values)
""")
APIs avancées
Au-delà du traitement d’image basique, le module jsolex fournit des fonctions spécialisées pour l’analyse spectrale et les systèmes de coordonnées solaires.
Accès aux données spectrales
| Fonction | Description |
|---|---|
|
Extrait le profil spectral aux coordonnées (x, y). Retourne un tableau 1D d’intensités. |
|
Lit une trame unique du fichier SER source. |
|
Retourne les coefficients polynomiaux |
|
Retourne |
|
Retourne |
|
Retourne |
Exemple :
import jsolex
img = jsolex.funcs.img(ps=0)
psr = jsolex.getPixelShiftRange()
print(f"Plage de décalage pixels : {psr['minShift']} à {psr['maxShift']}")
profile = jsolex.extractProfile(img, 512, 256)
if profile is not None:
min_idx = profile.argmin() if hasattr(profile, 'argmin') else profile.index(min(profile))
print(f"Centre de la raie au décalage pixel : {psr['minShift'] + min_idx}")
Conversion de coordonnées
| Fonction | Description |
|---|---|
|
Coordonnées héliographiques vers pixels. Retourne |
|
Pixels vers coordonnées héliographiques. Retourne |
|
Image vers coordonnées de trame SER. |
|
Trame SER vers coordonnées image. |
Exemple :
import jsolex
img = jsolex.funcs.img(ps=0)
# Convertir héliographique vers position image
coords = jsolex.heliographicToImage(img, lat=30.0, lon=45.0)
if coords['visible']:
print(f"Position image : ({coords['x']:.1f}, {coords['y']:.1f})")
# Reconvertir vers héliographique
helio = jsolex.imageToHeliographic(img, coords['x'], coords['y'])
if helio['onDisk']:
print(f"Héliographique : lat={helio['lat']:.1f}, lon={helio['lon']:.1f}")
print(f"mu={helio['mu']:.3f}") # 1.0 au centre, 0.0 au limbe
Paramètres solaires
| Fonction | Description |
|---|---|
|
Retourne |
|
Retourne |
Exemple :
import jsolex
img = jsolex.funcs.img(ps=0)
solar = jsolex.getSolarParameters()
if solar:
print(f"B0 = {solar['b0']:.2f} deg")
print(f"L0 = {solar['l0']:.2f} deg")
print(f"Rotation de Carrington : {solar['carringtonRotation']}")
ellipse = jsolex.getEllipseParams(img)
if ellipse:
print(f"Centre du disque : ({ellipse['centerX']:.1f}, {ellipse['centerY']:.1f})")
print(f"Rayon : {ellipse['radius']:.1f} pixels")
Exemples
Pipeline de traitement
[outputs]
processed = python("""
# Récupérer l'image de base
img = jsolex.funcs.img(0)
# Appliquer la chaîne de traitement
enhanced = jsolex.funcs.clahe(img, 8, 2.0, 1)
sharpened = jsolex.funcs.sharpen(enhanced, 3)
# Traitement conditionnel selon la taille de l'image
if img.width() > 2000:
result = jsolex.funcs.rescale_rel(sharpened, 0.5)
else:
result = sharpened
""")
Analyse de l’assombrissement centre-bord
import jsolex
import numpy as np
import matplotlib.pyplot as plt
from io import BytesIO
from PIL import Image
img = jsolex.funcs.img(ps=0)
data = jsolex.toNumpy(img)
# Échantillonner le long de l'équateur du centre vers le limbe est
mu_values = []
intensities = []
for lon in range(0, 90, 5):
coords = jsolex.heliographicToImage(img, lat=0.0, lon=float(lon))
if not coords['visible']:
break
helio = jsolex.imageToHeliographic(img, coords['x'], coords['y'])
if not helio['onDisk']:
break
x, y = int(coords['x']), int(coords['y'])
if 0 <= x < data.shape[1] and 0 <= y < data.shape[0]:
mu_values.append(helio['mu'])
intensities.append(data[y, x])
# Normaliser et tracer
intensities = np.array(intensities) / intensities[0]
plt.figure(figsize=(8, 6))
plt.plot(mu_values, intensities, 'o-')
plt.xlabel('mu (cosinus de l\'angle héliocentrique)')
plt.ylabel('Intensité normalisée')
plt.title('Assombrissement centre-bord')
plt.grid(True)
buf = BytesIO()
plt.savefig(buf, format='png', dpi=150)
buf.seek(0)
plot_img = np.array(Image.open(buf))[:, :, :3]
plt.close()
gray = plot_img.mean(axis=2).astype(np.float32) * 257.0
jsolex.emit(jsolex.fromNumpy(gray), "Assombrissement centre-bord")
Limitations
-
Pour les opérations simples, les fonctions ImageMath natives sont plus rapides que le code Python équivalent.
-
Tous les packages Python ne fonctionnent pas avec GraalPy. NumPy et PyArrow sont testés et supportés.