Skip to content

Tags: ejeschke/ginga

Tags

v7.2.0

Toggle v7.2.0's commit message
Ginga v7.2.0

- Fixed gtk4 application shutdown.  Confirming a quit popped the
  confirmation dialog a *second* time and then crashed while recording
  window sizes on already-deleted widgets, and the application could fail
  to terminate.  Two causes: a toplevel window's ``destroy`` signal
  re-entered the close-confirmation flow while the window was being torn
  down deliberately, and the gtk4 main loop (``Gtk.Application.run``) does
  not poll ``ev_quit`` the way the other backends' loops do.  The
  deliberate teardown now disconnects its ``destroy`` handler, ``get_size``
  tolerates a torn-down widget, and ``Application.process_end()`` stops the
  Gtk loop -- so ``gui_quit()`` / ``ev_quit``-driven shutdown works as on
  the other backends.
- ``TableView`` gained spreadsheet-style cell editing.  A new
  ``set_editable(tf)`` makes every text column editable in one call (instead
  of per-column ``editable`` flags), and a new ``set_header_font()`` sets the
  column-header font (headers are now non-bold by default for a more compact
  table; pass a bold font to embolden).  On the ``qt`` and ``pg`` backends the
  table also has a current-cell cursor with arrow/Tab navigation and
  spreadsheet editing (type to replace, Delete/Backspace to clear, and
  commit-and-move on Tab/Enter/arrow).  The qt ``TableView`` was reimplemented
  on ``QTableWidget`` (from ``QTreeWidget``) to get native cell navigation,
  grid lines, row-number header and per-cell editability.  The gtk backends
  get ``set_editable()`` and ``set_header_font()``; their spreadsheet cursor/
  editing is a later refactor.
- The web (``pg``) backend's ``Timer`` is now a *server-side* timer for the
  websocket case instead of a browser-side JavaScript timer.  The old timer
  only fired while a browser was connected and every tick round-tripped the
  websocket, so a deferred redraw scheduled before the browser connected was
  lost and the viewer's redraw could wedge (e.g. a plugin's plot not updating
  until you zoomed).  Timers now schedule on a ``heaptimer`` heap owned by the
  ``Application`` and fire their callbacks on the GUI thread regardless of
  browser state, matching the qt/gtk/tk backends; async (single event loop)
  mode uses the asyncio timer heap so it stays thread-free, and in-situ
  (Pyodide) keeps the browser timer.  Also fixed ``Application.make_timer()``
  (it returned a raw pgwidgets timer) and ``Application.quit()`` (it raised
  instead of shutting down via ``GwMain.gui_quit()``).
  application (from the ``appname`` setting) instead of hardcoding "Ginga",
  so an application built on Ginga shows its own name.  The translated
  message catalogs were updated accordingly (the message id now takes a
  ``{}`` placeholder).
- Fixed the qt ``TableView`` selection becoming unreadable (white text on a
  white background) when ``show_grid=True``.  The grid-line stylesheet forces
  Qt into stylesheet-based item rendering, which ignored the palette-based
  selection highlight; the selection colours are now also stated in the
  stylesheet so the blue highlight stays visible under the grid.
