setiastrosuitepro 1.6.2__py3-none-any.whl → 1.6.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of setiastrosuitepro might be problematic. Click here for more details.
- setiastro/images/abeicon.svg +16 -0
- setiastro/images/acv_icon.png +0 -0
- setiastro/images/colorwheel.svg +97 -0
- setiastro/images/cosmic.svg +40 -0
- setiastro/images/cosmicsat.svg +24 -0
- setiastro/images/first_quarter.png +0 -0
- setiastro/images/full_moon.png +0 -0
- setiastro/images/graxpert.svg +19 -0
- setiastro/images/last_quarter.png +0 -0
- setiastro/images/linearfit.svg +32 -0
- setiastro/images/new_moon.png +0 -0
- setiastro/images/pixelmath.svg +42 -0
- setiastro/images/rotatearbitrary.png +0 -0
- setiastro/images/waning_crescent_1.png +0 -0
- setiastro/images/waning_crescent_2.png +0 -0
- setiastro/images/waning_crescent_3.png +0 -0
- setiastro/images/waning_crescent_4.png +0 -0
- setiastro/images/waning_crescent_5.png +0 -0
- setiastro/images/waning_gibbous_1.png +0 -0
- setiastro/images/waning_gibbous_2.png +0 -0
- setiastro/images/waning_gibbous_3.png +0 -0
- setiastro/images/waning_gibbous_4.png +0 -0
- setiastro/images/waning_gibbous_5.png +0 -0
- setiastro/images/waxing_crescent_1.png +0 -0
- setiastro/images/waxing_crescent_2.png +0 -0
- setiastro/images/waxing_crescent_3.png +0 -0
- setiastro/images/waxing_crescent_4.png +0 -0
- setiastro/images/waxing_crescent_5.png +0 -0
- setiastro/images/waxing_gibbous_1.png +0 -0
- setiastro/images/waxing_gibbous_2.png +0 -0
- setiastro/images/waxing_gibbous_3.png +0 -0
- setiastro/images/waxing_gibbous_4.png +0 -0
- setiastro/images/waxing_gibbous_5.png +0 -0
- setiastro/qml/ResourceMonitor.qml +84 -82
- setiastro/saspro/__main__.py +20 -1
- setiastro/saspro/_generated/build_info.py +2 -2
- setiastro/saspro/abe.py +37 -4
- setiastro/saspro/aberration_ai.py +237 -21
- setiastro/saspro/acv_exporter.py +379 -0
- setiastro/saspro/add_stars.py +33 -6
- setiastro/saspro/backgroundneutral.py +114 -37
- setiastro/saspro/blemish_blaster.py +4 -1
- setiastro/saspro/blink_comparator_pro.py +548 -275
- setiastro/saspro/clahe.py +4 -1
- setiastro/saspro/continuum_subtract.py +4 -1
- setiastro/saspro/convo.py +13 -7
- setiastro/saspro/cosmicclarity.py +129 -18
- setiastro/saspro/crop_dialog_pro.py +134 -8
- setiastro/saspro/curve_editor_pro.py +109 -42
- setiastro/saspro/doc_manager.py +246 -16
- setiastro/saspro/exoplanet_detector.py +120 -28
- setiastro/saspro/frequency_separation.py +1158 -204
- setiastro/saspro/function_bundle.py +16 -16
- setiastro/saspro/ghs_dialog_pro.py +81 -16
- setiastro/saspro/graxpert.py +1 -0
- setiastro/saspro/gui/main_window.py +519 -289
- setiastro/saspro/gui/mixins/dock_mixin.py +276 -42
- setiastro/saspro/gui/mixins/geometry_mixin.py +105 -5
- setiastro/saspro/gui/mixins/menu_mixin.py +28 -1
- setiastro/saspro/gui/mixins/theme_mixin.py +160 -14
- setiastro/saspro/gui/mixins/toolbar_mixin.py +416 -27
- setiastro/saspro/gui/mixins/update_mixin.py +138 -36
- setiastro/saspro/gui/mixins/view_mixin.py +42 -0
- setiastro/saspro/halobgon.py +4 -0
- setiastro/saspro/histogram.py +5 -1
- setiastro/saspro/image_combine.py +4 -0
- setiastro/saspro/image_peeker_pro.py +4 -0
- setiastro/saspro/imageops/starbasedwhitebalance.py +23 -52
- setiastro/saspro/imageops/stretch.py +582 -62
- setiastro/saspro/isophote.py +4 -0
- setiastro/saspro/layers.py +13 -9
- setiastro/saspro/layers_dock.py +183 -3
- setiastro/saspro/legacy/image_manager.py +154 -20
- setiastro/saspro/legacy/numba_utils.py +67 -47
- setiastro/saspro/legacy/xisf.py +240 -98
- setiastro/saspro/live_stacking.py +180 -79
- setiastro/saspro/luminancerecombine.py +228 -27
- setiastro/saspro/mask_creation.py +174 -15
- setiastro/saspro/mfdeconv.py +113 -35
- setiastro/saspro/mfdeconvcudnn.py +119 -70
- setiastro/saspro/mfdeconvsport.py +112 -35
- setiastro/saspro/morphology.py +4 -0
- setiastro/saspro/multiscale_decomp.py +748 -255
- setiastro/saspro/numba_utils.py +72 -57
- setiastro/saspro/ops/commands.py +18 -18
- setiastro/saspro/ops/script_editor.py +10 -2
- setiastro/saspro/ops/scripts.py +122 -0
- setiastro/saspro/perfect_palette_picker.py +37 -3
- setiastro/saspro/plate_solver.py +84 -49
- setiastro/saspro/psf_viewer.py +119 -37
- setiastro/saspro/remove_stars_preset.py +55 -13
- setiastro/saspro/resources.py +97 -11
- setiastro/saspro/rgbalign.py +4 -0
- setiastro/saspro/selective_color.py +83 -21
- setiastro/saspro/sfcc.py +364 -152
- setiastro/saspro/shortcuts.py +253 -49
- setiastro/saspro/signature_insert.py +692 -33
- setiastro/saspro/stacking_suite.py +1610 -574
- setiastro/saspro/star_alignment.py +522 -453
- setiastro/saspro/star_spikes.py +4 -0
- setiastro/saspro/star_stretch.py +38 -3
- setiastro/saspro/stat_stretch.py +743 -128
- setiastro/saspro/status_log_dock.py +1 -1
- setiastro/saspro/subwindow.py +786 -360
- setiastro/saspro/supernovaasteroidhunter.py +1 -1
- setiastro/saspro/swap_manager.py +77 -42
- setiastro/saspro/translations/all_source_strings.json +1588 -516
- setiastro/saspro/translations/ar_translations.py +915 -684
- setiastro/saspro/translations/de_translations.py +442 -463
- setiastro/saspro/translations/es_translations.py +277 -47
- setiastro/saspro/translations/fr_translations.py +279 -47
- setiastro/saspro/translations/hi_translations.py +253 -21
- setiastro/saspro/translations/integrate_translations.py +3 -2
- setiastro/saspro/translations/it_translations.py +1211 -161
- setiastro/saspro/translations/ja_translations.py +3340 -3107
- setiastro/saspro/translations/pt_translations.py +3315 -3337
- setiastro/saspro/translations/ru_translations.py +351 -117
- setiastro/saspro/translations/saspro_ar.qm +0 -0
- setiastro/saspro/translations/saspro_ar.ts +15902 -138
- setiastro/saspro/translations/saspro_de.qm +0 -0
- setiastro/saspro/translations/saspro_de.ts +14428 -133
- setiastro/saspro/translations/saspro_es.qm +0 -0
- setiastro/saspro/translations/saspro_es.ts +11503 -7821
- setiastro/saspro/translations/saspro_fr.qm +0 -0
- setiastro/saspro/translations/saspro_fr.ts +11168 -7812
- setiastro/saspro/translations/saspro_hi.qm +0 -0
- setiastro/saspro/translations/saspro_hi.ts +14733 -135
- setiastro/saspro/translations/saspro_it.qm +0 -0
- setiastro/saspro/translations/saspro_it.ts +14347 -7821
- setiastro/saspro/translations/saspro_ja.qm +0 -0
- setiastro/saspro/translations/saspro_ja.ts +14860 -137
- setiastro/saspro/translations/saspro_pt.qm +0 -0
- setiastro/saspro/translations/saspro_pt.ts +14904 -137
- setiastro/saspro/translations/saspro_ru.qm +0 -0
- setiastro/saspro/translations/saspro_ru.ts +11766 -168
- setiastro/saspro/translations/saspro_sw.qm +0 -0
- setiastro/saspro/translations/saspro_sw.ts +15115 -135
- setiastro/saspro/translations/saspro_uk.qm +0 -0
- setiastro/saspro/translations/saspro_uk.ts +11206 -6729
- setiastro/saspro/translations/saspro_zh.qm +0 -0
- setiastro/saspro/translations/saspro_zh.ts +10581 -7812
- setiastro/saspro/translations/sw_translations.py +282 -56
- setiastro/saspro/translations/uk_translations.py +264 -35
- setiastro/saspro/translations/zh_translations.py +282 -47
- setiastro/saspro/view_bundle.py +17 -17
- setiastro/saspro/wavescale_hdr.py +4 -1
- setiastro/saspro/wavescalede.py +4 -1
- setiastro/saspro/whitebalance.py +84 -12
- setiastro/saspro/widgets/common_utilities.py +28 -21
- setiastro/saspro/widgets/minigame/game.js +11 -6
- setiastro/saspro/widgets/resource_monitor.py +133 -57
- setiastro/saspro/widgets/spinboxes.py +28 -13
- setiastro/saspro/wimi.py +92 -721
- setiastro/saspro/wims.py +46 -36
- setiastro/saspro/window_shelf.py +2 -2
- setiastro/saspro/xisf.py +101 -11
- {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/METADATA +8 -7
- {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/RECORD +162 -128
- {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/WHEEL +0 -0
- {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/entry_points.txt +0 -0
- {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/licenses/LICENSE +0 -0
- {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/licenses/license.txt +0 -0
|
@@ -27,6 +27,7 @@ from astropy.coordinates import SkyCoord
|
|
|
27
27
|
import astropy.units as u
|
|
28
28
|
from astropy.wcs import WCS
|
|
29
29
|
from astropy.timeseries import LombScargle, BoxLeastSquares
|
|
30
|
+
import re
|
|
30
31
|
|
|
31
32
|
from astroquery.simbad import Simbad
|
|
32
33
|
from astroquery.vizier import Vizier
|
|
@@ -152,6 +153,41 @@ def _estimate_scale_arcsec_per_pix(h: fits.Header):
|
|
|
152
153
|
|
|
153
154
|
return None
|
|
154
155
|
|
|
156
|
+
_TZ_RE = re.compile(r'([+-])(\d{2})(\d{2})$') # -0700 -> -07:00
|
|
157
|
+
|
|
158
|
+
def _fix_iso_tz(s: str) -> str:
|
|
159
|
+
s = s.strip()
|
|
160
|
+
m = _TZ_RE.search(s)
|
|
161
|
+
if m:
|
|
162
|
+
s = s[:m.start()] + f"{m.group(1)}{m.group(2)}:{m.group(3)}"
|
|
163
|
+
return s
|
|
164
|
+
|
|
165
|
+
def _parse_obs_time_from_header(hdr) -> Time | None:
|
|
166
|
+
# hdr can be fits.Header or your dict-ish header
|
|
167
|
+
def _get(key):
|
|
168
|
+
try:
|
|
169
|
+
return hdr.get(key)
|
|
170
|
+
except Exception:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
# 1) Prefer UT-OBS if present (already “UTC-ish”)
|
|
174
|
+
for key in ("UT-OBS", "DATE-OBS", "DATE-END"):
|
|
175
|
+
v = _get(key)
|
|
176
|
+
if isinstance(v, str) and v.strip():
|
|
177
|
+
try:
|
|
178
|
+
return Time(_fix_iso_tz(v), format="isot", scale="utc")
|
|
179
|
+
except Exception:
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
# 2) MJD-OBS is super reliable
|
|
183
|
+
v = _get("MJD-OBS")
|
|
184
|
+
if v is not None:
|
|
185
|
+
try:
|
|
186
|
+
return Time(float(v), format="mjd", scale="utc")
|
|
187
|
+
except Exception:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
return None
|
|
155
191
|
|
|
156
192
|
def _estimate_fov_deg(img_shape, scale_arcsec):
|
|
157
193
|
"""Rough FOV (deg) from image size and scale (max of X/Y)."""
|
|
@@ -646,9 +682,12 @@ class ExoPlanetWindow(QDialog):
|
|
|
646
682
|
self.measure_btn.setVisible(is_raw)
|
|
647
683
|
|
|
648
684
|
def load_and_measure_subs(self):
|
|
685
|
+
before = len(getattr(self, "image_paths", []))
|
|
649
686
|
self.load_aligned_subs()
|
|
687
|
+
after = len(getattr(self, "image_paths", []))
|
|
688
|
+
if after == 0 or after == before and not self._cached_images:
|
|
689
|
+
return
|
|
650
690
|
self.detect_stars()
|
|
651
|
-
|
|
652
691
|
# --------------- I/O + Calibration ----------------
|
|
653
692
|
|
|
654
693
|
def load_raw_subs(self):
|
|
@@ -682,13 +721,38 @@ class ExoPlanetWindow(QDialog):
|
|
|
682
721
|
ds = hdr0.get('DATE-OBS')
|
|
683
722
|
except:
|
|
684
723
|
ds = None
|
|
724
|
+
|
|
725
|
+
# Use robust header time parsing (UT-OBS -> DATE-OBS -> MJD-OBS fallback)
|
|
685
726
|
t = None
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
727
|
+
try:
|
|
728
|
+
if ext == ".xisf":
|
|
729
|
+
# Build a tiny dict-like header for the helper
|
|
730
|
+
hdr_like = {}
|
|
731
|
+
try:
|
|
732
|
+
xisf = XISF(p)
|
|
733
|
+
img_meta = xisf.get_images_metadata()[0]
|
|
734
|
+
kw = img_meta.get("FITSKeywords", {}) or {}
|
|
735
|
+
# XISF FITSKeywords layout: key -> [ {value: ...}, ... ]
|
|
736
|
+
for k in ("UT-OBS", "DATE-OBS", "DATE-END", "MJD-OBS"):
|
|
737
|
+
if k in kw and kw[k]:
|
|
738
|
+
hdr_like[k] = kw[k][0].get("value")
|
|
739
|
+
except Exception:
|
|
740
|
+
hdr_like = {}
|
|
741
|
+
t = _parse_obs_time_from_header(hdr_like)
|
|
742
|
+
|
|
743
|
+
elif ext in (".fit", ".fits", ".fz"):
|
|
744
|
+
hdr0, _ = get_valid_header(p)
|
|
745
|
+
t = _parse_obs_time_from_header(hdr0)
|
|
746
|
+
|
|
747
|
+
else:
|
|
748
|
+
# TIFF etc. may not have FITS-like time headers; leave None
|
|
749
|
+
t = None
|
|
750
|
+
|
|
751
|
+
except Exception as e:
|
|
752
|
+
print(f"[DEBUG] Failed to parse obs time for {p}: {e}")
|
|
753
|
+
|
|
691
754
|
datelist.append((p, t))
|
|
755
|
+
|
|
692
756
|
self.progress_bar.setValue(i)
|
|
693
757
|
QApplication.processEvents()
|
|
694
758
|
|
|
@@ -768,24 +832,28 @@ class ExoPlanetWindow(QDialog):
|
|
|
768
832
|
self.progress_bar.setValue(i)
|
|
769
833
|
QApplication.processEvents()
|
|
770
834
|
|
|
771
|
-
|
|
772
|
-
for _, t in datelist
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
ma_strs = np.ma.MaskedArray(iso_strs, mask=mask_arr)
|
|
778
|
-
self.times = Time(ma_strs, format='isot', scale='utc', out_subfmt='date')
|
|
835
|
+
# Keep full timestamps (DO NOT truncate to date-only)
|
|
836
|
+
tlist = [t for _, t in datelist if t is not None]
|
|
837
|
+
if tlist:
|
|
838
|
+
self.times = Time(tlist) # already utc scale from helper
|
|
839
|
+
else:
|
|
840
|
+
self.times = None
|
|
779
841
|
|
|
780
842
|
self.progress_bar.setVisible(False)
|
|
781
843
|
loaded = sum(1 for im in self._cached_images if im is not None)
|
|
782
844
|
self.status_label.setText(f"Loaded {loaded}/{len(sorted_paths)} raw frames")
|
|
783
845
|
|
|
784
|
-
def load_aligned_subs(self):
|
|
846
|
+
def load_aligned_subs(self) -> bool:
|
|
785
847
|
settings = QSettings()
|
|
786
848
|
start_dir = settings.value("ExoPlanet/lastAlignedFolder", os.path.expanduser("~"), type=str)
|
|
787
|
-
paths, _ = QFileDialog.getOpenFileNames(
|
|
788
|
-
|
|
849
|
+
paths, _ = QFileDialog.getOpenFileNames(
|
|
850
|
+
self, "Select Aligned Frames", start_dir,
|
|
851
|
+
"FITS or TIFF (*.fit *.fits *.tif *.tiff *.xisf)"
|
|
852
|
+
)
|
|
853
|
+
if not paths:
|
|
854
|
+
self.status_label.setText("Load canceled.")
|
|
855
|
+
return False
|
|
856
|
+
|
|
789
857
|
settings.setValue("ExoPlanet/lastAlignedFolder", os.path.dirname(paths[0]))
|
|
790
858
|
|
|
791
859
|
self.status_label.setText("Reading metadata from aligned frames…")
|
|
@@ -809,10 +877,35 @@ class ExoPlanetWindow(QDialog):
|
|
|
809
877
|
hdr0, _ = get_valid_header(p)
|
|
810
878
|
ds = hdr0.get('DATE-OBS')
|
|
811
879
|
except: ds = None
|
|
880
|
+
# Use robust header time parsing (UT-OBS -> DATE-OBS -> MJD-OBS fallback)
|
|
812
881
|
t = None
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
882
|
+
try:
|
|
883
|
+
if ext == ".xisf":
|
|
884
|
+
# Build a tiny dict-like header for the helper
|
|
885
|
+
hdr_like = {}
|
|
886
|
+
try:
|
|
887
|
+
xisf = XISF(p)
|
|
888
|
+
img_meta = xisf.get_images_metadata()[0]
|
|
889
|
+
kw = img_meta.get("FITSKeywords", {}) or {}
|
|
890
|
+
# XISF FITSKeywords layout: key -> [ {value: ...}, ... ]
|
|
891
|
+
for k in ("UT-OBS", "DATE-OBS", "DATE-END", "MJD-OBS"):
|
|
892
|
+
if k in kw and kw[k]:
|
|
893
|
+
hdr_like[k] = kw[k][0].get("value")
|
|
894
|
+
except Exception:
|
|
895
|
+
hdr_like = {}
|
|
896
|
+
t = _parse_obs_time_from_header(hdr_like)
|
|
897
|
+
|
|
898
|
+
elif ext in (".fit", ".fits", ".fz"):
|
|
899
|
+
hdr0, _ = get_valid_header(p)
|
|
900
|
+
t = _parse_obs_time_from_header(hdr0)
|
|
901
|
+
|
|
902
|
+
else:
|
|
903
|
+
# TIFF etc. may not have FITS-like time headers; leave None
|
|
904
|
+
t = None
|
|
905
|
+
|
|
906
|
+
except Exception as e:
|
|
907
|
+
print(f"[DEBUG] Failed to parse obs time for {p}: {e}")
|
|
908
|
+
|
|
816
909
|
datelist.append((p, t))
|
|
817
910
|
self.progress_bar.setValue(i)
|
|
818
911
|
QApplication.processEvents()
|
|
@@ -889,18 +982,17 @@ class ExoPlanetWindow(QDialog):
|
|
|
889
982
|
self.progress_bar.setValue(i)
|
|
890
983
|
QApplication.processEvents()
|
|
891
984
|
|
|
892
|
-
|
|
893
|
-
for _, t in datelist
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
ma_strs = np.ma.MaskedArray(iso_strs, mask=mask_arr)
|
|
899
|
-
self.times = Time(ma_strs, format='isot', scale='utc', out_subfmt='date')
|
|
985
|
+
# Keep full timestamps (DO NOT truncate to date-only)
|
|
986
|
+
tlist = [t for _, t in datelist if t is not None]
|
|
987
|
+
if tlist:
|
|
988
|
+
self.times = Time(tlist) # already utc scale from helper
|
|
989
|
+
else:
|
|
990
|
+
self.times = None
|
|
900
991
|
|
|
901
992
|
self.progress_bar.setVisible(False)
|
|
902
993
|
loaded = sum(1 for im in self._cached_images if im is not None)
|
|
903
994
|
self.status_label.setText(f"Loaded {loaded}/{len(sorted_paths)} aligned frames")
|
|
995
|
+
return loaded > 0
|
|
904
996
|
|
|
905
997
|
def load_masters(self):
|
|
906
998
|
settings = QSettings()
|