pyredshift 1.13__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.13 → pyredshift-1.14}/PKG-INFO +1 -1
- {pyredshift-1.13 → pyredshift-1.14}/setup.py +1 -1
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift/pyredshift-help.html +10 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift/redshift.py +43 -6
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift.egg-info/PKG-INFO +1 -1
- {pyredshift-1.13 → pyredshift-1.14}/LICENSE +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/README.md +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/pyproject.toml +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/pyredshift +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/setup.cfg +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift/__init__.py +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift/pyredshift.lines +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift.egg-info/SOURCES.txt +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift.egg-info/dependency_links.txt +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift.egg-info/requires.txt +0 -0
- {pyredshift-1.13 → pyredshift-1.14}/src/pyredshift.egg-info/top_level.txt +0 -0
|
@@ -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">
|
|
@@ -56,6 +56,16 @@ V1.12 - The version number is shown by -h/-help and on the help page.
|
|
|
56
56
|
V1.13 - CSV reader: blank flux cells are bad pixels (NaN, plotted as
|
|
57
57
|
gaps) instead of desynchronising the wavelength and flux arrays;
|
|
58
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.
|
|
59
69
|
"""
|
|
60
70
|
|
|
61
71
|
import ctypes
|
|
@@ -69,10 +79,16 @@ from html.parser import HTMLParser
|
|
|
69
79
|
import numpy as np
|
|
70
80
|
import matplotlib
|
|
71
81
|
|
|
72
|
-
# 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.
|
|
73
85
|
if "MPLBACKEND" not in os.environ:
|
|
74
|
-
|
|
86
|
+
import importlib
|
|
87
|
+
for _backend, _mod in (("QtAgg", "backend_qtagg"),
|
|
88
|
+
("MacOSX", "backend_macosx"),
|
|
89
|
+
("TkAgg", "backend_tkagg")):
|
|
75
90
|
try:
|
|
91
|
+
importlib.import_module("matplotlib.backends." + _mod)
|
|
76
92
|
matplotlib.use(_backend)
|
|
77
93
|
break
|
|
78
94
|
except ImportError:
|
|
@@ -95,7 +111,7 @@ try:
|
|
|
95
111
|
except AttributeError:
|
|
96
112
|
pass
|
|
97
113
|
|
|
98
|
-
__version__ = "1.
|
|
114
|
+
__version__ = "1.14"
|
|
99
115
|
|
|
100
116
|
C_LIGHT = 2.99792458e8 # m/s
|
|
101
117
|
|
|
@@ -384,27 +400,38 @@ class StickyCursor(Cursor):
|
|
|
384
400
|
self.linev.set_data((xdata, xdata),
|
|
385
401
|
((figbb.y0 - axbb.y0) / axbb.height,
|
|
386
402
|
(figbb.y1 - axbb.y0) / axbb.height))
|
|
387
|
-
self.linev.set_visible(self.visible and self.vertOn)
|
|
388
403
|
self.lineh.set_data(((figbb.x0 - axbb.x0) / axbb.width,
|
|
389
404
|
(figbb.x1 - axbb.x0) / axbb.width),
|
|
390
405
|
(ydata, ydata))
|
|
391
|
-
self.lineh.set_visible(self.visible and self.horizOn)
|
|
392
406
|
if not (self.visible and (self.vertOn or self.horizOn)):
|
|
393
407
|
return
|
|
394
|
-
# 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.
|
|
395
411
|
if self.useblit:
|
|
396
412
|
if self.background is not None:
|
|
397
413
|
self.canvas.restore_region(self.background)
|
|
414
|
+
self.linev.set_visible(self.vertOn)
|
|
415
|
+
self.lineh.set_visible(self.horizOn)
|
|
398
416
|
self.ax.draw_artist(self.linev)
|
|
399
417
|
self.ax.draw_artist(self.lineh)
|
|
418
|
+
self.linev.set_visible(False)
|
|
419
|
+
self.lineh.set_visible(False)
|
|
400
420
|
if readout_artist is not None:
|
|
401
421
|
set_readout_text(event) # restore wiped the corner -
|
|
422
|
+
readout_artist.set_visible(True)
|
|
402
423
|
fig.draw_artist(readout_artist) # redraw with fresh values
|
|
424
|
+
readout_artist.set_visible(False)
|
|
403
425
|
self.canvas.blit(figbb)
|
|
404
426
|
else:
|
|
427
|
+
self.linev.set_visible(self.visible and self.vertOn)
|
|
428
|
+
self.lineh.set_visible(self.visible and self.horizOn)
|
|
405
429
|
self.canvas.draw_idle()
|
|
406
430
|
|
|
407
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)
|
|
408
435
|
if self.active and self._last_event is not None:
|
|
409
436
|
self.onmove(self._last_event)
|
|
410
437
|
elif readout_lastev is not None:
|
|
@@ -652,8 +679,11 @@ readout_lastev = None # last motion event, to survive full redraws
|
|
|
652
679
|
|
|
653
680
|
def make_readout():
|
|
654
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
|
|
655
684
|
readout_artist = fig.text(0.995, 0.012, "", ha="right", va="bottom",
|
|
656
685
|
family="monospace", fontsize=8, animated=True,
|
|
686
|
+
visible=False,
|
|
657
687
|
color="white" if dark_mode else "black")
|
|
658
688
|
readout_bg = None
|
|
659
689
|
readout_lastev = None
|
|
@@ -668,6 +698,8 @@ def snapshot_readout(ev):
|
|
|
668
698
|
the cursor takes ITS (full-figure) snapshot; the cursor's _redraw
|
|
669
699
|
re-renders the readout after every repaint instead."""
|
|
670
700
|
global readout_bg
|
|
701
|
+
if fig.canvas.is_saving():
|
|
702
|
+
return # don't snapshot a file render as the screen background
|
|
671
703
|
W, H = fig.bbox.width, fig.bbox.height
|
|
672
704
|
box = Bbox([[0.40 * W, 0.0], [W, 0.055 * H]])
|
|
673
705
|
readout_bg = (fig.canvas.copy_from_bbox(box), box)
|
|
@@ -696,10 +728,14 @@ def set_readout_text(ev):
|
|
|
696
728
|
def update_readout(ev):
|
|
697
729
|
if readout_artist is None or readout_bg is None or f is None:
|
|
698
730
|
return
|
|
731
|
+
if fig.canvas.is_saving():
|
|
732
|
+
return # no blitting into a file render
|
|
699
733
|
set_readout_text(ev)
|
|
700
734
|
bg, box = readout_bg
|
|
701
735
|
fig.canvas.restore_region(bg)
|
|
736
|
+
readout_artist.set_visible(True)
|
|
702
737
|
fig.draw_artist(readout_artist)
|
|
738
|
+
readout_artist.set_visible(False)
|
|
703
739
|
fig.canvas.blit(box)
|
|
704
740
|
|
|
705
741
|
|
|
@@ -979,6 +1015,7 @@ body { font-family: -apple-system, "Helvetica Neue", sans-serif;
|
|
|
979
1015
|
color: %(fg)s; background: %(bg)s; line-height: 1.45; }
|
|
980
1016
|
h1 { font-size: 1.5em; border-bottom: 2px solid %(rule)s; padding-bottom: 0.2em; }
|
|
981
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; }
|
|
982
1019
|
h2 { font-size: 1.15em; color: %(accent)s; margin-top: 1.4em; }
|
|
983
1020
|
table { border-collapse: collapse; margin: 0.5em 0; }
|
|
984
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
|
|
File without changes
|