- Added a ``pixi.toml`` manifest (https://pixi.sh) for a reproducible
  conda-forge based development environment: ``pixi run ginga`` launches the
  viewer and ``pixi run -e dev test`` runs the test suite.
- Window-fixed overlays now stay pinned to the viewport under a 3D camera in
  the OpenGL and Vulkan renderers.  Objects drawn in window/percentage
  coordinates (the onscreen message, mode indicator, color bar, etc.) are
  routed through a 2D orthographic projection instead of the (possibly
  tumbled) camera, so they no longer drift or scale with the 3D view.
  Relatedly, a ``Text`` object's background/border box is now built in window
  coordinates (matching the mode indicator and color bar) so it keeps a
  constant pixel size instead of growing with zoom under the camera, and
  ``set_onscreen_message()`` measures text extents accurately via Pillow.
- The **agg** renderer (``renderer='agg'``) has been reimplemented on top of
  matplotlib's Anti-Grain Geometry rasterizer (``backend_agg.RendererAgg``)
  instead of the unmaintained ``aggdraw`` package, dropping that dependency
  (matplotlib is already required).  The port also restores native drawing of
  Bezier curves and (rotated) ellipses -- ellipses now take a direct
  ``draw_ellipse`` path instead of a 13-point Bezier approximation -- and adds
  rotated text.
- The **pil** renderer now draws rotated text (previously rotation was
  ignored) by rasterizing the string to a scratch tile and rotating it; the
  common unrotated case still uses the fast direct-draw path.
- Requesting the generic ``qt`` toolkit (``-t qt``, or letting Ginga
  auto-choose) no longer emits a ``qtpy`` ``PythonQtWarning`` about falling
  back from ``pyqt5`` when that binding is absent: Ginga now points
  ``$QT_API`` at whichever Qt binding is actually installed and selects it
  directly.  A *specific* request (``qt5``/``qt6``/``pyside2``/``pyside6``)
  still forces that binding and warns if it is missing, and a user-set
  ``$QT_API`` is respected.
- The ``mkapp`` folder for building a standalone desktop application (a macOS
  ``.app`` or Windows ``.exe``) has been modernized to use **PyInstaller**
  (replacing the obsolete py2app/py2exe ``setup.py``): a single ``ginga.spec``
  builds either platform, driven by a cross-platform ``build.py``.  Install
  the tooling with the new ``pyinstaller`` extra (``pip install
  ginga[pyinstaller]``).  See ``mkapp/README.rst``.

v7.1.0

Toggle v7.1.0's commit message
Ginga release v7.1.0

- Added an experimental **Vulkan renderer** (``renderer='vulkan'``), a
  GPU-accelerated, toolkit-agnostic renderer built as an alternative to the
  OpenGL one.  It renders GPU-native (images colormapped in-shader with live
  cut levels/distribution, shapes/wide/dashed lines, native Pillow text, RGBA
  alpha, and a 3D camera mode) into an *offscreen* Vulkan image and hands the
  result back as an array, so every backend (qt, gtk3, gtk4, tk, and the pg
  web/websocket backend) can use it via the same array path as the pil/agg
  renderers.  Select it with ``ginga -t <toolkit> -r vulkan`` or the new
  per-viewer ``renderer`` setting; it falls back automatically when the
  ``vulkan`` binding or a device is unavailable.  Requires the optional
  ``vulkan`` dependency (``pip install ginga[vulkan]``) and a system Vulkan
  driver (Mesa lavapipe works for a CPU/headless device).  See the developer
  manual ("The Vulkan renderer") for details.  Not available in-situ under
  Pyodide/PyScript.
- The OpenGL renderer now draws text by rasterizing it with Pillow and
  blitting a texture (filled, anti-aliased) instead of converting it to
  cairo path outlines, and supports wide and dashed lines by expanding them
  into filled triangles (OpenGL does not guarantee ``lineWidth > 1`` or
  stippling).  This drops the cairo dependency for OpenGL text.
- bump required version of a few dependencies
- Menu items can now show an icon as well as (or instead of) text, like
  toolbar actions.  ``Menu.add_name()``, ``Menu.add_menu()`` and
  ``Menubar.add_name()`` accept ``iconpath``/``iconsize`` keyword arguments,
  and ``MenuAction`` gains a ``set_icon()`` method.  An ``icon_only`` flag
  requests showing just the icon where the backend can render it, always
  falling back to the text label otherwise, so the same calling code shows
  the icon, the text, or both depending on the backend.  Fully supported on
  the qt, gtk3, and pg (web) backends; the gtk4 backend accepts the
  arguments for API parity but renders text only for now
- The qt ``RadioButton`` now honors the ``group`` keyword across different
  containers.  Previously qt only made radio buttons mutually exclusive when
  they shared a parent widget; grouped buttons now use a shared
  ``QButtonGroup``, matching the gtk3/gtk4/pg backends
- Added a ``TreeView.delete_tree()`` method (qt/gtk3/gtk4/pg) that removes
  the nodes named by a subtree of keys -- individual leaves or whole
  subtrees -- from a loaded tree, optionally pruning branches left empty,
  preserving the selection on surviving items, and firing the ``selected``
  callback if the selection changed and ``changed`` if anything was deleted
- The ``ColorDist`` color distribution classes now produce a normalized
  0.0-1.0 floating point curve; the RGB mapping ``Distribute`` stage scales
  that to the output level (bit depth) and quantizes to the index type.
  This preserves precision (no longer capped at 256 levels for deeper
  outputs) and is slightly faster.  The ``colorlen`` argument to the
  ``ColorDist`` classes is now vestigial and deprecated (it has no effect).
  Custom ``ColorDist`` subclasses should now install their curve as a
  normalized 0.0-1.0 float array via the new public ``set_hash()`` method
  (formerly ``_set_hash``).  For backward compatibility, a subclass whose
  ``calc_hash()`` still stores a pre-7.1 integer/``colorlen``-scaled hash is
  detected at build time and normalized automatically, with a
  ``PendingDeprecationWarning``; this shim will be removed in a future
  release (github issue #1148)
- Color maps are now resolution-independent: ``ginga.cmap.ColorMap`` gains
  ``get_colors(n)``, which samples/interpolates the map to any size, and can
  be built from a discrete list (as before), piecewise-linear control points
  (``ColorMap.from_control_points``), or a callable (``from_function``).
  matplotlib color maps are captured without retaining a runtime dependency
  on matplotlib
- Added a ``color_depth`` viewer setting that controls the resolution (in
  bits) at which pseudocolor is distributed, decoupled from the RGB output
  depth.  Raising it (e.g. to 12) yields much smoother gradients -- many more
  distinct colors and far less banding -- for colorful color maps on a
  standard 8-bit display, at negligible cost.  The default (8) is unchanged.
  Both the standard and OpenGL renderers honor the setting (the OpenGL
  renderer sizes its GPU colormap texture up to 4096 entries)
- The DS9-derived color maps (``gray``, ``ramp``, ``red``, ``green``,
  ``blue``, ``heat``, ``ds9_cool``, ``ds9_a``, ``ds9_b``, ``ds9_bb``,
  ``ds9_he``) are now defined by their authoritative SAOImageDS9
  piecewise-linear control points instead of baked 256-entry arrays.  They
  are exact, resolution-independent (smooth at any color depth), and small
  (this also removed ~2600 lines from ``ginga/cmap.py``)
- Fixed an issue with matplotlib plots getting their axes labels cut off

v7.0.0

Toggle v7.0.0's commit message
Ginga v7.0.0

- Adopted the new ``pgwidgets`` widget set (JavaScript widgets + Python
  bindings) as the basis of the ``ginga.web.pgw`` backend.
  (More information on pgwidgets can be found at the
  `pgwidgets-js home page <https://github.com/naojsoft/pgwidgets-js>`__
  and `pgwidgets-python page <https://github.com/naojsoft/pgwidgets-python>`__)
- The reference viewer and the ``pg`` (web) widget set can now run
  *entirely in the browser* via Pyodide/PyScript ("in-situ"), in addition
  to the existing remote (web socket) mode; the widgets, image viewer
  (``ImageViewPg``), plot viewer and ``ipg`` were reworked to support this
- Added an optional asyncio-based, single-event-loop task pool (with an
  async timer heap) so background ("nongui") work can run cooperatively on
  the browser event loop where there are no threads; added
  ``GwMain.nongui_foreach`` for responsive chunked work
- Refactored the font assistant to support family/style/weight, added
  ``Application`` methods to register shipped/loadable fonts and set a
  default font, changed the default font from "Roboto" to "sans", and
  fixed font handling across the PIL, OpenCV, AGG and Matplotlib backends
- Added a central ``download_file()`` (Downloads delegates to it), a
  ``fetch_url`` helper plus a Sesame name server, a backend-aware
  ``open_url``, and an ``is_in_situ()`` check, so network access works
  both natively and in the browser (via a same-origin CORS proxy)
- Remember position and size of a window in an MDI workspace after a plugin
  has been closed and reopened
- Plugin updates: PixTable now uses a ``TableView``; fixes to Contents,
  Errors, FBrowser, Blink (close), WCSAxes, label color, and the startup
  banner under the ``pg`` backend
- Many backend fixes (Qt/Gtk3/Gtk4/pg): font resolution, cell padding,
  label colors, Gtk4 menu styling and Info-panel label alignment
- Fixed application shutdown under Qt6: ``Application.quit()`` now calls
  ``QApplication.exit()`` instead of ``quit()``.  On Qt6, ``quit()`` sends a
  close event to every top-level window and cancels the shutdown if any window
  ignores it -- which Ginga's windows do by default -- so ``app.mainloop()``
  would never return.  Window-close (``'close'``) callbacks are unaffected, so
  applications can still intervene in a window closing
- Added internationalization (i18n) support to the reference viewer: most
  UI strings, ``build_info`` captions, and plugin/mode help are now
  translatable through ``ginga.locale``, with a ``Language`` menu to switch
  and translations provided for German, Japanese, French, Italian, Chinese,
  Korean and Spanish; the machinery is reusable by downstream applications
  via ``localize.register()``
- Added two general settings (in ``general.cfg``) to control the UI language:
  ``language`` selects the language (``None`` honors the environment locale,
  otherwise a code like ``"ja"``, falling back to English if unavailable), and
  ``show_languages`` (default ``True``) controls whether the ``Language`` menu
  is offered in the menubar -- set it to ``False`` to lock down the language
  while still honoring the ``language`` setting

See doc/WhatsNew.rst for a full description of changes

v6.0.0

Toggle v6.0.0's commit message
Ginga release v6.0.0

- Added ability to add icons to Ginga-wrapped Button widgets
- Refactored Pan and Header plugins to use new parent/child plugin
  implementation
- Fixed an issue with setting filters in Gtk based FileDialogs
- Refactoring of the Control module of the reference viewer to separate viewer
  logic from the workspace and plugin management
- You can now set the start attribute for a local plugin in the plugin
  spec and it will start when a new channel is created
- New ability to have more than one instance of a global plugin (if enabled)
  and more than one instance of a local plugin per channel (if enabled)

  - local plugins with this enabled: Pick, Cuts, Histogram, Ruler, Drawing,
    PlotTable. Check use of "ident" attribute in the plugin code and setting
    singeton=False in the plugin spec

- Added a background to Crosshair text for better readability
- Refactored cursor readout to allow for more flexible ways to override the
  default.  You can now register a function to the 'pixel-info' callback
  on a canvas, and return the information to show in the readout.
- Fixed an issue where there was an unintended fill in drawing a Bezier
  curve with the Qt backend
- Improvements to plugins to use the new the plot viewer (event callback
  API is changed, thus bump to new major version), but should be backward
  compatible aside from event callbacks
- Fix to handling of pan/scroll with touchpads in Qt6

v5.5.1

Toggle v5.5.1's commit message
Ginga v5.5.1

- Fixed an issue with values not being read out under the cursor
- Added variable size font (according to window size) in the plot viewer

v5.5.0

Toggle v5.5.0's commit message
Ginga v5.5.0

- fixed default port number for Ginga remote control in the docstring
- fixed an issue with the Pan viewer not redrawing when only the overlay
  graphics change in the associated channel viewer
- fixed an issue where the Preferences plugin did not show the color
  distribution algorithm that was saved in the channel correctly
- Added internal support for dask and zarr arrays
- Fixed an issue with the close confirmation dialog under Gtk3 backend
- Adds keyboard mode support for the plot viewer
- Adds thumbnails for plot and table viewer items
- Fixed a mouse scrolling issue for Gtk4 backend
- Fixed an issue where the thumbnail labels were not highlighted correctly
  in the Thumbs plugin

v5.4.0

Toggle v5.4.0's commit message
Ver 5.4.0 (2025-08-10)

- Wrapped widget enhancements

  - added methods and callbacks for expansion and collapse of rows in TreeView
  - ability to set color of Button widgets
  - add ColorDialog, a color selection dialog
  - add FileDialog, a file/directory dialog (can replace FileSelection)
  - fixed an issue with custom styling being inherited unnecessarily

- Fixed a bug where FITS loader preference on command line options
  or configuration file was not working
- Add ability to dynamically reload separately distributed plugins
  using the Command plugin (with reload_local or reload_global commands)
- Changed default port for Remote Control plugin and made a command line
  switch (--rcport) to allow launch time changing of the port
- Fixed an spurious error when closing Ginga after shutting down the RC
  plugin manually
- A fix for the Tk widget on Windows and Mac OSX to allow proper scrolling
- Better formatting of cuts and plot limits (limit excessive decimals)
- Fixed an error in reference viewer with detection of Gtk toolkits
- Gtk4 backend support is much improved
- Enhancements to the thread pool, with dynamic adding of threads when
  busy and stopping of threads when they have been idle

v5.3.0

Toggle v5.3.0's commit message
Ginga v5.3.0

- Fixed an issue with editing objects in the Pick plugin
- Fixed an issue where image metadata not always loaded correctly with
  Pillow for RGB images
- Added support for Apple HEIF (.HEIC) RGB images if pillow-heif is installed
- Fixed an issue with circular import of loader entry points under python 3.12
- Updates of minimum required versions of support packages

v5.2.0

Toggle v5.2.0's commit message
Ginga version v5.2.0

- Substituted puremagic package for python-magic (works better across
  platforms).
- Fixed an issue with the mouse wheel event scrolling MDI workspaces.
- Fixed a spurious warning when moving the cursor in the Pan plugin
  window and a table or plot viewer is running in the channel
- Made the enter_focus property default to False

  - Viewer windows will not steal the keyboard focus if the mouse moves
    over them

- Added alternate versions of installed fonts to the default font set
  (bold, italic, light)
- Some minor bug fixes for TreeView in Gtk3 backend
- Enhanced Plot viewer can plot 1D images or from tables via Table viewer

  - Toolbar and Info (Synopsis) bars change GUIs according to which
    viewer is active in the channel

- Text canvas type gets new attributes: bgcolor, bgalpha, bordercolor,
  borderpadding, borderalpha, borderlinewidth
- Deprecate Gtk.Table from GTK3 backend (switch to Gtk.Grid)
- Added experimental support for GTK4 backend
- Fixed an issue with toggling CheckBoxes in Qt6
- Closing a workspace now doesn't require closing all windows first

v5.1.0

Toggle v5.1.0's commit message
Ginga v5.1.0

- Fixed an issue where --modules option did not start a global plugin
  automatically
- Improved error checking on contains_pts() method for canvas items
- Removed references to distutils module, deprecated in python 3.12
- Made menubar a plugin; this allows very flexible menu configuration
  for users implementing their own variations on the reference viewer;
  NOTE: if you don't see Ginga menus, delete your $HOME/.ginga/layout*
- Added default antialiasing to cairo renderer
- Fixed drawing of dimension labels for rectangles specified in WCS
  coordinates
- Fixed drawing of Crosshair canvas object in opengl backend
- Fixed drawing of XRange and YRange in non-data coordinates
- Refactoring of rendering primitives; simplifies renderer implementation

  - "Text" objects now have linewidth (default: 0), fill (default: True),
    fillcolor (default: None) and fillalpha (default: 1.0) attributes.
    Default behavior if fillcolor isn't specified is to default to the
    "color" attribute, thus preserving backward-compatible behavior.

- Fixed broken WCS compass in Pan plugin
- Fixed broken Close button in FBrowser and ColorMapPicker when activated
  as global plugins
- Fixed a bug in PixTable plugin where it would report a table for X and Y
  values outside the image
- Fixed bokeh back end to be up to date with recent bokeh changes