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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyredshift
3
- Version: 1.13
3
+ Version: 1.14
4
4
  Summary: Interactive redshifting of 1D astronomical spectra (Python successor of pdlredshift / redshift.f)
5
5
  Home-page: https://github.com/karlglazebrook/pyredshift
6
6
  Author: Karl Glazebrook
@@ -13,7 +13,7 @@ from setuptools import setup
13
13
 
14
14
  setup(
15
15
  name="pyredshift",
16
- version="1.13",
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) &rarr; <code>pdlredshift</code>
6
+ (Perl/PDL/PGPLOT 2018) &rarr; <code>pyredshift</code> (Python/matplotlib,
7
+ ported with Claude, 2026) &mdash; 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
- for _backend in ("QtAgg", "MacOSX", "TkAgg"):
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.13"
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; }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyredshift
3
- Version: 1.13
3
+ Version: 1.14
4
4
  Summary: Interactive redshifting of 1D astronomical spectra (Python successor of pdlredshift / redshift.f)
5
5
  Home-page: https://github.com/karlglazebrook/pyredshift
6
6
  Author: Karl Glazebrook
File without changes
File without changes
File without changes
File without changes
File without changes