-
Notifications
You must be signed in to change notification settings - Fork 13
/
Inti_ser_recon.py
2720 lines (2296 loc) · 114 KB
/
Inti_ser_recon.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 25 16:38:55 2020
Version 20 mai 2021
@author: valerie
Front end de traitements spectro helio de fichier ser
- interface pour selectionner un ou plusieurs fichiers
- appel au module inti_recon qui traite la sequence et genere les fichiers fits
-------------------------------------------------------------------------------
version 6.2
- tk error 6.1b
- histogram pour seuil non uniformity pic max * 0.5
- bug fix : ligne blanche dans non unif - mettre à 1 etait erreur car non norm
- creation routine pic_histo(frame) pour eliminer histo des valeurs de fond
Version en cours V6.0b > V6.0c>V6.0d > 6.1 a publier !
- ajout correction bad pixel sur ligne du polynome pour chaque trame > en commentaire
- message log datetime sur fichier SER si pb
- image mix
- ajout colorisation en rouge h-alpha, calcium et jaune
- selection couleur auto sur histogramme des intensités
- ajout param grille on/off dans yaml, a editer dans yaml - pas de GUI
- bouton Fr-En
6.0c
- abaisse seuil calcium histo de 80 à 70
- prend en compte valeur longeur d'onde de database pour "overrider" le mode auto (sécurité)
6.0d
- bug saturation overflow division flat dans recon
- max visu protu *0.6 au lieu de 0.5
- augemente la luminosité images couleurs et leur gamma
- accorde flip images png couleurs
- ajout dans recon des coordonnées y1,y2 et x1,x2 des bords du disque dans log et header
- modif couleur jaune > pale
- suppression sauvegarde fichier fits BASS2000 si le label wave est a Manual
6.1
- nom fichier color avec la couleur pour ne pas ecraser couleur continuum
- stonyhurst on/off dans les advanced settings
6.1.1
- fix selection Ha2cb
Version en cours Paris 5.8a>b>c>d> 6.0 publiée
- gestion seuil max sliders pour protus à 50 au lieu de 255
- bug fix sur imgdata apres sliders change pour garder l'image originale
- ajoute generation profil spectral depuis image _mean en .dat dans complements
- offset decalage doppler
- ajout egalisation luminosité des couleurs si doppler est decalé
- ajout bouton pour afficher le profil spectral
- remise de la barre de titre
- plus de barre de titre et grab_anywhere
- ajout d'un bouton pour traiter le dernier fichier du repertoire
- limite image autour du disque pour detection bords apres tilt
- TODO : seuils disks en calcium sont trop contrastés, prefere clahe
- TODO : bandes images helium
version 5.8 du 10 fev 2024 paris
- retour en arriere sur le clamp du profil pour la detection de edge
version 5.7 du 3 fevrier 2024 Antibes
- ajout lignes en haut et bas sur fort tilt plutot qu'une valeur unique dans la zone de padding
- ajout du fichier de config pour variable globale
- ajout variable LowDyn pour scan faible dynamique
- modif clamp zone brillante sur detection edge comme en faible dynamique
- modif ligne zero et derniere pour detection bord disque partiel sans etre en echec sur disque calcium avec diffusé
version 13 janvier 2024
- modif autocrop padding a droite
- test mode seuil inversé
- ajout image seuils inversés _inv
Version 5.6 paris 6 janvier 2024
- bug fix :ajout test os si pas windows pour detection taille ecran
- ajout d'un override avec param screen_scale dans inti.yaml
Version 5.5 paris 28 decembre
- ajout de 3 sous rep BASS2000, Clahe et Complements
- ajout de disk stonyhurst et gestion disk non entier
- calcul angle P, B0 en local
- gestion ecran 4k
- oriente grid si P=0 avec calcul en local
- acquisition 8bits
Version 5.3 paris 6 decembre
- test si deux edges droit et gauche sont trop proches dans le cas d'une protuberances
Version 5.2 paris 6 decembre
- fit polynomiale pour edge - soleil partiel
- refinement zone haute et basse pour image calcium
Version 5.1 paris 12 nov
- ajout mode auto ZEE_AUTOPOLY dans POl (magnetogramme)
- gestion background améiorée pour image a fort diffusé (calcium)
Version V4.1.8 paris 21 juillet 23 > V5.0
- meilleure gestion background pour padding
- ajout poly auto et decalage en mode free auto et manuel
- gestion mode degradé scan statique
- sauve _check de la trame
- decalage en decimal
version V4.1.7 antibes 15 juillet 2023
- gestion overflow doppler avec passage en float
- creer un mode sauve polynome
- stocke valeur de zeeman_shift
- menage fichier _dp2_raw, manual, jpg
- ajouter la diff r-b dans zeeman et faire r-b aussi dans mode free
- ajoute reduction bruit en mode general et free
Version V4.1.4 antibes du 14 juillet 2023
- mode frame redressée avec suppression du calcul raie
- ajout luminance moyenne
- accepte ang_tilt à zero et gere sur flag_force
- ajout calcul intensité sur zone centrale image
- sauve forcage tilt et ratio pour modes magn et free
- reactive shift_zeeman
version V4.1.2 paris du 7 juillet 2023
- ajout cas difficiles
- inversion doppler
- gestion serveur meudon ne repond pas
- ajout calcul ROI intensite pour mode free
- ROI devient Intensity et valeur en int
version V4.1.1 du 3 juillet 2023
- suppression decalage zeeman
- remplace _moy par _sum
- BUGFIX : close popup_get_file si pas de fichier choisi
- BUGFIX : sauvegarde b-1.png sauvait raie centrale dans zeeman mais fits ok
version V4.1.0 du 2 juillet 2023
- remplace circularisation limbes en mode forcé par la circu mode auto avec ajustement des coor cercle et cercle0
- ajout force tilt dans zeeman
- ajout filtre sur _mean.fits dans trame
version 4.0.9 paris 1 juillet 2023
- gestion autocrop dans ini.yaml
- ajout gestion trame dans zeeman
- remplace position par decalage dans free
Version 4.0.8 paris juin 2023
- angle tilt RA
- autocrop
version 4.0.7 11-17 juin - Paris
- prends en compte le facteur de rescaling pour orienter axe RA
- BUGFIX : calculette Ang/Pix
version 4.0.6 du 3 mai - Antibes
- ajout calculette pour disp par longueur d'onde
version 4.0.5 du 3 mai - Antibes
- ajout des labels et longueurs d'onde d'apres fichier Meudon
- test depassement pixel_shift
version du 22 mars 2023 - paris
- bug base_filename fi si dpx
- ajout creation fits3D avec checkbox dans sequence doppler
- typo N et E dans labels GUI
version du 12 mars 2023 - paris
- gestion des seuils avec sliders
- force fenetres zoom et sliders en premier
version du 21 fev 2023 - Paris V4.0.3bis
- oubli de mettre a jour en anglais la valeur par defaut des inversions
version du 18 fev 2023 - Paris
- sauvegarde des inversions dans my_dictini
- gere cas ou fichier ini n'a pas les mots clef inversion (evite plantage avec ancien fichier ini)
- bug fix erreur longueur d'onde CaH/HeID3
- ajustement taille ecran dynamique avec screen size
version du 3 fev 2023 - Paris
- ajout bouton pour avoir la date du fichier ser
- affiche date du fichier ser a la selection du fichier
version du 29 jan 2022 antibes V4.0.2
- ajout sauvegarde jpg avec facteur compression de 0.0038 des intensités et nom fichier fits database filename
- ajout de requete VO pour recuperer image jpg a la date d'observation pour affichage
- inversion coordonnées zoom et flip image
- bug fix sur hauteur image doppler
Version 26 dec 2022 Paris V4.0.1
- ajout rotation angle P manuel dans mode avancé
- ajout des mots clef fits demandé par JM Malherbe
FILENAME= 'solex_meudon _ha_20180620_122805.fits' /instrument, raie, date, heure (voir ci-dessous)
DATE_OBS= '2018-06-20T12:28:05.000' /date et heure TU de l’observation
INSTRUME= 'meudon' /instrument (à changer)
CONTACT = 'observateurs.solaires@obspm.fr' /adresse de contact
PHYSPARA= 'Intensity'
WAVELNTH= 6562.762 / en Angström, à changer selon raie (voir ci-dessous)
WAVEUNIT= -10
- inversion haut-bas des images png pour etre en conformité avec orientation image fits
- ajout de la connexion avec site kso pour obtention angle P a partir d'un champ dataobs
- inverse sens angle tilt correction avec flip
Version 17 sept 2022 Paris V3.3.6 > V4.0.0
- image trame mean en cv2 pour pointer une raie avec la souris en mode raie libre
- capture data entete observer, site long & lat, instrument
- transmission data_entete à la routine de traitement
Version 11 sept 2022 Paris V3.3.5
- sauvegarde poly_slit si pas POL ou WEAK flags
Version du 28 Aout 2022 V3.3.4
- gere la selection des onglets, suppression des checkbox
- ajoute des decimales dans raie libre
- avoir possiblité de fixer tilt et scaling dans raie libre
Version du 22 Aout V3.3.3
- revient en arriere sur sauvegarde du polynome calculé
- sauve des coeff de polynome pour raie libre
- raie libre position x bleue et rouge en absolu
Version du 21 Aout Paris V3.3.2
- conservation du dernier nom de fichier unique traité
- gestion disque saturé pour ne pas faire de flat
Version 14 aout 2022 Antibes V3.3.1
- ajout onglet decalage pour raie libre
- ajout lecture des coef du dernier polynome
- ajout calcul constante polynome pour raie libre
- calcul image free et diff
- positionne fenetre à 300,300
- boucle tant que pas cancel ou win_closed ou fichier ser vide
- position depart fenetre dans inti.yaml win_posx et win_posy
- 2 chiffres apres virgule pour constante polynome
Version du 12 mai 2022 - V3.3.0
- ajout fenetre de zoom avec curseur souris sur disk, protus, clahe
version du 27 avril 2022 - Paris
- correction bug multiple fichier test si pas de nom de fichier
version du 23 avril 2022 - Paris
- ajout onglet de calcul d'une sequence doppler
- ajout de generation film mp4
- ajout onglet de la fonction magnetogramme
- ajout de memoire de boucle sur fichier traité pour gérér sequence b et v
- creation d'une version anglaise par swith LG a la compil
- ajout de sauvegarde des coefficients de polynomes
- ajout4
version 18 sept 2021 - antibes
- reserre un peu seuils pour la visu des protuberances
version 16 sept 2021 - antibes
- back to circle display of black disk, not ellipse to really check deviation from circle
- adjust black disk size versus disk edge with disk_limit_percent variable
version 12 sept 2021 - antibes
- affichage disque noir et seuils protus sur suggestion de mattC
Version 8 sept 2021
- gestion erreur absence nom de fichier
- disque noir plus grand de 97% a 98 %
- ne sauve plus les fichiers fits intermediaires par defaut (_mean, _tilt et _flat)
Version 19 aout 2021
- suppression des flags dans la GUI pour simplification
- ajout '_' pour avoir fichier en tete dans explorer/finder
- ajout de _dp pour valeur de decalage différente de zéro dans noms de fichier pour eviter d'ecraser le precedent traitement
Version 16 juillet
- remplacement des methodes des limbes par fit_ellipse
- modification code avec code de Doug & Andrew Smith pour acceleration stupefiante
o vectorisation dans calcul extraction des intensités pour reconstruction du disque
o vectorisation dans le calcul de slant, qui est en fait un calcul de tilt
- fichier ini a la racine du repertoire ou est le script (etait en dur)
- ajout d'un flag pour afficher ou pas le disque noir dans image png ayant les seuils adequats pour les protus
To be noted... image fits data are the image pixels value, no change of dynamic, no thresholding. Only png images are thresholded.
Black disk is a python graphic overlay, not burned into images. Circle data are logged for ISIS processing.
"""
import numpy as np
import cv2
import os
import sys
#import Inti_recon as sol - test gestion multi decalage
import Inti_recon as sol
from astropy.io import fits
from Inti_functions import *
import yaml
# import shutil
import tkinter as tk
import math
import requests as rq
import webbrowser as web
import urllib.request
from datetime import datetime
import config as cfg
try :
from serfilesreader.serfilesreader import Serfile
except ImportError :
from serfilesreader import Serfile
import stonyhurst as sth
import PySimpleGUI as sg
try :
import ctypes
except:
pass
import matplotlib
import matplotlib.pyplot as plt
import time
SYMBOL_UP = '▲'
SYMBOL_DOWN = '▼'
short_version = 'Inti V6.2'
current_version = short_version + ' by V.Desnoux et.al. '
def Colorise_Image (couleur, frame_contrasted, basefich, suff):
# gestion couleur auto ou sur dropdown database compatibility
# 'Manual','Ha','Ha2cb','Cah','Cah1v','Cak','Cak1v','HeID3'
couleur_lbl=couleur
if couleur_lbl == 'Manual' :
couleur = 'on' # mode detection auto basé sur histogramme simple
else :
if couleur_lbl[:2] == 'Ha' :
couleur='H-alpha'
if couleur_lbl[:3] == 'Ha2' :
couleur='Pale'
if couleur_lbl[:2] == 'Ca' :
couleur='Calcium'
if couleur_lbl[:2] == 'He' :
couleur='Pale'
f=frame_contrasted/256
f_8=f.astype('uint8')
#hist = cv2.calcHist([f_8],[0],None,[256],[10,256])
# separe les 2 pics fond et soleil
th_otsu,img_binarized=cv2.threshold(f_8, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
hist = cv2.calcHist([f_8],[0],None,[256],[0,256])
hist[0:int(th_otsu)]=0
pos_max=np.argmax(hist)
"""
plt.plot(hist)
plt.show()
print('couleur : ',pos_max)
"""
# test ombres >> provoque des applats
ombres=False
if ombres :
i_low=[]
i_hi=[]
fr=np.copy(frame_contrasted)
i_low=np.array((fr<(pos_max*256))*fr*1.01, dtype='uint16')
i_hi=(fr>=pos_max)*fr
fr=i_low+i_hi
f=fr/256
f_8=f.astype('uint8')
if couleur =='on' :
if pos_max<200 and pos_max>=70 :
couleur="H-alpha"
if pos_max<70 :
couleur="Calcium"
if pos_max>=200 :
couleur="Pale"
# test ombres >> provoque des applats
ombres=False
if ombres :
f8_low=[]
f8_hi=[]
f8_low=np.array((f_8<pos_max)*f_8*1.05, dtype='uint8')
f8_hi=(f_8>=pos_max)*f_8
f_8=f8_low+f8_hi
#couleur="H-alpha"
if couleur != '' :
# image couleur en h-alpha
if couleur == 'H-alpha' :
# build a lookup table mapping the pixel values [0, 255] to
# their adjusted gamma values
gamma=0.3 # was gam 1.3 > 0.3 ok un peu plus clair et 0.1 plus sombre sombre
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f1_gam= cv2.LUT(f_8, table)
gamma=0.55 # was gam 0.5 - 0.3 trop rouge, 0.6 un peu jaune - 0.55 ok
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f2_gam= cv2.LUT(f_8, table)
gamma=1 # gam is 1.0
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f3_gam= cv2.LUT(f_8, table)
i1=(f1_gam*0.1).astype('uint8') # was 0.05 - 1 trop pale - 0.1 ok
i2=(f2_gam*1).astype('uint8') # is 1
i3=(f3_gam*1).astype('uint8') # is 1
gamma=1.5 # gam total image 2 est trop fade, 1.2 pas assez, 1.5 pas mal
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
i1= cv2.LUT(i1, table)
i2= cv2.LUT(i2, table)
i3= cv2.LUT(i3, table)
img_color=np.zeros([frame_contrasted.shape[0], frame_contrasted.shape[1], 3],dtype='uint8')
img_color[:,:,0] = np.array(i1, dtype='uint8') # blue
img_color[:,:,1] = np.array(i2, dtype='uint8') # blue
img_color[:,:,2] = np.array(i3, dtype='uint8') # blue
# gestion gain alpha et luminosité beta
#alpha=(255//2+10)/pos_max
#print('alpha ', alpha)
#img_color=cv2.convertScaleAbs(img_color, alpha=alpha, beta=0) # was 1.3 - 1.1 plus sombre - 1.2 ok
# affiche dans clahe window for test
#cv2.imshow('clahe',img_color)
#cv2.setWindowTitle("clahe", "color")
# image couleur en calcium
if couleur == 'Calcium' :
# build a lookup table mapping the pixel values [0, 255] to
# their adjusted gamma values
gamma=1.2 # was 1
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f1_gam= cv2.LUT(f_8, table)
gamma=1 # was 0.8
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f2_gam= cv2.LUT(f_8, table)
gamma=1 # was 0.8
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f3_gam= cv2.LUT(f_8, table)
# i1: bleu, i2: vert, i3:rouge
i1=(f1_gam*1).astype('uint8') # was 0.05 - 1 trop pale - 0.1 ok
i2=(f2_gam*0.7).astype('uint8') # is 1
i3=(f3_gam*0.7).astype('uint8') # was 0.8 un peu trop violet
gamma=1 # gam total image finalement aucun, 1.2 un peu fade
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
i1= cv2.LUT(i1, table)
i2= cv2.LUT(i2, table)
i3= cv2.LUT(i3, table)
img_color=np.zeros([frame_contrasted.shape[0], frame_contrasted.shape[1], 3],dtype='uint8')
img_color[:,:,0] = np.array(i1, dtype='uint8') # blue
img_color[:,:,1] = np.array(i2, dtype='uint8') # green
img_color[:,:,2] = np.array(i3, dtype='uint8') # red
vp=np.percentile(f_8, 99.7)
alpha=(255//2)/(vp*0.5)
#print('alpha ', alpha)
img_color=cv2.convertScaleAbs(img_color, alpha=alpha) # was 1.5 ok
# affiche dans clahe window for test
#cv2.imshow('clahe',img_color)
#cv2.setWindowTitle("clahe", "color")
# image couleur en jaune-orange (helium, sodium, continuum)
if couleur == 'Pale' :
# build a lookup table mapping the pixel values [0, 255] to
# their adjusted gamma values
gamma=1 #
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f1_gam= cv2.LUT(f_8, table)
gamma=1 # was 0.7
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f2_gam= cv2.LUT(f_8, table)
gamma=1 #
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
f3_gam= cv2.LUT(f_8, table)
# i1: bleu, i2: vert, i3:rouge
i1=(f1_gam*0.92).astype('uint8') # was 0.5
i2=(f2_gam*0.98).astype('uint8') # was 0.9
i3=(f3_gam*1).astype('uint8') # is 1
gamma=0.5 # gam total image 1 trop fade, 0.7 pas mal
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
i1= cv2.LUT(i1, table)
i2= cv2.LUT(i2, table)
i3= cv2.LUT(i3, table)
img_color=np.zeros([frame_contrasted.shape[0], frame_contrasted.shape[1], 3],dtype='uint8')
img_color[:,:,0] = np.array(i1, dtype='uint8') # blue
img_color[:,:,1] = np.array(i2, dtype='uint8') # green
img_color[:,:,2] = np.array(i3, dtype='uint8') # red
#alpha=(255//2+50)/pos_max
#alpha=1
#print('alpha ', alpha)
#img_color=cv2.convertScaleAbs(img_color, alpha=alpha) # was 1
# affiche dans clahe window for test
#cv2.imshow('clahe',img_color)
#cv2.setWindowTitle("clahe", "color")
#img_color=cv2.flip(img_color,0)
#cv2.imshow('clahe',img_color)
#cv2.setWindowTitle("clahe", "color")
cv2.imwrite(basefich+suff+'_color_'+str(couleur)+'.png',img_color)
if cfg.LG == 1:
logme("Couleur : "+ str(couleur))
else:
logme("Color : "+ str(couleur))
return img_color
def seuil_image (img):
Seuil_haut=np.percentile(img,99.999)
Seuil_bas=(Seuil_haut*0.25)
img[img>Seuil_haut]=Seuil_haut
img_seuil=(img-Seuil_bas)* (65535/(Seuil_haut-Seuil_bas)) # was 65500
img_seuil[img_seuil<0]=0
return img_seuil, Seuil_haut, Seuil_bas
def seuil_image_force (img, Seuil_haut, Seuil_bas):
img[img>Seuil_haut]=Seuil_haut
img_seuil=(img-Seuil_bas)* (65535/(Seuil_haut-Seuil_bas)) # was 65500
img_seuil[img_seuil<0]=0
return img_seuil
def get_lum_moyenne(img) :
# ajout calcul intensité moyenne sur ROI centrée
ih, iw =img.shape
dim_roi = 100
rox1 = iw//2 - dim_roi
rox2 = iw//2 + dim_roi
roy1 = ih//2 - dim_roi
roy2 = ih//2 + dim_roi
#print('roi ', rox1,rox2,roy1,roy2)
try :
lum_roi=np.mean(img[roy1:roy2,rox1:rox2])
except:
lum_roi=0
return lum_roi
def on_change_slider(x):
# x est la valeur du curseur
global source_window
global img_data
#print(params[0])
sb = cv2.getTrackbarPos('Seuil bas', 'sliders')
sh = cv2.getTrackbarPos('Seuil haut', 'sliders')
if sh>255:
sh=255
s_bas=int(sb*65535/255)
s_haut=int(sh*65535/255)
#print('non inv : ',s_haut, s_bas)
diff=s_haut-s_bas
if diff==0:
diff=65535
f1=np.copy(img_data)
if diff<0 :
f1=np.copy(img_data)
f1=65535-f1
s_bas=65535-s_bas
s_haut=65535-s_haut
f1=np.copy(img_data)
f1[f1>s_haut]=s_haut
f1[f1<s_bas]=s_bas
f=(f1-s_bas)* (65535/abs(diff))
f[f<0]=0
cc=np.array(f, dtype='uint16')
#param=np.copy(cc)
param2=np.copy(img_data)
paramh=s_haut
paramb=s_bas
cv2.setMouseCallback(source_window,mouse_event_callback, [source_window, cc,param2,paramh,paramb])
cc=cv2.flip(cc,0)
cv2.imshow(source_window,cc)
def mouse_event_callback( event,x,y,flags,params):
global source_window
global img_data
try :
if event==cv2.EVENT_LBUTTONDOWN or event==cv2.EVENT_LBUTTONUP:
source_window=params[0]
img_data=np.copy(params[2])
#print('mouse: ',params[0])
sh=int(params[3]/65535*255)
sb=int(params[4]/65635*255)
cv2.setTrackbarPos('Seuil bas','sliders',sb)
cv2.setTrackbarPos('Seuil haut','sliders',sh)
if source_window == 'protus' :
cv2.setTrackbarMax('Seuil haut', 'sliders', 100) #was 50
cv2.setTrackbarMax('Seuil bas', 'sliders', 100) #was 50
else :
cv2.setTrackbarMax('Seuil haut', 'sliders', 255)
cv2.setTrackbarMax('Seuil bas', 'sliders', 255)
cv2.setWindowProperty('sliders',cv2.WND_PROP_TOPMOST,1)
cv2.setWindowProperty('Zoom',cv2.WND_PROP_TOPMOST,1)
if event == cv2.EVENT_MOUSEMOVE:
try :
img=np.copy(params[1])
y=img.shape[0]-y
img=img[y-150:y+150,x-150:x+150]
img=cv2.flip(img,0)
cv2.imshow('Zoom', img)
except:
pass
except:
print('pb sliders')
pass
def mouse_event2_callback( event,x,y,flags,param):
global mouse_x, mouse_y
if event==cv2.EVENT_LBUTTONDOWN:
try:
font = cv2.FONT_HERSHEY_PLAIN
font_scale=1
font_thickness=1
mouse_x, mouse_y=x,y
text_size, _ = cv2.getTextSize(str(x)+';'+str(y)+' '+str(param[y,x]), font, font_scale, font_thickness)
text_w, text_h = text_size
cv2.rectangle(param, (10,30), (text_w+10,text_h), 0, cv2.FILLED)
cv2.putText(param, str(x)+';'+str(y)+' '+str(param[y,x]), (10, 30), font, font_scale, 65000, font_thickness, cv2.LINE_AA)
cv2.imshow('mean', param)
except:
pass
def get_sun_meudon (date_jd1):
# obsolete
date_jd2=date_jd1+1
r1="http://voparis-tap-helio.obspm.fr/__system__/tap/run/sync?LANG=ADQL&format=txt&"
r2="request=doQuery&query=select%20access_url%20from%20bass2000.epn_core%20where%20time_min%20between%20"
r3=str(date_jd1)+"%20and%20"+str(date_jd2)+"%20and%20access_format=%27image/jpeg%27%20"
r4="and%20filter=%27H%20Alpha%27"
Vo_req=r1+r2+r3+r4
reponse_web=rq.get(Vo_req)
sun_meudon=reponse_web.text.split("\n")[0]
return sun_meudon
def display_mean_img2 ():
# Lecture et affiche image disque brut
ImgFile = sg.popup_get_file("Select file", file_types=(('Mean Files', '*mean.fits'), ('ALL Files', '*.*'),))
if ImgFile != None :
try :
hdulist = fits.open(ImgFile, memmap=False)
hdu=hdulist[0]
myspectrum=hdu.data
mih=hdu.header['NAXIS2']
miw=hdu.header['NAXIS1']
mean_trame=np.reshape(myspectrum, (mih,miw))
#print(mih, miw)
hdulist.close()
if miw<178:
# window title bar CV2 force image minimal size at 178, so pad to avoid autorescale
mean_trame_pad=np.array(np.zeros((mih, 178)), dtype="uint16")
mean_trame_pad[:mih, :miw]=mean_trame
else:
mean_trame_pad=np.array(mean_trame,dtype='uint16')
#fenetre pour image mean de trame
sc=0.8
cv2.namedWindow('mean', cv2.WINDOW_NORMAL)
cv2.moveWindow('mean', 100, 0)
cv2.resizeWindow('mean', (int(miw*sc), int(mih*sc)))
cv2.imshow('mean',mean_trame_pad)
cv2.setMouseCallback('mean',mouse_event2_callback, mean_trame_pad)
cv2.waitKey(0)
cv2.destroyAllWindows()
except :
pass
def display_mean_img (poly):
# version image redressee
# Lecture et affiche image disque brut
ImgFile = sg.popup_get_file("Select file", file_types=(('Mean Files', '*mean.fits'), ('ALL Files', '*.*'),))
if ImgFile != None :
try :
hdulist = fits.open(ImgFile, memmap=False)
hdu=hdulist[0]
myspectrum=hdu.data
mih=hdu.header['NAXIS2']
miw=hdu.header['NAXIS1']
mean_trame=np.reshape(myspectrum, (mih,miw))
hdulist.close()
# redresse raies pour faciliter la prise de position de la raie
try :
image_mean_redresse = translate_img(mean_trame, poly)
except :
image_mean_redresse = np.copy(mean_trame)
if miw<178:
# window title bar CV2 force image minimal size at 178, so pad to avoid autorescale
mean_trame_pad=np.array(np.zeros((mih, 178)), dtype="uint16")
mean_trame_pad[:mih, :miw]=image_mean_redresse
#mean2_trame_pad=np.array(np.zeros((mih, 178)), dtype="uint16")
#mean2_trame_pad[:mih, :miw]=np.copy(mean_trame)
else:
mean_trame_pad=np.array(mean_trame,dtype='uint16')
#mean2_trame_pad=np.array(mean_trame,dtype='uint16')
#sauvegarde du fits en _check
WorkDir=os.path.dirname(ImgFile)+"/"
base=os.path.basename(ImgFile)
basefich=os.path.splitext(base)[0].split('_mean')[0]
DiskHDU=fits.PrimaryHDU(mean_trame_pad,hdu.header)
DiskHDU.writeto(WorkDir+basefich+'_check.fits', overwrite='True')
print(WorkDir+basefich+'_check.fits')
#fenetre pour image mean de trame
sc=1
cv2.namedWindow('mean')
cv2.moveWindow('mean', 100, 0)
cv2.resizeWindow('mean', (int(miw*sc), int(mih*sc)))
cv2.imshow('mean',mean_trame_pad)
cv2.setMouseCallback('mean',mouse_event2_callback, mean_trame_pad)
cv2.waitKey(0)
cv2.destroyAllWindows()
except :
pass
def UI_calculette(size_pix_cam, bin_cam):
sg.theme('Dark2')
sg.theme_button_color(('white', '#500000'))
resultat=0
disp=0
wav_name=''
wav_dict={'Ha':6562.762,'Ca':3968.469,'He':5877.3}
if cfg.LG==1 : # en français
layout=[
[sg.Radio('Ha', 'wav',key="-HA-", default=True), sg.Radio('Ca', 'wav',key='-CA-'), sg.Radio('He', 'wav', key='-HE-')],
[sg.Text("Valeur en angströms : ", size=(20,1)), sg.Input(default_text='1', size=(7,1), key='-ang-', background_color='light yellow')],
[sg.Text("Taille pixel caméra en mm : ", size=(20,1)), sg.Input(default_text=str(size_pix_cam), size=(7,1), key='-size-')],
[sg.Text("Facteur de Binning : ", size=(20,1)), sg.Input(default_text=str(bin_cam), size=(7,1), key='-bin-')],
[sg.Text(str(resultat)+ " en pixels", size=(28,1), key='-RESULT-', background_color='dark green')],
[sg.Text('Dispersion en Ang/Pix : '),sg.Text(str(disp), key='-DISP-')],
[sg.Button("Calcul ", key='-VALID-'),sg.Text(' '),sg.Button('Fermer', key='-Exit-')]
]
else: # en anglais
layout=[
[sg.Radio('Ha', 'wav',key="-HA-", default=True), sg.Radio('Ca', 'wav',key='-CA-'), sg.Radio('He', 'wav', key='-HE-')],
[sg.Text("Value in angströms : ", size=(20,1)), sg.Input(default_text='1', size=(8,1),key='-ang-',background_color='light yellow')],
[sg.Text("Camera pixel size in mm : ", size=(20,1)), sg.Input(default_text=str(size_pix_cam), size=(8,1), key='-size-')],
[sg.Text("Binning factor : ", size=(20,1)), sg.Input(default_text=str(bin_cam), size=(8,1),key='-bin-')],
[sg.Text(str(resultat) + " in pixels", size=(28,1), key='-RESULT-', background_color='dark green')],
[sg.Text('Dispersion in Ang/Pix : '),sg.Text(str(disp),key='-DISP-')],
[sg.Button("Compute ", key='-VALID-'),sg.Text(' '),sg.Button('Exit', key='-Exit-')]
]
a,b=win_pos
win2_pos=(a+250, b+150)
window2 = sg.Window('Sol\'Ex calculette', layout, location=win2_pos,finalize=True)
window2.BringToFront()
while True:
event, values = window2.read()
#print(event, values)
if event == sg.WIN_CLOSED or event == '-Exit-':
break
if event == '-VALID-' :
if values['-HA-'] == True :
wav_name = 'Ha'
if values['-CA-'] == True:
wav_name = 'Ca'
if values['-HE-'] == True:
wav_name = 'He'
wave=wav_dict[wav_name]*1e-7
alpha=np.degrees(np.arcsin((2400*wave)/(2*np.cos(np.radians(17)))))+17
beta=alpha-34
size_pix_cam=float(values['-size-'])
bin_cam=float(values['-bin-'])
val_toconvert=float(values['-ang-'])
disp = 1e7 * size_pix_cam* np.cos(np.radians(beta)) / 2400 / 125
val_ang_onepix= disp * bin_cam
#print(val_ang_onepix)
resultat=round(val_toconvert / val_ang_onepix)
window2['-RESULT-'].update(str(resultat)+' pixels')
window2['-DISP-'].update("{:.3f}".format(disp))
window2.close()
return resultat, size_pix_cam, bin_cam
def collapse(layout, key):
"""
Helper function that creates a Column that can be later made hidden, thus appearing "collapsed"
:param layout: The layout for the section
:param key: Key used to make this seciton visible / invisible
:return: A pinned column that can be placed directly into your layout
:rtype: sg.pin
"""
return sg.pin(sg.Column(layout, key=key))
def UI_graph():
if sys.platform=="win32" :
sg.set_options(dpi_awareness=True, scaling=screen_scale)
else:
sg.set_options(scaling=screen_scale)
if cfg.LG == 1 :
color_list=['Jaune', 'Noir']
c=color_list[0]
g=True
layout=[
[sg.Text('')],
[sg.Text('Couleur grille : '), sg.Combo(color_list,default_value=color_list[0], key='-GRID_COLOR-', enable_events=True)],
[sg.Text('')],
[sg.Checkbox('Graduations On', default=True,key='-GRADU_ON-',enable_events=True)],
[sg.Text('')],
[sg.Button('Ok',size=(20,1))]
]
Title='Grille'
else :
color_list=['yellow', 'Black']
c=color_list[0]
g=True
layout=[
[sg.Text('')],
[sg.Text('Grid Color : '), sg.Combo(color_list,default_value=color_list[0], key='-GRID_COLOR-', enable_events=True)],
[sg.Text('')],
[sg.Checkbox('Graduations On', default=True,key='-GRADU_ON-',enable_events=True)],
[sg.Text('')],
[sg.Button('Ok', size=(20,1))]
]
Title='Grid'
a,b=win_pos
win3_pos=(a+400, b+300)
window3 = sg.Window(Title, layout, location=win3_pos,finalize=True)
while True:
event, values = window3.read()
if event==sg.WIN_CLOSED or event=='Ok':
break
else :
g=values['-GRADU_ON-']
c=values['-GRID_COLOR-']
window3.close()
return c, g
#-------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------
# Interface INTI
#-------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------
def UI_SerBrowse (WorkDir,saved_tilt, saved_ratio, dec_pix_dop, dec_pix_cont, poly, pos_free_blue,
pos_free_red,free_shift, zee_shift, win_pos, previous_serfile, data_entete,saved_angP,Flags, size_pix_cam, bin_cam, screen_scale):
if sys.platform=="win32" :
sg.set_options(dpi_awareness=True, scaling=screen_scale)
else:
sg.set_options(scaling=screen_scale)
#sg.set_options(font="Arial, 10")
sg.theme('Dark2')
sg.theme_button_color(('white', '#500000'))
#print('ui :', os.path.join(WorkDir,previous_serfile))
Shift=[]
#Flags={}
Flags["DOPCONT"]=False
Flags["VOL"]=False
Flags["POL"]=False
Flags["WEAK"]=False
Racines=[]
list_wave=[['Manual','Ha','Ha2cb','Cah','Cah1v','Cak','Cak1v','HeID3'],[0,6562.762,6561.432,3968.469,3966.968,3933.663,3932.163,5877.3]]
if cfg.LG == 1 :
LG_str='FR'
else :
LG_str='EN'
if cfg.LG == 1 :
colonne0=[
[sg.Checkbox(' Inversion E-W', default=Flags['FLIPRA'], key='-RA_FLIP-')],
[sg.Checkbox(' Inversion N-S', default=Flags['FLIPNS'], key='-NS_FLIP-')]
]
colonne1=[[sg.Button('Grille', key='Graph')]]
else :
colonne0=[
[sg.Checkbox(' E-W flip', default=Flags['FLIPRA'], key='-RA_FLIP-')],
[sg.Checkbox(' N-S flip', default=Flags['FLIPNS'], key='-NS_FLIP-')]
]
colonne1=[[sg.Button('Grid', key='Graph')]]
if cfg.LG == 1:
section1 = [
[sg.Checkbox(' Affichage de la reconstruction en temps réel ', default=False, key='-DISP-')],
#[sg.Checkbox(' Non sauvegarde des fichiers FITS intermédiaires', default=True, key='-SFIT-')],
[sg.Checkbox('Réduction de bruit (modes general, magnétogramme, libre)', default=Flags['NOISEREDUC'], key='-NOISEREDUC-')],
[sg.Checkbox(' Sauve paramètres polynome pour magnétogramme et libre ', default=Flags['SAVEPOLY'], key='-SAVEPOLY-')],
[sg.Checkbox(' Autocrop', default=Flags['Autocrop'], key='-AUTOCROP-')],
[sg.Checkbox(' Stonyhurst', default=Flags['Grid'], key='-GRID-', enable_events=True)],
[sg.Checkbox(' Force les valeurs tilt et facteur d\'échelle', default=False, key='-F_ANG_SXSY-')],
[sg.Text('Angle Tilt en degrés :', size=(15,1)), sg.Input(default_text=saved_tilt, size=(6,1),key='-TILT-')],
[sg.Text('Ratio SY/SX :', size=(15,1)), sg.Input(default_text=saved_ratio, size=(6,1),key='-RATIO-')]
]
else:
section1 = [
[sg.Checkbox(' Real time reconstruction display ', default=False, key='-DISP-')],
#[sg.Checkbox(' No intermediate files FITS saving', default=True, key='-SFIT-')],
[sg.Checkbox('Noise reduction (general and free modes)', default=Flags['NOISEREDUC'], key='-NOISEREDUC-')],
[sg.Checkbox(' Save polynome parameters for magnetogram and free ', default=Flags['SAVEPOLY'], key='-SAVEPOLY-')],
[sg.Checkbox(' Autocrop', default=Flags['Autocrop'], key='-AUTOCROP-')],
[sg.Checkbox(' Stonyhurst', default=Flags['Grid'], key='-GRID-', enable_events=True)],
[sg.Checkbox(' Force values of tilt and scale ratio', default=False, key='-F_ANG_SXSY-')],
[sg.Text('Tilt angle in degrees :', size=(15,1)), sg.Input(default_text=saved_tilt, size=(6,1),key='-TILT-')],
[sg.Text('SY/SX ratio :', size=(15,1)), sg.Input(default_text=saved_ratio, size=(6,1),key='-RATIO-')]
]
if cfg.LG == 1:
section2 = [
[sg.Text('Observateur :', size=(12,1)), sg.Input(default_text=data_entete[0], size=(25,1),key='-OBSERVER-')],
[sg.Text('Contact :', size=(12,1)), sg.Input(default_text=data_entete[4], size=(25,1),key='-CONTACT-')],
[sg.Text('Site Long :', size=(12,1)), sg.Input(default_text=data_entete[2], size=(6,1),key='-SITE_LONG-'),sg.Text('E positif'),
sg.Text(' Site Lat :', size=(12,1)), sg.Input(default_text=data_entete[3], size=(6,1),key='-SITE_LAT-'), sg.Text('N positif'),
sg.Text(' in decimal degree')],
[sg.Text('Instrument :', size=(12,1)), sg.Input(default_text=data_entete[1], size=(35,1),key='-INSTRU-')],
[sg.Text('Longueur d\'onde :', size=(12,1)), sg.Combo(list_wave[0], default_value=list_wave[0][0], size=(10,1),key='-WAVE-',enable_events=True),