pyredshift 1.12__tar.gz → 1.14__tar.gz
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.
- {pyredshift-1.12 → pyredshift-1.14}/PKG-INFO +1 -1
- {pyredshift-1.12 → pyredshift-1.14}/pyredshift +8 -3
- {pyredshift-1.12 → pyredshift-1.14}/setup.py +1 -1
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift/pyredshift-help.html +10 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift/redshift.py +46 -6
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift.egg-info/PKG-INFO +1 -1
- {pyredshift-1.12 → pyredshift-1.14}/LICENSE +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/README.md +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/pyproject.toml +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/setup.cfg +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift/__init__.py +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift/pyredshift.lines +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift.egg-info/SOURCES.txt +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift.egg-info/dependency_links.txt +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift.egg-info/requires.txt +0 -0
- {pyredshift-1.12 → pyredshift-1.14}/src/pyredshift.egg-info/top_level.txt +0 -0
|
@@ -75,10 +75,15 @@ def read_csv(fname):
|
|
|
75
75
|
continue
|
|
76
76
|
parts = line.split(",")
|
|
77
77
|
try:
|
|
78
|
-
|
|
79
|
-
spec.append(float(parts[1]))
|
|
78
|
+
x = float(parts[0])
|
|
80
79
|
except (IndexError, ValueError):
|
|
81
|
-
continue
|
|
80
|
+
continue # no wavelength - not a data row
|
|
81
|
+
try:
|
|
82
|
+
y = float(parts[1])
|
|
83
|
+
except (IndexError, ValueError):
|
|
84
|
+
y = np.nan # blank/bad flux cell -> bad pixel, plots as a gap
|
|
85
|
+
wav.append(x)
|
|
86
|
+
spec.append(y)
|
|
82
87
|
return np.array(wav), np.array(spec), True
|
|
83
88
|
|
|
84
89
|
|
|
@@ -13,7 +13,7 @@ from setuptools import setup
|
|
|
13
13
|
|
|
14
14
|
setup(
|
|
15
15
|
name="pyredshift",
|
|
16
|
-
version="1.
|
|
16
|
+
version="1.14",
|
|
17
17
|
description="Interactive redshifting of 1D astronomical spectra "
|
|
18
18
|
"(Python successor of pdlredshift / redshift.f)",
|
|
19
19
|
long_description=open("README.md").read(),
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
<h1>pyredshift help <span class="ver">v{version}</span></h1>
|
|
2
2
|
|
|
3
|
+
<p class="lineage">Karl's interactive redshift program. Thirty-four years
|
|
4
|
+
of redshifts by eye, now in its third language: <code>redshift.f</code>
|
|
5
|
+
(FIGARO/Fortran, Durham 1992) → <code>pdlredshift</code>
|
|
6
|
+
(Perl/PDL/PGPLOT 2018) → <code>pyredshift</code> (Python/matplotlib,
|
|
7
|
+
ported with Claude, 2026) — same keys, same beautiful crosshair,
|
|
8
|
+
faster carriage.</p>
|
|
9
|
+
|
|
10
|
+
<p class="lineage">Karl Glazebrook, Swinburne University of Technology.
|
|
11
|
+
MIT license.</p>
|
|
12
|
+
|
|
3
13
|
<input type="radio" name="tabs" id="tab-keys" checked>
|
|
4
14
|
<input type="radio" name="tabs" id="tab-lines">
|
|
5
15
|
<input type="radio" name="tabs" id="tab-guide">
|
|
@@ -53,6 +53,19 @@ V1.11 - Proper file-format documentation: a per-format table in the
|
|
|
53
53
|
script's -h and a File formats section in the help page, both
|
|
54
54
|
generated from FORMAT_HELP here so they cannot drift apart.
|
|
55
55
|
V1.12 - The version number is shown by -h/-help and on the help page.
|
|
56
|
+
V1.13 - CSV reader: blank flux cells are bad pixels (NaN, plotted as
|
|
57
|
+
gaps) instead of desynchronising the wavelength and flux arrays;
|
|
58
|
+
rows with no wavelength are skipped.
|
|
59
|
+
V1.14 - Saving works properly: the toolbar save button no longer
|
|
60
|
+
truncates the output (the crosshair/readout blit machinery ran
|
|
61
|
+
during savefig and corrupted the file render), and the crosshair
|
|
62
|
+
and readout are no longer printed into saved PNGs/PDFs (savefig
|
|
63
|
+
draws animated artists - they now stay invisible outside blit
|
|
64
|
+
passes; the crosshair had been in 'p' output since V1.0).
|
|
65
|
+
- The backend chooser actually imports each backend before
|
|
66
|
+
choosing it, so a python without Qt falls back to MacOSX
|
|
67
|
+
instead of crashing at the first figure.
|
|
68
|
+
- Lineage/credits at the top of the help page.
|
|
56
69
|
"""
|
|
57
70
|
|
|
58
71
|
import ctypes
|
|
@@ -66,10 +79,16 @@ from html.parser import HTMLParser
|
|
|
66
79
|
import numpy as np
|
|
67
80
|
import matplotlib
|
|
68
81
|
|
|
69
|
-
# Pick a GUI backend unless the user forced one via MPLBACKEND
|
|
82
|
+
# Pick a GUI backend unless the user forced one via MPLBACKEND.
|
|
83
|
+
# matplotlib.use() validates lazily (a missing Qt only explodes later at
|
|
84
|
+
# figure creation), so import the backend module to prove it really works.
|
|
70
85
|
if "MPLBACKEND" not in os.environ:
|
|
71
|
-
|
|
86
|
+
import importlib
|
|
87
|
+
for _backend, _mod in (("QtAgg", "backend_qtagg"),
|
|
88
|
+
("MacOSX", "backend_macosx"),
|
|
89
|
+
("TkAgg", "backend_tkagg")):
|
|
72
90
|
try:
|
|
91
|
+
importlib.import_module("matplotlib.backends." + _mod)
|
|
73
92
|
matplotlib.use(_backend)
|
|
74
93
|
break
|
|
75
94
|
except ImportError:
|
|
@@ -92,7 +111,7 @@ try:
|
|
|
92
111
|
except AttributeError:
|
|
93
112
|
pass
|
|
94
113
|
|
|
95
|
-
__version__ = "1.
|
|
114
|
+
__version__ = "1.14"
|
|
96
115
|
|
|
97
116
|
C_LIGHT = 2.99792458e8 # m/s
|
|
98
117
|
|
|
@@ -381,27 +400,38 @@ class StickyCursor(Cursor):
|
|
|
381
400
|
self.linev.set_data((xdata, xdata),
|
|
382
401
|
((figbb.y0 - axbb.y0) / axbb.height,
|
|
383
402
|
(figbb.y1 - axbb.y0) / axbb.height))
|
|
384
|
-
self.linev.set_visible(self.visible and self.vertOn)
|
|
385
403
|
self.lineh.set_data(((figbb.x0 - axbb.x0) / axbb.width,
|
|
386
404
|
(figbb.x1 - axbb.x0) / axbb.width),
|
|
387
405
|
(ydata, ydata))
|
|
388
|
-
self.lineh.set_visible(self.visible and self.horizOn)
|
|
389
406
|
if not (self.visible and (self.vertOn or self.horizOn)):
|
|
390
407
|
return
|
|
391
|
-
# Redraw
|
|
408
|
+
# Redraw. Animated artists still land in savefig output (bitten:
|
|
409
|
+
# crosshair printed into PDFs/PNGs), so they stay invisible except
|
|
410
|
+
# inside this blit pass - a save sees them switched off.
|
|
392
411
|
if self.useblit:
|
|
393
412
|
if self.background is not None:
|
|
394
413
|
self.canvas.restore_region(self.background)
|
|
414
|
+
self.linev.set_visible(self.vertOn)
|
|
415
|
+
self.lineh.set_visible(self.horizOn)
|
|
395
416
|
self.ax.draw_artist(self.linev)
|
|
396
417
|
self.ax.draw_artist(self.lineh)
|
|
418
|
+
self.linev.set_visible(False)
|
|
419
|
+
self.lineh.set_visible(False)
|
|
397
420
|
if readout_artist is not None:
|
|
398
421
|
set_readout_text(event) # restore wiped the corner -
|
|
422
|
+
readout_artist.set_visible(True)
|
|
399
423
|
fig.draw_artist(readout_artist) # redraw with fresh values
|
|
424
|
+
readout_artist.set_visible(False)
|
|
400
425
|
self.canvas.blit(figbb)
|
|
401
426
|
else:
|
|
427
|
+
self.linev.set_visible(self.visible and self.vertOn)
|
|
428
|
+
self.lineh.set_visible(self.visible and self.horizOn)
|
|
402
429
|
self.canvas.draw_idle()
|
|
403
430
|
|
|
404
431
|
def _redraw(self, event):
|
|
432
|
+
if self.canvas.is_saving():
|
|
433
|
+
return # savefig also fires draw_event: never blit the screen
|
|
434
|
+
# background into a file render (bitten: truncated PNGs)
|
|
405
435
|
if self.active and self._last_event is not None:
|
|
406
436
|
self.onmove(self._last_event)
|
|
407
437
|
elif readout_lastev is not None:
|
|
@@ -649,8 +679,11 @@ readout_lastev = None # last motion event, to survive full redraws
|
|
|
649
679
|
|
|
650
680
|
def make_readout():
|
|
651
681
|
global readout_artist, readout_bg, readout_lastev
|
|
682
|
+
# visible=False except inside blit passes: savefig draws animated
|
|
683
|
+
# artists (mpl 3.9), so this keeps the readout out of saved output
|
|
652
684
|
readout_artist = fig.text(0.995, 0.012, "", ha="right", va="bottom",
|
|
653
685
|
family="monospace", fontsize=8, animated=True,
|
|
686
|
+
visible=False,
|
|
654
687
|
color="white" if dark_mode else "black")
|
|
655
688
|
readout_bg = None
|
|
656
689
|
readout_lastev = None
|
|
@@ -665,6 +698,8 @@ def snapshot_readout(ev):
|
|
|
665
698
|
the cursor takes ITS (full-figure) snapshot; the cursor's _redraw
|
|
666
699
|
re-renders the readout after every repaint instead."""
|
|
667
700
|
global readout_bg
|
|
701
|
+
if fig.canvas.is_saving():
|
|
702
|
+
return # don't snapshot a file render as the screen background
|
|
668
703
|
W, H = fig.bbox.width, fig.bbox.height
|
|
669
704
|
box = Bbox([[0.40 * W, 0.0], [W, 0.055 * H]])
|
|
670
705
|
readout_bg = (fig.canvas.copy_from_bbox(box), box)
|
|
@@ -693,10 +728,14 @@ def set_readout_text(ev):
|
|
|
693
728
|
def update_readout(ev):
|
|
694
729
|
if readout_artist is None or readout_bg is None or f is None:
|
|
695
730
|
return
|
|
731
|
+
if fig.canvas.is_saving():
|
|
732
|
+
return # no blitting into a file render
|
|
696
733
|
set_readout_text(ev)
|
|
697
734
|
bg, box = readout_bg
|
|
698
735
|
fig.canvas.restore_region(bg)
|
|
736
|
+
readout_artist.set_visible(True)
|
|
699
737
|
fig.draw_artist(readout_artist)
|
|
738
|
+
readout_artist.set_visible(False)
|
|
700
739
|
fig.canvas.blit(box)
|
|
701
740
|
|
|
702
741
|
|
|
@@ -976,6 +1015,7 @@ body { font-family: -apple-system, "Helvetica Neue", sans-serif;
|
|
|
976
1015
|
color: %(fg)s; background: %(bg)s; line-height: 1.45; }
|
|
977
1016
|
h1 { font-size: 1.5em; border-bottom: 2px solid %(rule)s; padding-bottom: 0.2em; }
|
|
978
1017
|
h1 .ver { font-size: 0.6em; font-weight: normal; color: %(accent)s; }
|
|
1018
|
+
p.lineage { font-size: 0.85em; color: %(rule)s; margin-top: -0.3em; }
|
|
979
1019
|
h2 { font-size: 1.15em; color: %(accent)s; margin-top: 1.4em; }
|
|
980
1020
|
table { border-collapse: collapse; margin: 0.5em 0; }
|
|
981
1021
|
th, td { border: 1px solid %(rule)s; padding: 0.25em 0.7em; text-align: left; }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|