Ginga: Image Viewer and Toolkit¶
About Ginga¶
Ginga is a toolkit designed for building viewers for scientific image data in Python, visualizing 2D pixel data in NumPy arrays. It can view astronomical data such as contained in files based on the FITS (Flexible Image Transport System) file format. It is written and is maintained by software engineers at the Subaru Telescope, National Astronomical Observatory of Japan.
The Ginga toolkit centers around an image display class which supports zooming and panning, color and intensity mapping, a choice of several automatic cut levels algorithms and canvases for plotting scalable geometric forms. In addition to this widget, a general purpose “reference” FITS viewer is provided, based on a plugin framework.
A fairly complete set of “standard” plugins are provided for features that we expect from a modern FITS viewer: panning and zooming windows, star catalog access, cuts, star pick/FWHM, thumbnails, etc.
Copyright and License¶
Copyright (c) 2011-2018 Eric R. Jeschke. All rights reserved.
Ginga is distributed under an open-source BSD licence. Please see the
file LICENSE.txt
in the top-level directory for details.
Requirements and Supported Platforms¶
Because Ginga is written in pure Python, it can run on any platform that has the required Python modules and has a supported widget set. The basic Ginga display class supports the Qt (4 and 5), PySide, Gtk (2 and 3), Tk widget sets natively as well as any Matplotlib Figure, and HTML5 canvases in a web browser. The full reference viewer supports Qt and Gtk variants. Ginga can also be used in Jupyter notebooks.
Getting the Source¶
Clone from Github:
$ git clone https://github.com/ejeschke/ginga.git
To get a zip or tar ball instead, see the links on About Ginga.
Building and Installation¶
Download and install from pip
:
$ pip install ginga
Or, if you have downloaded the source, go into the top-level directory and run the following:
$ python setup.py install
The reference viewer can then be run using the command ginga
.
Detailed Installation Instructions for Ginga¶
Dependences¶
Ginga is written entirely in Python, and only uses supporting Python packages. There is nothing to compile (unless you need to compile one of the supporting packages).
On recent Linux, Mac and Windows versions, all of the packages are available in binary (installable) form. It should not be necessary to compile anything, but as always, your mileage may vary.
REQUIRED¶
- python (either v. 2.7 OR v. 3.4 or higher)
- numpy (v. 1.7 or higher)
Highly recommended, because some features will not be available without it:
- scipy
- pillow
- opencv
For opening FITS files you will need one of the following packages:
- astropy
- fitsio
For WCS resolution you will need one of the following packages:
- astropy
- kapteyn
- astLib
- starlink
BACKENDS (one or more)¶
Ginga can draw its output to a number of different back ends. Depending on which GUI toolkit you prefer (and what you want to do), you will need at least one of the following:
- python-qt4
- python-qt5
- python-pyside (qt4 alternative)
- python-gtk (gtk2) AND python-cairo
- python gtk3 (gi) AND python-cairo
- python-Tkinter
- matplotlib
- tornado
- aggdraw
- PIL (pillow)
- OpenCv
RECOMMENDED¶
Certain plugins in the reference viewer (or features of those plugins) will not work without the following packages:
- matplotlib (required by: Pick, Cuts, Histogram, LineProfile)
- webkit (required by: WBrowser (used for online help))
- scipy (required by: Pick, some built-in auto cuts algorithms used when you load an image)
- astropy (required by: SAMP)
To save a movie:
- mencoder (required by: Cuts)
Helpful, but not necessary (may optimize or speed up certain operations):
- python-opencv (speeds up rotation, mosaicing and some transformations)
- python-pyopencl (speeds up rotation, mosaicing and some transformations)
- python-numexpr (speeds up rotation a little)
- python-filemagic (aids in identifying files when opening them)
- python-PIL or pillow (useful for various RGB file manipulations)
Notes on Supported Widget Sets¶
In the discussion below, we differentiate between the Ginga viewing
widget, such as used in the examples/\*/example\*.py
programs and the
full reference viewer, which includes many plugins (scripts/ginga
).
Note
For the full reference viewer, Mac and Windows users should probably install the Qt version, unless you are the tinkering sort. Linux can use either Qt or Gtk fine.
Qt/PySide¶
Ginga can use either PyQt or PySide, version 4 or 5. It will auto-detect which one is installed. There is support for both the basic widget and the full reference viewer.
Note
If you have both installed and you want to use a specific one then set the environment variable QT_API to either “pyqt” or “pyside”. This is the same procedure as for Matplotlib.
Gtk¶
Ginga can use either Gtk 2 (with pygtk) or gtk 3 (with gi). (If you have an older version of pycairo package you may need to install a newer version from github.com/pygobject/pycairo).
Tk¶
Ginga’s Tk support is limited to the viewing widget itself. For overplotting (graphics) support, you will also need:
- “pillow”/PIL package
- “OpenCv” module
- “aggdraw” module (which you can find here ; supports Python 2 only).
Matplotlib¶
Ginga can render directly into a Matplotlib figure. Support is limited to the viewing widget itself. Any of the backends that Matplotlib supports is usable. Performance is not as good as to one of the “native” backends listed above, but oh, the overplot options!
HTML5 web browser¶
Ginga can render into an HTML5 canvas via a web server. Support is limited
to the viewing widget itself. See the notes in example/pg/example1_pg.py
.
Tested browsers include Chromium (Chrome), Firefox, and Safari.
Installation from Source¶
Clone from github:
$ git clone https://github.com/ejeschke/ginga.git
Or see links on this page to get a zip or tar ball.
Unpack, go into the top level directory, and run:
$ python setup.py install
The reference viewer can then be run using the command
ginga
.
Alternatively you can download and install via pip
:
$ pip install ginga
Platform Specific Instructions¶
Linux¶
Install the necessary dependences. If you are on a relatively recent version of Ubuntu (e.g. v14.04 or later), something like the following will work:
$ apt-get install python-numpy python-scipy python-matplotlib \ python-astropy python-qt4 python-webkit python-magic git pip
Or:
$ apt-get install python-numpy python-scipy python-matplotlib \ python-astropy python-gtk python-cairo python-webkit \ python-magic git pip
(if you want to use the Gtk version)
Install ginga with pip:
$ pip install ginga
or by obtaining the source and installing as described above.
Mac¶
For Mac users, we recommend installing the Anaconda distribution. This distribution already includes all of the necessary packages to run Ginga.
As an alternative, you also have the choice of Enthought Canopy. The free version works fine. After installing this, open the Canopy package manager, search for “astropy” and install it. Also search for and install “pyside” (free version of Qt bindings).
After installing one of these distributions, open a Terminal and install Ginga via “pip install ginga”. You can then run the reference viewer via the command “ginga”.
Note
Ginga can be installed and run fine using a working Macports or Homebrew installation. Simply follow the package advice given above under the Linux instructions.
Windows¶
Anaconda¶
For Windows users, we recommend installing the
Anaconda distribution
.
This distribution already includes all of the necessary packages to run
Ginga.
After installing Anaconda, you can find the reference viewer script as:
Start -> All Programs -> Anaconda -> Anaconda Command Prompt
pythonw Scripts\ginga
Enthought Canopy¶
As an alternative, you also have the choice of Enthought Canopy.
Install the free version.
Open the Canopy package manager.
Search for and install “astropy”.
Search for and install “pyside” (free version of Qt bindings).
Start -> All Programs -> Enthought Canopy -> Canopy command prompt pip install ginga pythonw AppDataLocalEnthoughtCanopyUserScriptsginga
Documentation¶
What’s New in Ginga?¶
Ver 2.7.1 (2018-07-09)¶
- Fix for image rendering bug which shows last row and column of image being drawn twice
- Added option to “Compass” draw type to be in pixels (X/Y) or wcs (N/E)
- Changed Pan plugin to attempt to draw both kinds of compasses
- Log plugin enhanced to show lines logged before it was opened
- Info plugin adds convenience controls for “Follow New” and “Raise New”
- WCSMatch plugin enhanced to offer fine grained control over sync
- fixed an issue in Debian build that caused long start up times
- User can dynamically add scrollbars to channel viewers in Preferences
- Made Gtk backend default to ‘gtk3’ - “-t gtk” now invokes gtk3 instead of gtk2 - choose “-t gtk2” if you want the gtk2 back end
- Fixed a bug with opening wildcard-type filespec from the command line
- Fixed an issue in Thumbs plugin with opening FITS tables from the command line
- Fixes for some keyboard focus (Gtk) and unintentional channel changes (Qt) when viewer is in MDI mode
- IRAF plugin moved to experimental folder
- Allow setting of initial channel list, local, global and disabled plugins from general configuration file
- Fix for a bug when using OpenCv acceleration on dtype(‘>f8’) arrays
- Fixed a bug where colormap scale markers were sometimes not spaced wide enough
- Workaround for failed PDF build in RTD documentation
Ver 2.7.0 (2018-02-02)¶
- Fix for gtk 4.0 (use “gtk3” backend, it works for 4.0)
- Fix for broken polygon containment test
- Addition of configurable zoom handlers for pan gestures
- Fix for some broken tests under python 2.7
- Update to mode handling via keyboard shortcuts
- addition of a new “meta” mode used primarily for mode switching
- most modes now initiated from meta mode, which frees up keys for other uses
- see Ginga quick reference for details on how the new bindings work
- Efficiency update for Thumbs plugin when many thumbs are present
- Default for the save_layout option is now True, so the reference viewer will write out its layout state on exit and restore it on startup. See documentation in the “customization” section of the manual.
- Plugins can now be organized by category and these categories are used to construct a hierarchical Operations menu
- Zoom and Header plugins are now not started by default
- Fix for “sortable” checkbox behavior on Header plugin
- Default keyboard mode type is now ‘locked’ (prev ‘oneshot’)
- Fixes for missing CSS file in installation script
- Less confusing behavior for workspace and toolbar arrow buttons
Ver 2.6.6 (2017-11-02)¶
- Fix for broken sorting in Contents plugin in gtk backends
- Fix for resize bug in switching in and out of grid view in gtk backends
- Updated to have efficient support for gtk3
- please install compatible pycairo from github.com/pygobject/pycairo if you get a “Not implemented yet” exception bubbling up from a method called cairo.ImageSurface.create_for_data()
- Addition of a “Quick Mode” to the Pick plugin–see documentation
- More consistent font handing between widgets and Ginga canvases
- Bug fix for importing some types of matplotlib color maps
- Add antialiasing for Qt back end
- Bug fixes and enhancements for Qt gestures - holding shift with pinch now keeps position under cursor
- New Jupyter notebooks back end based on ipywidgets - requirements: $ pip install ipyevents - see examples/jupyter-notebook/
- Fixes to various reference viewer plugins
Ver 2.6.5 (2017-07-31)¶
- Coordinate transforms refactored for speed and code clarity
- Some canvas shapes refactored for better code reuse
- Allow max and min scale limits to be disabled (by None)
- Fixed a bug that prevented the reference viewer from resizing correctly with Qt back end
- Refactored WCS wrapper module for code clarity
- Set minimum astropy version requirement to 1.X
- Fixed a bug in NAXIS selection GUI (MultiDim plugin)
- Fixed MDI window resizing with Gtk back ends
- Fixed an error where zoom 100% button did not correctly zoom to 1:1 scale
- Several fixes for astropy 2.0 compatibility
- Fixed a bug in the FBrowser plugin when channel displaying a table and attempting to load a new file
- Fixed a bug when setting the pan position manually by wcs coordinates
- Updates for changes in PIL.ImageCms module
- Fix for window corruption on certain expose events
- New default bindings for touch pads and differentiation from wheel zoom
Ver 2.6.4 (2017-06-07)¶
- Added new ScreenShot plugin to take PNG/JPEG snaps of the viewer window
- Enhancements to the Pick plugin
- Added ability to make shapes besides rectangles for enclosing pick area. Masks out unwanted pixels. Choose the shape in the Settings tab.
- Changed behavior of pick log to only write the log when the user clicks the save button.
- Changed the name of the save button to “Save as FITS table” to make it clear what is being written.
- If “Show candidates” is selected in Settings, then ALL of the candidates are saved to the log.
- Added documentation to the manual
- Bug fix for error when changing radius
- Improvements to layout of Operations menu (plugin categories)
- Colorbar scale now placed below the color wedge and is more legible
- Bug fixes for LineProfile plugin
- Slit function for Cuts plugin can be enabled from GUI
- Bug fixes for Slit function
- Info plugin can now control new image cut/zoom/center settings
- Fixed an issue with the MultiDim plugin that could result in a hang with some back ends
- New canvas type for displaying WCS grid overlay and new WCSAxes plugin that uses it
- Bug fixes to scrolling via scrollbars and vert/horiz percentages
- Enhancements to the LineProfile plugin
- several new shapes besides the standard point
- plot multiple lines
Ver 2.6.3 (2017-03-30)¶
- Fix for issue that stops ginga startup when loading externally distributed plugins that have errors
- Fix for an issue loading plugins from the command line when they are nested in a package
- Added bindings for moving +/- pixel delta in X or Y and centering on the pixel
- Fixes for some key mappings for tk, matplotlib and HTML5 canvas backends
- Fixes for IRAF plugin under python 3
- Fix for a bug using remote control (RC) plugin from python2 client to python 3 ginga
- Documentation updates
Ver 2.6.2 (2017-02-16)¶
- Added some colormaps from ds9 that don’t have equivalents in Ginga or matplotlib
- Fix for recognizing CompImage HDU type when using astropy.io.fits
- Add new experimental OpenGL back end
- Fixes for Tk back end on python 3
- You can now write separately distributed and installable plugins for the reference viewer that Ginga will find and load on startup
- Added –sep option to load command line files into separate channels
- New help screen feature available for plugins
- Lots of updates to documentation
- Fixed a stability issue with drag and dropping large number of files under Linux
- Fixes for python3 and several example programs
- Fix for interactive rotation bug under matplotlib back end
Ver 2.6.1 (2016-12-22)¶
- Added a working MDI workspace for gtk2/gtk3.
- Added scrollbar frames. See examples/qt/example1_qt.py for standalone widget. Can be added to reference viewer by putting ‘scrollbars = “on”’ in your channel_Image.cfg preferences.
- Reorganized reference viewer files under “rv” folder.
- Improved Pick plugin: nicer contour plot, pick log uses table widget, pick log saved as a FITS table HDU
- Pick and Zoom plugins can now use a specific color map, rather than always using the same one as the channel window
- gtk3 reference viewer can now be resized smaller than the original layout (gtk2 still cannot)
- added ability to save the reference viewer size, layout and position on screen
- gtk MDI windows now remember their size and location when toggling workspace types
- Fixes for problems with pinch and scroll gestures with Qt5 backend
- Fixed a bug where scale changes between X and Y axes unexpectedly at extreme zoom levels
- Fixed a bug where cursor could get stuck on a pan cursor
- Added ability to define a cursor for any mode
- Added documented virtual methods to ImageView base class
- Added a workaround for a bug in early versions of Qt5 where excessive mouse motion events accumulate in the event queue
Ver 2.6.0 (2016-11-16)¶
With release 2.6.0 we are moving to a new versioning scheme that makes use of github tagged releases and a “dev” versioning scheme for updates between releases.
This release includes many bugfixes and improvements, new canvas types (XRange and YRange), a Command plugin, WCSMatch plugin, dynamically configurable workspaces, OpenCv acceleration, an HTML5 backend and much much more.
Ver 2.2.20160505170200¶
Ginga has merged the astropy-helpers template. This should make it more compatible management-wise with other astropy-affiliated packages.
Ver 2.2.20150203025858¶
Ginga drawing canvas objects now can specify points and radii in world coordinates degrees and sexigesimal notation.
- default is still data coordinates
- can play with this from Drawing plugin in reference viewer
Ver 2.1.20141203011503¶
Major updates to the drawing features of ginga:
- new canvas types including ellipses, boxes, triangles, paths, images
- objects are editable: press ‘b’ to go into edit mode to select and manipulate objects graphically (NOTE: ‘b’ binding is considered experimental for now–editing interface is still evolving)
- editing: scale, rotate, move; change: fill, alpha transparency, etc.
- editing features available in all versions of the widget
- updated Drawing plugin of reference viewer to make use of all this
Ver 2.0.20140905210415¶
Updates to the core display and bindings classes:
- improvements to interactive rotation command–now resume rotation from current value and direction is relative to horizontal motion of mouse
- most keyboard modes are now locking and not oneshot (press to turn on, press again (or hit escape) to turn off
- additional mouse button functionality in modes (see quick reference)
- some changes to default keyboard bindings (see quick reference)
- changes to auto cuts parameters always result in a new autocut being done (instead of having to explicity perform the autocut)–users seem to expect this
- autocenter preference changed from True/False to on/override/off
Reference viewer only: new global plugin “Toolbar” provides GUI buttons for many operations that previously had only keyboard bindings
Ver 2.0.20140811184717¶
Codebase has been refactored to work with python3 via the “six” module. Tests can now be run with py.test as well as nosetest.
Ver 2.0.20140626204441¶
Support has been added for image overlays. It’s now possible to overlay RGB images on top of the canvas. The images scale, transform and rotate wrt the canvas.
Ver 2.0.20140520035237¶
Auto cut levels algorithms have been updated. “zscale” has been reinforced by using the module from the “numdisplay” package, which does a fair sight closer to IRAF than the previous one Ginga was using. Also, the algorithm “median” (median filtering) makes a comeback. It’s now fast enough to include and produces more usable results.
Ver 2.0.20140417032430¶
New interactive command to orient the image by WCS to North=Up. The default binding to ‘o’ creates left-handed orientation (‘O’ for right-handed). Added a command to rotate the image in 90 deg increments. Default binding to ‘e’ rotates by 90 deg (‘E’ for -90 deg).
Ver 2.0.20140412025038¶
Major update for scale (mapping) algorithms
The scale mapping algorithms (for mapping data values during rendering) havebeen completely refactored. They are now separated from the RGBMap class and are pluggable. Furthermore I have redone them modeled after the ds9 algorithms.
There are now eight algorithms available: linear, log, power, sqrt, squared, asinh, sinh, histeq. You can choose the mapping from the Preferences plugin or cycle through them using the binding to the ‘s’ key (Use ‘S’ to reset to linear). There is also a mouse wheel mapping than can be assigned to this function if you customize your bindings. It is not enabled by default.
The Preferences plugin has been updated to make the function a little clearer, since there was some confusion also with the intensity map feature that is also part of the final color mapping process.
Ver 2.0.20140114070809¶
- The SAMP plugin has been updated to work with the new astropy.vo.samp module.
- The Catalogs plugin has been updated to allow the user to define the radius of the conesearch or image search by drawing a circle (as well as the previous option–a rectangle).
Ver 2.0.20131218034517¶
The user interface mapping just got a bit easier to use. Ginga now provides a way to do most UI remapping just by placing a simple config file in your ~/.ginga directory. An example for ds9 users is in the new “examples” folder.
Many simple examples were moved out of “scripts” and stored under subdirectories (by GUI toolkit) in “examples”.
Ver 2.0.20131201230846¶
Ginga gets trackpad gestures! The Qt rendering class gets support for pinch and pan gestures:
- The pinch/rotate gesture works as expected on a Mac trackpad
- The pan gesture is not a two-finger pan but a “non-standard”, Qt-specific one-finger pan. These are experimental for now, but are enabled by default in this release.
Also in this release there has been a lot of updates to the documentation. The developer and internals sections in particular have a lot of new material.
Ver 2.0.20131030190529¶
The great renaming
I really dislike it when developers do this, so it pains me to do it now, but I have performed a mass renaming of classes. FitsImage ended up being the View in the MVC way of doing things, yet it shared the same naming style as the model classes AstroImage and PythonImage. This would have been the source of endless confusion to developers down the road. Also, PythonImage needed to get renamed to something more akin to what it actually represents.
So the renaming went like this:
- FitsImage -> ImageView
- FitsImage{XYZ} -> ImageView{XYZ}
- PythonImage -> RGBImage
So we have:
- M: BaseImage, AstroImage, RGBImage
- V: ImageView{XYZ}
- C: Bindings, BindMap
I did this in the brand new 2.0 version so at least devs have a heads up that things will not be backward compatible.
And I apologize in advance for any renaming and support issues this may cause for you. Fire up your editor of choice and do a query/replace of “FitsImage” with “ImageView” and you should be good to go.
Ver 1.5-20131022230350¶
Ginga gets a Matplotlib backend!
Ginga can now render to any Matplotlib FigureCanvas. The performance using this backend is not as fast as the others, but it is acceptable and opens up huge opportunities for overplotting.
See scripts/example{1,2,3,4,5}_mpl.py
Also merges in bug fixes for recent changes to astropy, and support for other python WCS packages such as kapteyn and astLib.
Ver 1.5-20130923184124¶
Efficiency improvements¶
Efforts to improve speed of entire rendering pipeline and widget specific redrawing
- Decent improvements, Ginga can now render HD video (no sound) at 30 FPS on older hardware (see scripts/example1_video.py). This translates to a slightly speedier feel overall for many operations viewing regular scientific files.
- Fixed a bug that gave an error message of Callback.py:83 (make_callback) | Error making callback ‘field-info’: ‘Readout’ object has no attribute ‘fitsimage’
- Version bump
Ver 1.4.20130718005402¶
New Agg backend¶
There is now an Agg rendering version of the ImageView object.
- uses the python “aggdraw” module for drawing; get it here –> https://github.com/ejeschke/aggdraw
- this will make it easy to support all kinds of surfaces because the graphics drawing code does not have to be replicated for each toolkit
- see example code in /scripts/example1_agg_gtk.py
- currently not needed for Gtk, Qt versions of the object
New Tk backend¶
There is now a Tk rendering version of the ImageView object.
- see ginga.tkw.ImageViewTk
- renders on a Tk canvas
- see example code in /scripts/example{1,2}_tk.py
- you will need the aggdraw module (see above) to use it
AutoCuts¶
- the ginga.AutoCuts module has been refactored into individual classes for each algorithm
- The Preferences plugin for ginga now exposes all of the parameters
- used for each cut levels algorithm and will save them
Etc¶
- additions to the manual (still incomplete, but coming along)
- lots of docstrings for methods added (sphinx API doc coming)
- many colors added to the color drawing example programs
- WhatsNew.txt file added
Ginga Quick Reference¶
Main image window¶
These keyboard and mouse operations are available when the main image window has the focus.
Mode control commands¶
About modes¶
Certain keystrokes invoke a mode—modes are usually indicated by the mode indicator: a small black rectangle with the mode name in one corner of the view. In a mode, there are usually some special key, cursor, and scroll bindings that override some of the default ones.
Modes additionally have a mode type which can be set to one of the following:
held
: mode is active while the activating key is held downoneshot
: mode is released by initiating and finishing a cursor drag or whenEsc
is pressed, if no cursor drag is performedlocked
: mode is locked until the mode key is pressed again (orEsc
)softlock
: mode is locked until another mode key is pressed (orEsc
)
By default, most modes are activated in “oneshot” type, unless the mode lock is toggled. The mode type is indicated in the brackets after the mode name in the mode indicator. The following keys are important for initiating a mode:
Commmand | Description |
---|---|
Space | Enter “meta” mode. Next keystroke will trigger a particular mode. |
Esc | Exit any mode. Does not toggle the lock. |
l | Toggle the soft lock to the current mode or any future modes. |
L | Toggle the normal lock to the current mode or any future modes. |
“meta” mode¶
Most modes are defined so that they are invoked from a special intermediate mode called “meta”. In that case a two-key sequence is required to enter the mode: pressing the key that invokes “meta” and then pressing the key that invokes the desired mode. The following table shows the modes that can be triggered from meta mode.
Commmand | Description |
---|---|
Space | Exit/Enter “meta” mode. |
b | Enter draw mode (canvas must be enabled to draw). |
q | Enter pan mode. |
w | Enter freepan mode. |
r | Enter rotate mode. |
t | Enter contrast mode. |
y | Enter cmap (color map) mode. |
s | Enter cuts mode. |
d | Enter dist (distribution) mode. |
Note
For modes initiated from meta mode, the locked and softlock
mode types work the same way, which is slightly different
from that described above: you press the meta mode key to
switch back to meta mode, from which you can enter another
mode by pressing its key. You can always press Esc
in any
mode (including meta mode) to exit the mode.
Panning and zooming commands¶
Commmand | Description |
---|---|
Scroll wheel turned | Zoom in or out. |
Shift + scroll wheel | Zoom while keeping location under the cursor. |
Ctrl + scroll wheel turned | Pan in direction of scroll. |
Digit (1234567890) | Zoom image to zoom steps 1, 2, …, 9, 10. |
Shift + Digit | Zoom image to zoom steps -1, -2, …, -9, -10. |
Backquote (`) | Zoom image to fit window and center it. |
Minus, Underscore (-, _) | Zoom out. |
Equals, Plus (=, +) | Zoom in. |
Middle (scroll) button click | Set pan position (under cursor). |
p | Set pan position (under cursor) for zooming. |
Shift + left-click | Set pan position for zooming. |
Shift + arrow key | Move pan position 1 pixel in that direction. |
c | Set pan position to the center of the image. |
q | Enter Pan mode. |
w | Free Freepan mode. |
Ctrl + left-drag | Proportional pan (press and drag left mouse button. |
slash (/) | Set autocenter for new images to override. |
question (?) | Toggle autocenter for images to on or off. |
apostrophe (‘) | Set autozoom for new images to override. |
double quote (“) | Toggle autozoom for new images to on or off. |
Cut levels and colormap commands¶
Commmand | Description |
---|---|
a | Auto cut levels. |
d | Enter Color Distribution (“dist”) mode. See Dist mode. |
D | Reset color distribution algorithm to “linear”. |
s | Enter Cuts mode. |
t | Enter Contrast mode. |
T | Restore the contrast (via colormap) to its original (unstretched, unshifted) state. |
y | Enter CMap (color map) mode. |
Y | Restore the color map to default (gray). |
I | Invert the color map. |
semicolon (;) | Set autocuts for new images to override. |
colon (:) | Toggle autocuts for new images to on or off. |
Transform commands¶
Commmand | Description |
---|---|
Left bracket ([) | Toggle flip image in X. |
Left brace ({) | Reset to no flip of image in X. |
Right bracket (]) | Toggle flip image in Y. |
Right brace (}) | Reset to no flip image in Y. |
Backslash (\) | Swap X and Y axes. |
Vertical bar (|) | Reset to no swap of X and Y axes. |
r | Enter Rotate mode. |
R | Restore rotation to 0 degrees and additionally undo any flip/swap transformations. |
period (.) | Increment current rotation by 90 degrees. |
comma (,) | Decrement current rotation by 90 degrees. |
o | Orient image by transforms and rotation so that WCS indicates North=Up and East=Left. |
O | Orient image by transforms and rotation so that WCS indicates North=Up and East=Right. |
Pan mode¶
Commmand | Description |
---|---|
left-drag | Pan proportionally to drag. |
middle-click | Set pan position. |
right-drag | Zoom in/out proportionally to L/R drag. |
<Modifier> + arrow key | Pan in direction of arrow key. Adding Ctrl reduces amount, adding Shift reduces more. |
p | Pan to position under cursor. |
z | Save current scale (see below for use). |
backquote (`) | Zoom to fit window and center. |
1 | Pan to cursor and zoom to saved scale level (or 1:1 if no scale level saved). |
c | Set pan position to the center of the image. |
slash (/) | Set autocenter for new images to override. |
question (?) | Toggle autocenter for images to on or off. |
apostrophe (‘) | Set autozoom for new images to override. |
double quote (“) | Toggle autozoom for new images to on or off. |
Freepan mode¶
Commmand | Description |
---|---|
Turn scroll wheel | Zoom while keeping location under the cursor. |
left-click | Set pan position, zoom in a step and warp cursor to pan position (if supported on backend). |
right-click | Set pan position, zoom out a step and warp cursor to pan position (if supported on backend). |
middle-drag | Pans freely over entire image in proportion to cursor position versus window. |
p, z, backquote, 1, c, arrow keys | (Same as for Pan mode.) |
Dist mode¶
Commmand | Description |
---|---|
scroll | Select distribution from linear, log, etc. |
b, up-arrow | Select prev distribution in list. |
n, down-arrow | Select next distribution in list. |
D | Reset color distribution algorithm to “linear”. |
Cuts mode¶
Commmand | Description |
---|---|
left-drag | Interactive cut both low and high levels (vertical cuts low, horizontal cuts high). |
Ctrl + left-drag | Interactive cut low level only (horizontal drag). |
Shift + left-drag | Interactive cut high level only (horizontal drag). |
scroll | Coarse (10%) adjustment in/out. |
Ctrl + scroll | Fine (1%) adjustment in/out. |
a, right-click | Do an auto level to restore cuts. |
S | Set cuts to min/max values. |
A | Set cuts to 0/255 values (for 8bpp RGB images). |
b, up-arrow | Select prev auto cuts algorithm in list. |
n, down-arrow | Select next auto cuts algorithm in list. |
semicolon (;) | Set autocuts for new images to override. |
colon (:) | Toggle autocuts for new images to on or off. |
Contrast mode¶
Commmand | Description |
---|---|
left-drag | Interactive shift/stretch colormap (AKA contrast and bias). L/R controls shift, U/D controls stretch. |
right-click | Restore the contrast (via colormap) to its original (unstretched, unshifted) state. |
T | Restore the contrast (via colormap) to its original (unstretched, unshifted) state. |
Rotate mode¶
Commmand | Description |
---|---|
left-drag | Drag around center of window to rotate image. |
right-click | Restore rotation to 0 degrees (does not reset any flip/swap transformations). |
R | Restore rotation to 0 degrees and additionally undo any flip/swap transformations. |
Left bracket ([) | Toggle flip image in X. |
Left brace ({) | Reset to no flip of image in X. |
Right bracket (]) | Toggle flip image in Y. |
Right brace (}) | Reset to no flip image in Y. |
Backslash (\) | Swap X and Y axes. |
Vertical bar (|) | Reset to no swap of X and Y axes. |
period (.) | Increment current rotation by 90 degrees. |
comma (,) | Decrement current rotation by 90 degrees. |
o | Orient image by transforms and rotation so that WCS indicates North=Up and East=Left. |
O | Orient image by transforms and rotation so that WCS indicates North=Up and East=Right. |
Cmap mode¶
Commmand | Description |
---|---|
scroll | Select color map. |
left-drag | Rotate color map. |
right-click | Unrotate color map. |
b, up-arrow | Select prev color map in list. |
n, down-arrow | Select next color map in list. |
I | Toggle invert color map. |
r | Restore color map to unrotated, uninverted state. |
Ctrl + scroll | Select intensity map. |
j, left-arrow | Select prev intensity map in list. |
k, right-arrow | Select next intensity map in list. |
i | Restore intensity map to “ramp”. |
c | Toggle a color bar overlay on the image. |
Y | Restore the color map to default (‘gray’). |
Autozoom setting¶
The “autozoom” setting can be set to one of the following: “on”, “override”, “once” or “off”. This affects the behavior of the viewer when changing to a new image (when done in the typical way) as follows:
on
: the image will be scaled to fit the windowoverride
: likeon
, except that once the zoom/scale is changed by the user manually it turns the setting tooff
once
: likeon
, except that the setting is turned tooff
after the first imageoff
: an image scaled to the current viewer setting
(In the Reference Viewer, this is set under the “Zoom New” setting in the channel preferences.)
Autocenter setting¶
The “autocenter” setting can be set to one of the following: “on”, “override”, “once” or “off”. This affects the behavior of the viewer when changing to a new image (when done in the typical way) as follows:
on
: the pan position will be set to the center of the imageoverride
: likeon
, except that once the pan position is changed by the user manually it turns the setting tooff
once
: likeon
, except that the setting is turned tooff
after the first imageoff
: the pan position is taken from the current viewer setting
(In the Reference Viewer, this is set under the “Center New” setting in the channel preferences.)
Autocuts setting¶
The “autocuts” setting can be set to one of following: “on”, “override”, “once” or “off”. This affects the behavior of the viewer when changing to a new image (when done in the typical way) as follows:
on
: the cut levels for the image will be calculated and set according to the autocuts algorithm settingoverride
: likeon
, except that once the cut levels are changed by the user manually it turns the setting tooff
once
: likeon
, except that the setting is turned tooff
after the first imageoff
: the cut levels are applied from the current viewer setting
(In the ref:Reference Viewer
, this is set under the “Cut New” setting in the
channel preferences.)
Reference Viewer Only¶
Commmand | Description |
---|---|
H | Raise Header tab. |
Z | Raise Zoom tab. |
D | Raise Dialogs tab. |
C | Raise Contents tab. |
less than (<) | Toggle collapse left pane. |
greater than (>) | Toggle collapse right pane. |
f | Toggle full screen. |
F | Panoramic full screen. |
m | Maximize window. |
J | Cycle workspace type (tabs/mdi/stack/grid). Note that “mdi” type is not supported on all platforms. |
k | Add a channel with a generic name. |
Left, Right (arrow keys) | Previous/Next channel. |
Up, Down (arrow keys) | Previous/Next image in channel. |
Note
If there are one or more plugins active, additional mouse or keyboard bindings may be present. In general, the left mouse button is used to select, pick or move, and the right mouse button is used to draw a shape for the operation.
On the Mac, Ctrl + mouse button can also be used to draw or right-click. You can also invoke draw mode as described above in the section on modes.
The Ginga FAQ¶
Platforms¶
Does Ginga run on Mac/Windows/Linux/XYZ?¶
Ginga is written entirely in the Python programming language, and uses only supporting Python packages. As long as a platform supports Python and the necessary packages, it can run some version of Ginga. On recent Linux, Mac and Windows versions, all of these packages are available.
Does Ginga work with Python 3?¶
Yes. Just install with Python 3. Of course, you need all the supporting modules for Python 3 (NumPy, SciPy, Qt 5, etc.)
Toolkits¶
What GUI toolkit does Ginga use?¶
It depends what exactly you want to run. Ginga is both a toolkit for building viewers and also includes a “reference viewer”. The example programs currently support Qt, GTK, Tk, matplotlib and web browser via HTML5 canvas. Some other toolkits are being worked on and may be partially supported.
The full reference viewer currently supports Qt and Gtk. The difference is explained here, in Section Developing with Ginga.
Can Ginga work with PyQt5?¶
Yes.
Can Ginga work with Gtk3?¶
Yes, although the performance is not on par with Gtk2 yet. Cairo for Python 3 still lacks the important ImageSurface.create_for_data() API call, so we have to use a workaround. Detailed instructions can be found in Section Detailed Installation Instructions for Ginga.
Control Bindings¶
Can I get DS9-like user interface mappings?¶
Save the file called bindings.cfg.ds9 and drop it in your $HOME/.ginga folder as “bindings.cfg”. Then restart Ginga.
Can I customize the user interface mappings?¶
Yes. There is more information in the Rebinding Controls section.
Where can I find a quick reference of the bindings?¶
See Section Ginga Quick Reference.
Miscellaneous¶
Does Ginga work with SAMP?¶
Yes. See Section SAMP Control.
When are you going to add the XYZ feature that DS9 has?¶
Maybe never. The Ginga package design goal was never to replace DS9, but to provide a full featured Python FITS widget that we could use to build directly in Python. This is clearly seen if you look at the example programs in examples//example.py. The idea was to make it easy for someone to build any kind of custom viewer by having a full-featured widget to build on.
That said, we did write a reference viewer because we needed something with many of the convenience features of a modern FITS viewer. DS9 is almost the size of a small OS, however, and I’m not sure it is wise to try to match it feature for feature. Instead, since Ginga is plugin-based, you can write plugins to give you the features you need. DS9 is a “everything including kitchen sink” kind of viewer, whereas ginga reference viewer is more like a “take what you need from the pantry and whip it up” type viewer.
Please send a pull request!
Can I get Ginga reference viewer to save its size and position?¶
Yes. Add the line “save_layout = True” to your ~/.ginga/general.cfg
If the file does not exist, create it, or copy the one from ginga/examples/configs/general.cfg.
World Coordinate System¶
What library are you using for WCS?¶
We are lucky to have several possible choices for a Python WCS package compatible with Ginga: AstLib, Kapteyn, Starlink and Astropy WCS.
Kapteyn and Astropy wrap Mark Calabretta’s “WCSLIB”, astLib wraps Jessica Mink’s “wcstools”, and I’m not sure what Starlink uses. Note that Astlib and starlink require pyfits (or Astropy) to be installed in order to create a WCS object from a FITS header.
To force the use of a particular one add this to your “general.cfg” in $HOME/.ginga:
WCSpkg = ‘package’
Replace ‘package’ with one of {‘Astropy’, ‘Kapteyn’, ‘Starlink’ or ‘astlib’, ‘choose’}. If you pick ‘choose’ Ginga will try to pick one for you.
How easy is it for Ginga to support a custom WCS?¶
Pretty easy. See Section I want to use my own World Coordinate System!.
I/O and File Formats¶
What library are you using for FITS I/O?¶
There are two possible choices for a Python FITS file reading package compatible with Ginga: Astropy FITS and fitsio. Both are originally based on the CFITSIO library (although Astropy’s version uses very little of it any more, while fitsio is still tracking the current version).
To force the use of a particular one add this to your “general.cfg” in $HOME/.ginga:
FITSpkg = ‘package’
Replace ‘package’ with one of {‘Astropy’, ‘fitsio’, ‘choose’}. If you pick ‘choose’, Ginga will try to pick one for you.
How easy is it for Ginga to support a new file formats besides FITS?¶
Pretty easy. See Section I want to use my own file storage format, not FITS!.
Problems Displaying Images¶
Nothing changes in the image when I change settings under “Preferences”.
Note
The Preferences plugin sets the preferences on a per-channel basis. Make sure the channel you are looking at has the same name as the prefix for the preferences. For example: “Image” and “Image: Preferences” or “Image1” and “Image1: Preferences”.
The preferences for a given channel are copied from the default “Image” channel until they are explicitly set and saved using this plugin. So if you want preferences that follow around from channel to channel, save them as preferences for “Image” and any new channels created will get those as well, unless you have saved different ones under those channel names.
Nothing changes in the image when I change the “Auto Cuts” settings under Preferences. I’ve checked that I’m adjusting preferences for the same channel that I’m viewing.
Note
What is the setting for “Cut New” under the New Images section in Preferences for this channel?
If that setting is “Off” then you have elected not to have Ginga apply Auto Levels when an image is loaded in that channel. Press ‘a’ in the image window to force an auto cut levels–it will use the new settings.
No image shows in the display, and I get an error in the terminal about histogram and keyword “density”.
Note
You need a slightly newer version of NumPy.
I recommend getting at least NumPy>1.9.
The Ginga Viewer and Toolkit Manual¶
銀河
Ginga is a toolkit for building viewers for scientific data in Python, particularly astronomical data. It also includes a reference viewer for viewing FITS (Flexible Image Transport System) files.
The Ginga viewer is based on an image display widget that supports:
- Zooming and panning
- Color and intensity mapping
- A choice of several automatic cut levels algorithms, and
- Canvases for plotting scalable geometric forms.
In addition to the image display widget, the Ginga viewer provides a flexible plugin framework for extending the viewer with many different features.
A relatively complete set of standard plugins is provided for features that we expect from a modern viewer: panning and zooming windows, star catalog access, cuts, star pick/fwhm, and thumbnails.
Introduction¶
About¶
Ginga is a toolkit designed for building viewers for scientific image data in Python, visualizing 2D pixel data in numpy arrays. The Ginga toolkit can view astronomical data such as contained in files based on the FITS (Flexible Image Transport System) file format.
The Ginga toolkit is written and maintained by software engineers at the Subaru Telescope, National Astronomical Observatory of Japan. The code is released as open-source under a BSD license and maintained at http://ejeschke.github.io/ginga/
Features¶
The Ginga toolkit centers around an image display widget that supports zooming and panning, color and intensity mapping, a choice of several automatic cut levels algorithms, and canvases for plotting scalable geometric forms.
In addition to this widget, a general purpose reference FITS viewer is provided, based on a plugin framework. A relatively complete set of standard plugins are provided for features that we expect from a modern FITS viewer: panning and zooming windows, star catalog access, cuts, star pick/fwhm, thumbnails, etc.
Core Concepts¶
The Ginga reference viewer operation is organized around several basic concepts: workspaces, channels, plugins, modes. Understanding these will greatly aid in using and modifying Ginga.
Workspaces¶
Ginga has a flexible workspace layout algorithm that allows customizing the appearance of the program. The majority of the Ginga interface is constructed as hierarchical series of horizontally or vertically-adjustable panels. Each panel is eventually a workspace. Each workspace is implemented by a GUI toolkit container widget such as a notebook widget, where each item in the workspace is identified by a tab.
However, workspaces can also take the form of a stack (like a tabbed widget but with no tabs showing), or a Multiple Document Interface (MDI) style container (subwindow desktop-style layout), or a grid layout.
Workspaces typically contain either a channel viewer, a plugin UI or another workspace. In its default configuration, Ginga starts up with a single row (horizontal) panel of three workspaces, as shown in the image below.

The panel is sandwiched vertically between a menu bar and a status bar. The left workspace is further subdivided into an upper and lower, and there are also thin horizontal workspaces below the central workspace. The central workspace is mainly used for viewers, while the other workspaces hold the plugin UIs.
The initial layout of the workspaces is controlled by a table in the Ginga startup script (see Customizing Ginga). By changing this table the layout can be substantially altered.
Note
Note that workspaces may be implemented by several types of container widgets such as fixed position subwindows, sliding panes, MDI-style subwindows, etc.
A notebook widget is simply the most common (default) case.
Some workspaces can be converted dynamically between the different types. If the workspace contains a workspace toolbar, the workspace type selector can be used to change the type:

In the example shown below, we show a cutout of the main workspace (tabbed), which has two tabs: a channel viewer (Image) and a second workspace (ws1).
The ws1 workspace is configured as type MDI and has two windows: a viewer (Image0) and a third workspace (ws2). The third workspace contains a grid of four viewers. Depending on the the support of the back end widget set, tabs can be dragged between workspaces (or out onto the desktop if you are using the Gtk widget set), forming a new, detached workspace.

Channels¶
Another core tenet of Ginga is that that image content is organized into channels. A channel can be thought of as simply a named category under which similar types of images might be organized. A few examples are:
- A channel for each type of instrument at a telescope
- A channel for each observation or calibration target
- Channels based on time or program or proposal identifier
If no channels are specified when Ginga starts up it simply creates a
default channel named Image. New channels can be created using the
Channel/Add channel menu item. Pressing the +
button in the
workspace menu also adds a new channel using a default name.
A channel always has an image viewer associated with it, and may additionally have a table viewer. The viewer is what you see in the active window representing that channel.

In the workspace toolbar, pressing -
removes the currently selected
channel, while pressing the up or down arrows moves between images
in the selected channel.
In the case where multiple channels are present, they are usually visually organized as tabs, windows, and grid within the central workspace of the interface (as shown in the figure above) depending on how the workspace is configured. To change channels you simply click on the tab of the channel you want to view, or press the left or right arrow buttons in the workspace menu. There is also a channel selector in the plugin manager toolbar at the bottom of the center pane. You can change the channel by using the drop-down menu or by simply scrolling the mouse wheel on the control.

Channels occupy a flat namespace, i.e., there is no hierarchy in channel names.
By default, images are loaded into the same channel you are currently viewing (unless your viewer has been customized to load images according to special rules).
Note
To keep images organized, simply change to the desired channel before opening a new image, or drag the image to the desired channel viewer.
Many preferences in Ginga are set on a per-channel basis. Some per-channel settings include:
- Color distribution algorithm
- Color map
- Intensity map
- Cut levels
- Auto cut levels algorihm
- Transforms (flip, swap)
- Rotation
- WCS display coordinates
- Zoom algorithm
- Scale
- Interpolation type
- Pan position
A new channel will generally inherit the settings for the generic Image channel until new preferences are defined and saved.
If you create a new channel and had previously saved preferences for a channel with that name, the new channel will adopt those preferences. Thus you can set up channels configured for certain telescopes or for types of data and easily reuse them in later sessions.
Another idea embodied in the channel concept is that the user should not have to manage memory usage too explicitly. Each channel has a setting that limits how many images it should keep in memory. If the number of images exceeds the limit then Ginga will remove older images and load them back in as needed without user intervention.
Plugins¶
Almost all functionality in Ginga is achieved through the use of a plugin architecture.
Plugins are quasi-independent Python modules that can optionally have a Graphical User Interface. If they do have a GUI, it can be loaded at program startup or be dynamically opened and closed during the duration of the viewer’s execution.
Plugins can be global, in which case they don’t have any particular affiliation with a channel and are generally invoked singularly, or local in which case they can be invoked in multiple instances–one per channel.
In this documentation we will also use the word operation to describe activating a plugin. For example, a “pick” operation would use the Pick plugin.
Plugins are written as encapsulated Python modules that are loaded dynamically when Ginga starts. There is an API for programming plugins (see Developing with Ginga).
The plugins are each described in more detail in Plugins.
For those plugins that do have a visible interface, the Ginga startup script can map them to certain workspaces. By manipulating this mapping (and manipulating the workspace layout) we can customize to achieve flexible layouts.
In the image at the top, the left workspace contains three global plugin UIs: the Info, Header and Zoom panes. The middle workspace holds all the viewing panes for each channel. The right workspace has the Dialogs, Thumbs, Contents and Error panes. The operation of these plugins is described in Plugins.
Modes¶
Ginga provides a number of default bindings for key and pointer actions. However, there are too many different actions to bind to a limited set of keys and pointer buttons. Modes allow us to overcome this limitation.
Modes are a mechanism that allow Ginga to accommodate many key and pointer bindings for a large number of operations.
Modes are set on a per-channel basis. Pressing a particular mode key in a channel viewer puts that viewer into that mode.
When in a mode, the behavior is that some special key, and the cursor and scroll bindings will override the default ones. An adjacent viewer for a different channel may be in a different mode, or no mode.
Note
If a mode does not override a particular binding, the default one will still be active.
Modes have an associated mode type which can be set to one of:
held
: The mode is active while the activating key is held downoneshot
: The mode is released by initiating and finishing a cursor drag, or whenEsc
is pressed, if no cursor drag is performedlocked
: The mode is locked until the mode key is pressed again (orEsc
)softlock
: The mode is locked until another mode key is pressed (orEsc
)
By default most modes are activated in “oneshot” type, unless the mode
lock is toggled. The mode lock is typically toggled in and out of
softlock by the l
(lowercase letter l) key and “locked” with L
.
Modes are usually indicated by a small black rectangle with the mode name in one corner of the viewer, usually in the lower right corner of the viewer.
Note
When the lock is active it is signified by an additional “[SL]” (softlock) or “[L]” (locked) appearing in the mode indicator.

In the above figure, you can see the mode indicator showing that the viewer is in “contrast” mode, with the softlock on. The same information can be seen in the Toolbar plugin. On the Toolbar plugin you can click to set the mode and toggle the lock on/off.
General Operation¶
This chapter describes the general manipulations of images using Ginga.
For the most part these manipulations apply both to Ginga ImageView classes that can be embedded in a Python application, as well as to the reference viewer distributed with Ginga.
Note
In cases where we are referring to something that is only available in the reference viewer these will be prefixed by the notation [RV]
.
Keyboard and mouse operations¶
In this documentation we will use the following terms to describe the operations performed with the mouse:
- Click or Left-click means to click on an item with the left mouse button;
- Drag or Left-drag means to click, hold and drag with the left mouse button;
- Scroll means to scroll with the middle mouse wheel or a trackpad/touchpad;
- Scroll-click means to click with the middle mouse wheel/button;
- Scroll-drag means to click, hold and drag with the middle mouse wheel/button;
- Right-click means to click on an item with the right mouse button;
- Right-drag means to click, hold and drag with the right mouse button.
Mouse operations are also modified by the keyboard buttons Shift, and Ctrl.
Shift-click means to press and hold the Shift key while clicking with left mouse button. Shift-right-click is the same using the right mouse button, etc.
Some mouse-controlled operations in Ginga are initiated by a key stroke.
In these cases the key is pressed and released (not held), and then the
mouse is used to control the operation. Such operations are either
terminated by releasing the mouse button (if the operation employs a
drag), and clicking on the image or by pressing the Esc
key (if not a
drag operation).
Note
We describe the standard key and mouse bindings here. However these bindings can be changed completely by the user. For more information on changing the bindings, see Section Rebinding Controls.
Loading a FITS image file¶
There are several ways to load a file into Ginga:
- Ginga supports drag-and-drop in a typical desktop environment, so you can simply drag and drop files from a graphical file manager such as the Mac Finder or Linux Nautilus onto a Ginga viewing pane to load an image.
[RV]
Another way is to invoke theFBrowser
plugin, which opens in the Dialogs tab. The plugin pane shows file and folder contents and allows navigation up and down the filesystem hierarchy by double-clicking on folder names. Simply navigate to the location of the FITS file and double-click on the file name to load it, or drag it onto the image pane.[RV]
Use the Load Image entry from theFile
menu on the main menu bar at the top of the window. This opens a standard file dialog popup window where you can navigate to the file you wish to load.
Zooming and panning¶
The display object used throughout most of the Ginga panels has built-in support for zooming and panning. The Ginga Quick Reference has the complete listing of default keyboard and mouse bindings.
For example:
- The scroll wheel of the mouse can be used to zoom in and out, along with the “+” and “-” keys.
- The backquote key will fit the image to the window.
- Digit keys (1, 2, etc.) will zoom in to the corresponding zoom level, while holding Shift and pressing a zoom key zooms out to the corresponding level.
When zoomed in, panning is enabled. Panning takes two forms:
- Proportional panning or “drag panning” pans the image in direct proportion to the distance the mouse is moved. You can think of this as dragging the image canvas in the direction you want to move it under the window portal. To utilize a proportional pan, Ctrl-drag the canvas, or press Space followed by “q” to go into pan mode, and then drag the canvas.
2) Free panning allows scrolling around the entire image by mapping the entire image boundaries to the window boundaries. For example, moving the mouse to the upper right-hand corner of the window will pan to the upper right hand corner of the image, etc. You can think of this mode as moving the window portal around over the canvas. To initiate a free pan, press Space followed by “w” to enter “freepan” mode and then Scroll-drag to move around the window.
[RV]
The Pan
plugin (usually embedded under the Info tab) shows the
outline of the current pan position as a rectangle on a small version of
the whole image. Dragging this outline will also pan the image in the main
window. You can also click anywhere in the Pan window to set the pan
position, or right drag an outline to roughly specify the region to zoom
and pan to together.
Pan position¶
Panning in Ginga is based on an (X, Y) coordinate known as the pan position. The pan position determines what Ginga will try to keep in the middle of the window as the image is zoomed.
When zoomed out, you can Shift-click on a particular point in the image (or press the “p” key while hovering over a spot), setting the pan position. Zooming afterward will keep the pan position in the center of the window. To reset the pan position to the center of the image, press ‘c’.
Ginga has an auto zoom feature to automatically fit newly loaded images to the window, similar to what happens when the backquote key is pressed. See “Zoom Preferences” section in Preferences for details.
How Ginga maps an image to color¶
The process of mapping a monochrome science image to color in Ginga involves four steps, in order:
- Applying the cut levels, which scales all values in the image to a specified range [1],
- Applying a color distribution algorithm, which distributes values within that range to indexes into a color map table, and
- Applying a shift map, which shifts and stretches or shrinks the values according to the user’s contrast adjustment [2], and finally,
- Applying an intensity map and color map to map the final output to RGB pixel values.
Setting cut levels¶
When visualizing pixel data with an arbitrary value range, the range is first scaled into a limited range based on the low and high cut levels defined in the view object. These cut levels can be set manually by the user or automatically based on an algorithm. This eliminates the effect of outlier pixel/flux values.
There are several ways to manually set the cut levels:
- Pressing Space followed by “s” key will put the viewer into “cuts” mode. Here you can invoke a dual (high and low) interactive cut levels. Click and drag the mouse horizontally in the window to interactively set the high level, and vertically to set the low level; and when you reach the desired levels, release the mouse button. Scrolling the mouse wheel in this mode will also change the low and high cut levels simultaneously–toward or away from each other, resulting in lower or higher contrast.
[RV]
The “Cut Low” and “Cut High” boxes in the Info plugin panel can be used. The current values are shown to the left; simply type a new value in the corresponding box and press Enter or click the “Cut Levels” button below. Cut values can also be set from the “Histogram” plugin.
Ginga can algorithmically estimate and set the cut levels–called auto (cut) levels. To activate the auto levels:
- Press the (“a”) key when the viewing widget has the focus.
[RV]
Click the “Auto Levels” button in the Info plugin panel.
[RV]
The auto cut levels feature is controlled by several factors in the
preferences, including the choice of algorithm and some parameters to
the algorithm. See “Auto Cuts Preferences” section in
Preferences for details.
Ginga can also automatically set the cut levels for new images displayed in the view. See “New Image Preferences” section in Preferences for details.
Ginga supports a number of color scale distribution algorithms, including:
- “linear”,
- “log”,
- “power”,
- “sqrt”,
- “squared”,
- “asinh”,
- “sinh”, and
- “histeq” (histogram equalization).
These can be sampled with the current color and intensity maps by pressing Space followed by “d” key to go into “dist” mode, and then scrolling the mouse, pressing the up/down keys, or the “b” and “n” keys.
Press Esc to exit the “dist” mode.
To reset to the default (“linear”) map, press “D” (capital D).
[RV]
The color scale distribution algorithms can also be set from the
Preferences
plugin, under the heading “Color Distribution”.
The value range can be shifted and stretched or squeezed to alter the visibility and contrast of the image. This is sometimes called a “bias/contrast” adjustment in other viewers.
In most Ginga configurations the shift map adjustment is bound to the Ctrl-right drag combination (hold Ctrl down and right drag). Dragging left/right shifts the map, and up/down stretches or shrinks the map.
You can also press “t” to enter “contrast” mode, where you can then use a regular Left-drag.
The color and intensity maps control the final mapping of colors to the values in the image.
Intensity maps are available to produce a final permutation on the value range of the image before color is applied. The function of these largely overlaps the function of the color distribution algorithm, so most users will typically use either one or the other, but not both.
For example, the intensity map “log” essentially applies a log distribution to the range. If this has already been done with the color distribution “log”, the effect is doubly applied.
Possible values for the intensity map are:
- “equa”,
- “expo”,
- “gamma”,
- “jigsaw”,
- “lasritt”,
- “log”,
- “neg”,
- “neglog”,
- “null”, “ramp” and
- “stairs”.
“ramp” is the default value.
While in “cmap” mode (described below), the “j” and “k” keys can be used to cycle through the intensity maps.
To change color maps from the keyboard shortcuts, press Space followed by “y” to go into “cmap” mode. While in “cmap” mode you can change color maps by scrolling the mouse, pressing the up/down keys, or the “b” and “n” keys.
While in “cmap” mode, pressing “I” (uppercase) will invert the current color map. Press Esc to exit cmap mode.
Note
Setting a new color map will cancel the color map inversion. Some color maps are available in both regular and inverted forms. If selecting an already inverted (aka “reversed”) color map it is not necessary to explicitly invert it.
While many color maps are available built in, users can also define their own color maps or use matplotlib color maps, if the matplotlib
package is installed.
[RV]
The ColorMapPicker
global plugin is useful you to visualize all of the colormaps and apply one to the currently active channel viewer.
Transforming the image view¶
Ginga provides several controls for transforming the image view. The image can be flipped in the X axis (“horizontally”), Y axis (“vertically”), have the X and Y axes swapped, or any combination thereof. These operations can be done by keyboard shortcuts:
- Press “[” to flip in X, “{” to restore.
- Press “]” to flip in Y, “}” to restore.
- Press “” to swap X and Y axes, “|” to restore.
The image can also be rotated in arbitrary amounts.
An interactive rotate operation can be initiated by pressing Space follwed by “r” in the image and then dragging the mouse horizontally left or right to set the angle. Press “R” (Shift+R) to restore the angle to 0 (unrotated).
Note
It is less computationally-intensive to rotate the image using the simple transforms (flip, swap) than by the rotation feature. Rotation may slow down some viewing operations.
[RV]
The image can also be transformed in the channel
Preferences (see “Transform Preferences”) which has
checkboxes for flip X, flip Y, swap XY and a box for rotation by degrees.
Footnotes
[1] | Some image viewers or graphing programs use the term “limits” for what we call “cut levels”. |
[2] | What some programs call a “contrast/bias” adjustment. |
Ginga Canvas Graphics¶
This chapter describes the basic architecture of Ginga’s canvas-viewer-renderer model, and describes how to do graphics operations on canvases.
Canvases and Canvas Objects¶
Ginga’s canvas is based on the DrawingCanvas
class.
On the canvas can be placed a number of different kinds of
canvas objects, including many geometric shapes. The set of canvas
objects includes:
Text
: a piece of text having a single point coordinate.Polygon
: a closed polygon defined by N points.Path
: an open polygon defined by N points.Box
: a rectangular shape defined by a single center point, two radii and a rotation angle.Ellipse
: an elliptical shape defined by a single center point, two radii and a rotation angle.Triangle
: an equilateral triangular shape defined by a single center point, two radii and a rotation angle.Circle
: a circular shape defined by a center point and a radius.Point
: a marker for a point defined by a single point and a radius for the “arms”.Rectangle
– a rectangular shape defined by two points.Line
– a line defined by two points.RightTriangle
– a right triangle defined by two points.Compass
– a compass defined by a point and a radius.Ruler
– a ruler defined by two points.Crosshair
– a crosshair defined by one point.Annulus
– an annulus defined by one point and two radii.Image
– a raster image anchored by a point.NormImage
– a subclass ofImage
, with rendering done with the aid of a colormap, a color distribution algorithm (linear, log, etc), and defined low and high cut levels.CompoundObject
: a compound object combining a series of other canvas objects.Canvas
: a transparent subcanvas on which items can be placed.DrawingCanvas
: Like aCanvas
, but also can support manual drawing operations initiated in a viewer to create shapes on itself.ColorBar
: a bar with a color range and ticks and value markers to help indicate the mapping of color to the value range of the data.ModeIndicator
: a small rectangular overlay with text indicating that the user has entered a special keyboard/mouse mode.
All canvas objects are subclasses of CanvasObjectBase
and may also
contain mixin classes that define common attributes or behavior. For
example, Line
, Ruler
and RightTriangle
are all subclasses of
the mixin class TwoPointMixin
.
Note
In most general canvas systems you can layer objects in any order. In Ginga there is an optimization of canvas redrawing that merges image bitmaps before updating other kinds of canvas objects. This means that while images can be stacked in any order, effectively you cannot have other objects appear underneath image objects. For most uses of the viewer this is not a big limitation.
Viewers¶
All Ginga viewers are subclasses of ImageViewBase
. These objects
implement a viewport onto a DrawingCanvas
object. Each viewer
contains a handle to a canvas and provides a particular view onto that
canvas defined by:
- dimensions of their viewport (i.e. the height and width of the native widget’s window into which the viewer is rendering),
- scale in X and Y dimensions,
- a pan position linking the center of the viewport to a canvas coordinate,
- a transform consisting of possible flips in X, Y axes and/or swapping of X/Y axes, and
- a rotation.
Two different ImageView
-based viewers can share the same canvas
handle, providing different views into the same canvas. Another typical
arrangement for sharing is where each viewer has a private canvas, and
on each private canvas is placed a shared transparent subcanvas, an
arrangement which allows each viewer to have a mix of private and shared
canvas objects. Another common idiom is to layer multiple
DrawingCanvas
objects to more easily manage multiple collections of
overlaid graphics.
The various subclasses of ImageView
are designed to render into a
different widget set’s “native” canvas using a CanvasRenderer
customized for that target.
Plugins¶
Ginga is written so that most of the functionality of the program is achieved through the use of plugins. This modular approach allows a large degree of flexibility and customization, as well as making overall design and maintenance of the program simpler.
Plugins are divided into two types: global and local. A global plugin has a single instance shared by all channels, while a local plugin creates a unique instance for each channel. If you switch channels, a global plugin will respond to the change by updating itself, while a local plugin will remain unchanged if the channel is switched, because its operation is specific to a given channel. (Ginga’s concept of channels is discussed in Channels.)
This chapter describes the set of plugins that come with Ginga. Those interested in writing their own custom plugins should refer to Writing a Global Plugin or Anatomy of a Local Ginga Plugin.
Global plugins¶
Toolbar¶
Toolbar
provides a set of convenience UI controls for common operations
on viewers.
Plugin Type: Global
Toolbar
is a global plugin. Only one instance can be opened.
Usage
Hovering over an icon on the toolbar should provide you with usage tool tip.
It is customizable using ~/.ginga/plugin_Toolbar.cfg
, where ~
is your HOME directory:
#
# Toolbar plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Toolbar.cfg"
# Accepted value: 'oneshot' or 'locked'
mode_type = 'oneshot'
Pan¶

The Pan
plugin provides a small panning image that gives an overall
“birds-eye” view of the channel image that last had the focus. If the
channel image is zoomed in 2X or greater, then the pan region is shown
graphically in the Pan
image by a rectangle.
Plugin Type: Global
Pan
is a global plugin. Only one instance can be opened.
Usage
The channel image can be panned by clicking and/or dragging to place
the rectangle. Using the right mouse button to drag a rectangle will
force the channel image viewer to try to match the region (taking into
account the differences in the aspect ratio between the drawn rectangle
and the window dimensions). Scrolling in the Pan
image will zoom the
channel image.
The color/intensity map and cut levels of the Pan
image are updated
when they are changed in the corresponding channel image.
The Pan
image also displays the World Coordinate System (WCS) compass, if
valid WCS metadata is present in the FITS HDU being viewed in the
channel.
The Pan
plugin usually appears as a sub-pane under the “Info” tab, next
to the Info
plugin.
It is customizable using ~/.ginga/plugin_Pan.cfg
, where ~
is your HOME directory:
#
# Pan plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Pan.cfg"
# Share a canvas with the channel viewer
use_shared_canvas = False
# color of pan position marker
pan_position_color = 'yellow'
# color of pan rectangle
pan_rectangle_color = 'red'
# color of compass
compass_color = 'skyblue'
# rotate the pan image if the main image is rotated?
rotate_pan_image = True
Info¶

The Info
plugin provides a pane of commonly useful metadata about the
associated channel image. Common information includes some metadata
header values, coordinates, dimensions of the image, minimum and
maximum values, etc. As the cursor is moved around the image, the X, Y,
Value, RA, and DEC values are updated to reflect the value under the cursor.
Plugin Type: Global
Info
is a global plugin. Only one instance can be opened.
Usage
At the bottom of the Info
interface the cut levels controls. Here
the low and high cut levels are shown and can be adjusted. Pressing the
“Auto Levels” button will recalculate cut levels based on the current
auto cut levels algorithm and parameters defined in the channel
preferences.
Below the “Auto Levels” button, the status of the settings for “Cut New”, “Zoom New”, and “Center New” are shown for the currently active channel. These indicate how new images that are added to the channel will be affected by auto cut levels, fitting to the window and panning to the center of the image.
The “Follow New” checkbox controls whether the viewer will automatically display new images added to the channel. The “Raise New” checkbox controls whether an image viewer window is raised when a new image is added. These two controls can be useful, for example, if an external program is adding images to the viewer, and you wish to prevent interruption of your work examining a particular image.
As a global plugin, Info
responds to a change of focus to a new channel
by displaying the metadata from the new channel.
It typically appears under the “Synopsis” tab in the user interface.
Header¶

The Header
plugin provides a listing of the metadata associated with the
image.
Plugin Type: Global
Header
is a global plugin. Only one instance can be opened.
Usage
The Header
plugin shows the FITS keyword metadata from the image.
Initially only the Primary HDU metadata is shown. However, in
conjunction with the MultiDim
plugin, the metadata for other HDUs will be
shown. See MultiDim
for details.
If the “Sortable” checkbox has been checked in the lower left of the UI, then clicking on a column header will sort the table by values in that column, which may be useful for quickly locating a particular keyword.
If the “Include primary header” checkbox toggles the inclusion of the primary HDU keywords or not. This option may be disabled if the image was created with an option not to save the primary header.
It is customizable using ~/.ginga/plugin_Header.cfg
, where ~
is your HOME directory:
#
# Header plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Header.cfg"
# Sort header
sortable = True
# Include primary header in table output
include_primary_header = False
# If True, color every other row in alternating shades to improve
# readability of long tables
color_alternate_rows = True
# Maximum number of rows that will turn off auto column resizing (for speed)
max_rows_for_col_resize = 5000
Zoom¶

The Zoom
plugin shows an enlarged image of a cutout region centered
under the cursor position in the associated channel image. As the
cursor is moved around the image, the zoom image updates to allow close
inspection of the pixels or precise control in conjunction with other
plugin operations.
Plugin Type: Global
Zoom
is a global plugin. Only one instance can be opened.
Usage
The size of the cutout radius can be adjusted by the slider below the zoom image labeled “Zoom Radius”. The default radius is 30 pixels, making a 61x61 zoom image. The magnification can be changed by adjusting the “Zoom Amount” slider.
Two modes of operation are possible – absolute and relative zoom:
- In absolute mode, the zoom amount controls exactly the zoom level shown in the cutout; For example, the channel image may be zoomed into 10X, but the zoom image will only show a 3X image if the zoom amount is set to 3X.
- In relative mode, the zoom amount setting is interpreted as relative to the zoom setting of the channel image. If the zoom amount is set to 3X and the channel image is zoomed to 10X then the zoom image shown will be 13X (10X + 3X). Note that the zoom amount setting can be < 1, so a setting of 1/3X with a 3X zoom in the channel image will produce a 1X zoom image.
The “Refresh Interval” setting controls how quickly the Zoom
plugin
responds to the movement of the cursor in updating the zoom image. The
value is specified in milliseconds.
Tip
Usually setting a small refresh interval improves the overall responsiveness of the zoom image, and the default value of 20 is a reasonable one. You can experiment with the value if the zoom image seems too jerky or out of sync with the mouse movement in the channel image window.
The “Defaults” button restores the default settings of the controls.
It is customizable using ~/.ginga/plugin_Zoom.cfg
, where ~
is your HOME directory:
#
# Zoom plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Zoom.cfg"
# default zoom radius in pixels
zoom_radius = 30
# default zoom level
zoom_amount = 3
# refresh interval (sec)
# NOTE: usually a small delay speeds things up
refresh_interval = 0.02
# rotate the zoom image if the channel image is rotated?
rotate_zoom_image = True
# use a different color map than channel image?
zoom_cmap_name = None
# use a different intensity map than channel image?
zoom_imap_name = None
Thumbs¶

The Thumbs
plugin provides a thumbnail index of all images viewed since
the program was started.
Plugin Type: Global
Thumbs
is a global plugin. Only one instance can be opened.
Usage
By default, Thumbs
appear in cronological viewing history,
with the newest images at the bottom and the oldest at the top.
The sorting can be made alphanumeric by a setting in the
“plugin_Thumbs.cfg” configuration file.
Clicking on a thumbnail navigates you directly to that image in the associated channel. Hovering the cursor over a thumbnail will show a tool tip that contains a couple of useful pieces of metadata from the image.
The “Auto Scroll” checkbox, if checked, will cause the Thumbs
pan to
scroll to the active image.
It is customizable using ~/.ginga/plugin_Thumbs.cfg
, where ~
is your HOME directory:
#
# Thumbs plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Thumbs.cfg"
# If you revisit the same directories frequently
# caching thumbs saves a lot of time when they need to be regenerated
cache_thumbs = False
# cache location-- "local" puts them in a .thumbs subfolder, otherwise
# they are cached in ~/.ginga/thumbs
cache_location = 'local'
# Scroll the pane automatically when new thumbnails arrive
auto_scroll = True
# Keywords to extract and show if we mouse over the thumbnail
tt_keywords = ['OBJECT', 'FRAMEID', 'UT', 'DATE-OBS']
# Mandatory unique image identifier in tooltip
mouseover_name_key = 'NAME'
# How many seconds to wait after an image is altered to begin trying
# to rebuild a matching thumb. Usually a few seconds is good in case
# there is ongoing adjustment of the image
rebuild_wait = 0.5
# Max length of thumb on the long side
thumb_length = 180
# Separation between thumbs in pixels
thumb_hsep = 15
thumb_vsep = 15
# Sort the thumbs alphabetically: 'alpha' or None
sort_order = None
# Thumbnail label length in num of characters (None = no limit)
label_length = 25
# Cut off long label ('left', 'right', or None)
label_cutoff = 'right'
# Option to highlight images that are displayed in channels.
# If set to True this option will only highlight the image that is in the
# channel with the keyboard focus
highlight_tracks_keyboard_focus = True
# Highlighted label colors
label_bg_color = 'lightgreen'
label_font_color = 'white'
label_font_size = 10
# Load visible thumbs in the background to replace placeholder icons
autoload_visible_thumbs = True
# Length of time to wait after scrolling to begin autoloading
autoload_interval = 1.0
# list of attributes to transfer from the channel viewer to the
# thumbnail generator if the channel has an image in it
transfer_attrs = ['transforms', 'cutlevels', 'rgbmap']
Contents¶

The Contents
plugin provides a table of contents-like interface for all
the images viewed since the program was started. Unlike Thumbs
,
Contents
is sorted by channel. The contents also shows some configurable
metadata from the image.
Plugin Type: Global
Contents
is a global plugin. Only one instance can be opened.
Usage
Click on a column heading to sort the table by that column; Click again to sort the other way.
Note
The columns and their values are drawn from the FITS header, if applicable. This can be customized by setting the “columns” parameter in the “plugin_Contents.cfg” settings file.
The active image in the currently focused channel will normally be highlighted. Double-click on an image will force that image to be shown in the associated channel. Single-click on any image to activate the buttons at the bottom of the UI:
- “Display”: Make the image the active image.
- “Move”: Move the image to another channel.
- “Copy”: Copy the image to another channel.
- “Remove”: Remove the image from the channel.
If “Move” or “Copy” is done on an image that has been modified in Ginga
(which would have an entry under ChangeHistory
, if used), the
modification history will be retained as well. Removing an image from
a channel destroys any unsaved changes.
It is customizable using ~/.ginga/plugin_Contents.cfg
, where ~
is your HOME directory:
#
# Contents plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Contents.cfg"
# columns to show from metadata -- NAME and MODIFIED recommended
# format: [(col header, keyword1), ... ]
columns = [ ('Name', 'NAME'), ('Object', 'OBJECT'), ('Filter', 'FILTER01'), ('Date', 'DATE-OBS'), ('Time UT', 'UT'), ('Modified', 'MODIFIED')]
# If set to True, will always expand the tree in Contents when new entries are added
always_expand = True
# Option to highlight images that are displayed in channels.
# If set to True this option will only highlight the image that is in the
# channel with the keyboard focus
highlight_tracks_keyboard_focus = False
# If True, color every other row in alternating shades to improve
# readability of long tables
color_alternate_rows = True
# Highlighted row colors (in addition to bold text)
row_font_color = 'green'
# Maximum number of rows that will turn off auto column resizing (for speed)
max_rows_for_col_resize = 100
Colorbar¶

The Colorbar
plugin shows a colorbar indicating the colormap applied
to the image and showing the example values along the range.
Plugin Type: Global
Colorbar
is a global plugin. Only one instance can be opened.
Usage
Clicking and dragging in the Colorbar
window will shift the colormap
left or right. Scrolling will stretch or shrink the colormap at the
cursor position. Right-clicking will restore the colormap from any
shift or stretch.
If the focus shifts to another channel, the colorbar will be updated to reflect that channel’s colormap and value information.
It is customizable using ~/.ginga/plugin_Colorbar.cfg
, where ~
is your HOME directory:
#
# Colorbar plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Colorbar.cfg"
# Set colorbar height, if default is too big or little
cbar_height = 36
# size of font used in the color bar
fontsize = 10
Cursor¶

The Cursor
plugin displays a summary line of text that changes as the
user moves the cursor around an image. In the standard reference viewer
configuration, it appears as a line containing green text just below the
Colorbar
plugin.
Plugin Type: Global
Cursor
is a global plugin. Only one instance can be opened.
Usage
Cursor
simply tracks the cursor as it moves around an image and displays
information about the pixel coordinates, WCS coordinates (if available)
and the value of the pixel under the cursor.
There is no associated configuration GUI.
Note
Pixel coordinates are affected by the general setting “pixel_coords_offset” which can be set in the “general.cfg” configuration file for ginga. The default is value for this setting is 1.0, which means pixel coordinates are reported from an origin of 1, as per the FITS standard.
It is customizable using ~/.ginga/plugin_Cursor.cfg
, where ~
is your HOME directory:
#
# Cursor plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Cursor.cfg"
share_readout = True
Operations¶
This plugin defines the GUI for managing local plugins, a.k.a., “operations”.
Plugin Type: Global
Operations
is a global plugin. Only one instance can be opened.
Usage
The Operations
plugin acts as a visual interface to the reference viewer
plugin manager. With this plugin, you can change the active channel,
start, stop, or unfocus a local plugin on a channel, and see which local
plugins are running.
Note
By replacing or subclassing this plugin, you can customize the way the reference viewer starts and manages operations.
It is customizable using ~/.ginga/plugin_Operations.cfg
, where ~
is your HOME directory:
#
# Operations plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Operations.cfg"
# Show the change channel drop-down control
show_channel_control = True
# Color to highlight focused plugins in the operations control tray
focuscolor = "lightgreen"
# Change to False to use combobox+button launch approach
use_popup_menu = True
WBrowser¶
Web browser plugin for Ginga.
Plugin Type: Global
WBrowser
is a global plugin. Only one instance can be opened.
Usage
This global plugin is used to browse help pages for Ginga.
When a “Help” button is pressed from a plugin (e.g., Pick
),
Ginga will attempt to download an existing documentation build
from ReadTheDocs for the matching version. If successful,
plugin documentation from that download is displayed.
If not successful or deliberately disabled in “plugin_WBrowser.cfg”,
Ginga will render the plugin’s docstring locally.
It is customizable using ~/.ginga/plugin_WBrowser.cfg
, where ~
is your HOME directory:
#
# WBrowser plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_WBrowser.cfg"
# Set to True to force offline doc browsing, otherwise download from RTD
offline_doc_only = False
ColorMapPicker¶

The ColorMapPicker
plugin is used to graphically browse and select a
colormap for a channel image viewer.
Plugin Type: Global
ColorMapPicker
is a global plugin. Only one instance can be opened.
Usage
Operation of the plugin is very simple: the colormaps are displayed in the form of colorbars and labels in the main view pane of the plugin. Click on any one of the bars to set the colormap of the currently active channel in the viewer.
Change the channel to set the colormap on a different channel.
You can scroll vertically or use the scroll bars to move through the colorbar samples.
Note
When the plugin starts for the first time, it will generate a bitmap RGB image of colorbars and labels corresponding to all the available colormaps. This can take a few seconds depending on the number of colormaps installed.
Colormaps are shown with the “ramp” intensity map applied.
It is customizable using ~/.ginga/plugin_ColorMapPicker.cfg
, where ~
is your HOME directory:
#
# ColorMapPicker plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_ColorMapPicker.cfg"
cbar_ht = 20
cbar_wd = 300
cbar_sep = 10
cbar_pan_accel = 1.0
Errors¶
The Errors
plugin reports error messages on the viewer.
Plugin Type: Global
Errors
is a global plugin. Only one instance can be opened.
Usage
When an error occurs in Ginga, its message may be reported here.
RC¶
The RC
plugin implements a remote control interface for the Ginga
viewer.
Plugin Type: Global
RC
is a global plugin. Only one instance can be opened.
Usage
The RC
(Remote Control) plugin provides a way to control Ginga remotely
through the use of an XML-RPC interface. Start the plugin from the
“Plugins” menu (invoke “Start RC”) or launch ginga with the --modules=RC
command line option to start it automatically.
By default, the plugin starts up with server running on port 9000 bound
to the localhost interface – this allows connections only from the local
host. If you want to change this, set the host and port in the “Set
Addr” control and press Enter
– you should see the address update in the
“Addr:” display field.
Please note that the host part (before the colon) does not indicate which host you want to allow access from, but to which interface to bind. If you want to allow any host to connect, leave it blank (but include the colon and port number) to allow the server to bind on all interfaces. Press “Restart” to then restart the server at the new address.
Once the plugin is started, you can use the ggrc
script (included when
ginga
is installed) to control Ginga. Take a look at the script if you
want to see how to write your own programmatic interface.
Show example usage:
$ ggrc help
Show help for a specific Ginga method:
$ ggrc help ginga <method>
Show help for a specific channel method:
$ ggrc help channel <chname> <method>
Ginga (viewer shell) methods can be called like this:
$ ggrc ginga <method> <arg1> <arg2> ...
Per-channel methods can be called like this:
$ ggrc channel <chname> <method> <arg1> <arg2> ...
Calls can be made from a remote host by adding the options:
--host=<hostname> --port=9000
(In the plugin GUI, be sure to remove the “localhost” prefix from the “addr”, but leave the colon and port.)
Examples
Create a new channel:
$ ggrc ginga add_channel FOO
Load a file:
$ ggrc ginga load_file /home/eric/testdata/SPCAM/SUPA01118797.fits
Load a file into a specific channel:
$ ggrc ginga load_file /home/eric/testdata/SPCAM/SUPA01118797.fits FOO
Cut levels:
$ ggrc channel FOO cut_levels 163 1300
Auto cut levels:
$ ggrc channel FOO auto_levels
Zoom to a specific level:
$ ggrc -- channel FOO zoom_to -7
(Note the use of --
to allow us to pass a parameter beginning with -
.)
Zoom to fit:
$ ggrc channel FOO zoom_fit
Transform (arguments are a boolean triplet: flipx
flipy
swapxy
):
$ ggrc channel FOO transform 1 0 1
Rotate:
$ ggrc channel FOO rotate 37.5
Change colormap:
$ ggrc channel FOO set_color_map rainbow3
Change color distribution algorithm:
$ ggrc channel FOO set_color_algorithm log
Change intensity map:
$ ggrc channel FOO set_intensity_map neg
In some cases, you may need to resort to shell escapes to be able to pass certain characters to Ginga. For example, a leading dash character is usually interpreted as a program option. In order to pass a signed integer, you may need to do something like:
$ ggrc -- channel FOO zoom -7
Interfacing from within Python
It is also possible to control Ginga in RC mode from within Python. The following describes some of the functionality.
Connecting
First, launch Ginga and start the RC
plugin.
This can be done from the command line:
ginga --modules=RC
From within Python, connect with a RemoteClient
object as
follows:
from ginga.util import grc
host='localhost'
port=9000
viewer = grc.RemoteClient(host, port)
This viewer object is now linked to the Ginga using RC
.
Load an Image
You can load an image from memory in a channel of your choosing. First, connect to a channel:
ch = viewer.channel('Image')
Then, load a Numpy image (i.e., any 2D ndarray
):
import numpy as np
img = np.random.rand(500, 500) * 10000.0
ch.load_np('Image_Name', img, 'fits', {})
The image will display in Ginga and can be manipulated as usual.
Overlay a Canvas Object
It is possible to add objects to the canvas in a given channel. First, connect:
canvas = viewer.canvas('Image')
This connects to the channel named “Image”. You can clear the objects drawn in the canvas:
canvas.clear()
You can also add any basic canvas object. The key issue to keep in
mind is that the objects input must pass through the XMLRC
protocol. This means simple data types (float
, int
, list
,
or str
); No arrays. Here is an example to plot a line through a series
of points defined by two Numpy arrays:
x = np.arange(100)
y = np.sqrt(x)
points = list(zip(x.tolist(), y.tolist()))
canvas.add('path', points, color='red')
This will draw a red line on the image.
WCSMatch¶

WCSMatch
is a global plugin for the Ginga image viewer that allows
you to roughly align images with different scales and orientations
using the images’ World Coordinate System (WCS) for viewing purposes.
Plugin Type: Global
WCSMatch
is a global plugin. Only one instance can be opened.
Usage
To use, simply start the plugin, and from the plugin GUI select a channel from the drop-down menu labeled “Reference Channel”. The image contained in that channel will be used as a reference for synchronizing the images in the other channels.
The channels will be synchronized in viewing (pan, scale (zoom), transforms (flips) and rotation. The checkboxes “Match Pan”, “Match Scale”, “Match Transforms” and “Match Rotation” can be checked or not to control which attributes are synchronized between channels.
To completely “unlock” the synchronization, simply select “None” from the “Reference Channel” drop-down menu.
Currently, there is no way to limit the channels that are affected by the plugin.
ChangeHistory¶

Keep track of buffer change history.
Plugin Type: Global
ChangeHistory
is a global plugin. Only one instance can be opened.
This plugin is used to log any changes to data buffer. For example,
a change log would appear here if a new image is added to a mosaic via the
Mosaic
plugin. Like Contents
,
the log is sorted by channel, and then by image name.
Usage
History should stay no matter what channel or image is active. New history can be added, but old history cannot be deleted, unless the image/channel itself is deleted.
The redo()
method picks up an 'add-image-info'
event and displays
related metadata here. The metadata is obtained as follows:
channel = self.fv.get_channel_info(chname)
iminfo = channel.get_image_info(imname)
timestamp = iminfo.time_modified
description = iminfo.reason_modified # Optional
Both 'time_modified'
and 'reason_modified'
have to be explicitly set
by the calling plugin in the same method that issues the
'add-image-info'
callback, like this:
# This changes the data buffer
image.set_data(new_data, ...)
# Add description for ChangeHistory
info = dict(time_modified=datetime.utcnow(),
reason_modified='Data has changed')
self.fv.update_image_info(image, info)
It is customizable using ~/.ginga/plugin_ChangeHistory.cfg
, where ~
is your HOME directory:
#
# ChangeHistory plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_ChangeHistory.cfg"
# If set to True, will always expand the tree in ChangeHistory when
# new entries are added
always_expand = True
# If set to True, rows will have alternate colors
color_alternate_rows = True
# Timestamp column width
ts_colwidth = 250
SAMP Control¶

The SAMP
plugin implements a SAMP interface for the Ginga reference
viewer.
Note
To run this plugin, you need to install astropy
that has the
samp
module.
Plugin Type: Global
SAMP
is a global plugin. Only one instance can be opened.
Usage
Ginga includes a plugin for enabling SAMP (Simple Applications Messaging Protocol) support. With SAMP support, Ginga can be controlled and interoperate with other astronomical desktop applications.
The SAMP
module is not started by default. To start it when Ginga
starts, specify the command line option:
--modules=SAMP
Otherwise, start it using “Start SAMP” from the “Plugins” menu.
Currently, SAMP support is limited to image.load.fits
messages,
meaning that Ginga will load a FITS file if it receives one of these
messages.
Ginga’s SAMP
plugin uses the astropy.samp
module, so you will need to
have astropy
installed to use the plugin. By default, Ginga’s SAMP
plugin will attempt to start a SAMP hub if one is not found running.
It is customizable using ~/.ginga/plugin_SAMP.cfg
, where ~
is your HOME directory:
#
# SAMP plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_SAMP.cfg"
SAMP_channel = 'Image'
# Default location is set by Ginga's viewer.
#cache_location = '/my/cache/path/'
default_connect = True
start_hub = True
Log¶

See the logging output of the reference viewer.
Plugin Type: Global
Log
is a global plugin. Only one instance can be opened.
Usage
The Log
plugin builds a UI that includes a large scrolling text widget
showing the active output of the logger. The latest output shows up at
the bottom. This can be useful for troubleshooting problems.
There are four controls:
- The combo box on the lower left allows you to choose the level of logging desired. The four levels, in order of verbosity are: “debug”, “info”, “warn”, and “error”.
- The box with the number on the lower right allows you to set how many lines of input to keep in the display buffer (e.g., keep only the last 1000 lines).
- The checkbox “Auto scroll”, if checked, will cause the large text widget to scroll to the end as new log messages are added. Uncheck this if you want to peruse the older messages and study them.
- The “Clear” button is used to clear the text widget, so that only new logging shows up.
Command¶
This plugin provides a command line interface to the reference viewer.
Note
The command line is for use within the plugin UI.
If you are looking for a remote command line interface,
please see the RC
plugin.
Plugin Type: Global
Command
is a global plugin. Only one instance can be opened.
Usage
Get a list of commands and parameters:
g> help
Execute a shell command:
g> !cmd arg arg ...
Notes
An especially powerful tool is to use the reload_local
and
reload_global
commands to reload a plugin when you are developing
that plugin. This avoids having to restart the reference viewer and
laboriously reload data, etc. Simply close the plugin, execute the
appropriate “reload” command (see the help!) and then start the plugin
again.
Note
If you have modifed modules other than the plugin itself, these will not be reloaded by these commands.
SaveImage (Save File)¶

Save images to output files.
Plugin Type: Global
SaveImage
is a global plugin. Only one instance can be opened.
Usage
This global plugin is used to save any changes made in Ginga back to output
images. For example, a mosaic image that was created by the Mosaic
plugin. Currently, only FITS images (single or multiple extensions) are
supported.
Given the output directory (e.g., /mypath/outputs/
), a suffix
(e.g., ginga
), an image channel (Image
), and a selected image
(e.g., image1.fits
), the output file will be
/mypath/outputs/image1_ginga_Image.fits
. Inclusion of the channel name is
optional and can be omitted using plugin configuration file,
plugin_SaveImage.cfg
.
The modified extension(s) will have new header or data extracted from
Ginga, while those not modified will remain untouched. Relevant change
log entries from the ChangeHistory
global plugin will be inserted into
the history of its PRIMARY
header.
Note
This plugin uses the module astropy.io.fits
to write the output
images, regardless of what is chosen for FITSpkg
in the
general.cfg
configuration file.
It is customizable using ~/.ginga/plugin_SaveImage.cfg
, where ~
is your HOME directory:
#
# SaveImage plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_SaveImage.cfg"
# Default output parameters. Can also be changed in the GUI.
output_directory = '.'
output_suffix = 'ginga'
# Include channel name in the suffix.
# If False, only output_suffix is used regardless of channel.
include_chname = True
# Clobber existing output files or not
clobber = False
# Only list modified images from the channel
modified_only = True
# Maximum mosaic size to allow for writing out.
# This is useful to prevent super large mosaic from being written.
# Default is 10k x 10k
max_mosaic_size = 1e8
# Maximum number of rows that will turn off auto column resizing (for speed)
max_rows_for_col_resize = 5000
Local plugins¶
An operation is the activation of a local plugin to perform some function. The plugin manager toolbar at the bottom of the center pane is the graphical way to start an operation.
Pick¶

Perform quick astronomical stellar analysis.
Plugin Type: Local
Pick
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
The Pick
plugin is used to perform quick astronomical data quality analysis
on stellar objects. It locates stellar candidates within a drawn rectangle
and picks the most likely candidate based on a set of search settings.
The Full Width Half Max (FWHM) is reported on the candidate object, as
well as its size based on the plate scale of the detector. Rough
measurement of background, sky level and brightness is also done.
Defining the pick area
The default pick area is defined as a rectangle of approximately 30x30 pixels that encloses the search area.
The move/draw/edit selector at the bottom of the plugin is used to determine what operation is being done to the pick area:
- If “move” is selected, then you can move the existing pick area by dragging it or clicking where you want the center of it placed. If there is no existing area, a default one will be created.
- If “draw” is selected, then you can draw a shape with the cursor to enclose and define a new pick area. The default shape is a rectangle, but other shapes can be selected in the “Settings” tab.
- If “edit” is selected, then you can edit the pick area by dragging its control points, or moving it by dragging in the bounding box.
After the area is moved, drawn or edited, Pick
will perform one of three
actions:
- In “Quick Mode” ON, with “From Peak” OFF, it will simply attempt to perform a calculation based on the coordinate under the crosshair in the center of the pick area.
- In “Quick Mode” ON, with “From Peak” ON, it will perform a quick detection of peaks in the pick area and perform a calculation on the first one found, using the peak’s coordinates.
- In “Quick Mode” OFF, it will search the area for all peaks and evaluate the peaks based on the criteria in the “Settings” tab of the UI (see “The Settings Tab” below) and try to locate the best candidate matching the settings.
If a candidate is found
The candidate will be marked with a point (usually an “X”) in the channel viewer canvas, centered on the object as determined by the horizontal and vertical FWHM measurements.
The top set of tabs in the UI will be populated as follows:
The “Image” tab will show the contents of the cutout area. The widget in this tab is a Ginga widget and so can be zoomed and panned with the usual keyboard and mouse bindings (e.g., scroll wheel). It will also be marked with a point centered on the object and additionally the pan position will be set to the found center.
The “Contour” tab will show a contour plot. This is a contour plot of the area immediately surrounding the candidate, and not usually encompassing the entire region of the pick area. You can use the vertical slider to the right of the plot to increase or decrease the area of the contour plot.
The “FWHM” tab will show a FWHM plot. The blue lines show measurements in the X direction and the green lines show measurements in the Y direction. The solid lines indicate actual pixel values and the dotted lines indicate the fitted 1D function. The shaded green and blue regions indicate the FWHM measurements.
The “Radial” tab contains a radial profile plot. Plotted points in blue are data values, and a line is fitted to the data.
The “Cuts” tab contains a profile plot for the vertical and horizontal cuts represented by the crosshairs present in “Quick Mode” ON. This plot is updated in real time as the pick area is moved. In “Quick Mode” OFF, this plot is not updated.
The “Readout” tab will be populated with a summary of the measurements. There are two buttons and two check boxes in this tab:
- The “Default Region” button restores the pick region to the default shape and size.
- The “Pan to pick” button will pan the channel viewer to the located center.
- The “Quick Mode” check box toggles “Quick Mode” on and off. This affects the behavior of the pick region as described above.
- The “From Peak” check box changes the behavior of “Quick Mode” slightly as described above.
The “Controls” tab has a couple of buttons that will work off of the measurements.
- The “Bg cut” button will set the low cut level of the channel viewer to the measured background level. A delta to this value can be applied by setting a value in the “Delta bg” box (press “Enter” to change the setting).
- The “Sky cut” button will set the low cut level of the channel viewer to the measured sky level. A delta to this value can be applied by setting a value in the “Delta sky” box (press “Enter” to change the setting).
- The “Bright cut” button will set the high cut level of the channel viewer to the measured sky+brightness levels. A delta to this value can be applied by setting a value in the “Delta bright” box (press “Enter” to change the setting).
The “Report” tab is used to record information about the measurements in tabular form.
By pressing the “Add Pick” button, the information about the most recent candidate is added to the table. If the “Record Picks automatically” checkbox is checked, then any candidates are added to the table automatically.
Note
If the “Show candidates” checkbox in the “Settings” tab is checked, then all objects found in the region (according to the settings) will be added to the table instead of just the selected candidate.
You can clear the table at any time by pressing the “Clear Log” button. The log can be saved to a table by putting a valid path and filename in the “File:” box and pressing “Save table”. File type is automatically determined by the given extension (e.g., “.fits” is FITS and “.txt” is plain text).
If no candidate is found
If no candidate can be found (based on the settings), then the pick area is marked with a red point centered on the pick area.
The image cutout will be taken from this central area and so the “Image” tab will still have content. It will also be marked with a central red “X”.
The contour plot will still be produced from the cutout, and the cuts plot will be updated in “Quick Mode”.
All the other plots will be cleared.
The Settings Tab
The “Settings” tab controls aspects of the search within the pick area:
- The “Show candidates” checkbox controls whether all detected sources are marked or not (as shown in the figure below). Additionally, if checked, then all the found objects are added to the pick log table when using the “Report” controls.
- The “Draw type” parameter is used to choose the shape of the pick area to be drawn.
- The “Radius” parameter sets the radius to be used when finding and evaluating bright peaks in the image.
- The “Threshold” parameter is used to set a threshold for peak finding; if set to “None”, then a reasonable default value will be chosen.
- The “Min FWHM” and “Max FWHM” parameters can be used to eliminate certain sized objects from being candidates.
- The “Ellipticity” parameter is used to eliminate candidates based on their asymmetry in shape.
- The “Edge” parameter is used to eliminate candidates based on how close to the edge of the cutout they are. NOTE: currently this works reliably only for non-rotated rectangular shapes.
- The “Max side” parameter is used to limit the size of the bounding box that can be used in the pick shape. Larger sizes take longer to evaluate.
- The “Coordinate Base” parameter is an offset to apply to located sources. Set to “1” if you want sources pixel locations reported in a FITS-compliant manner and “0” if you prefer 0-based indexing.
- The “Calc center” parameter is used to determine whether the center is calculated from FWHM fitting (“fwhm”) or centroiding (“centroid”).
- The “FWHM fitting” parameter is used to determine which function is is used for FWHM fitting (“gaussian” or “moffat”).
- The “Contour Interpolation” parameter is used to set the interpolation method used in rendering the background image in the “Contour” plot.
The “Redo Pick” button will redo the search operation. It’s convenient if you have changed some parameters and want to see the effect based on the current pick area without disturbing it.
User Configuration
It is customizable using ~/.ginga/plugin_Pick.cfg
, where ~
is your HOME directory:
#
# Pick plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Pick.cfg"
color_pick = 'green'
shape_pick = 'box'
color_candidate = 'purple'
# Offset to add to Pick results. Default is 1.0 for FITS like indexing,
# set to 0.0 here if you prefer numpy-like 0-based indexing
pixel_coords_offset = 0.0
# Maximum side for a pick region
max_side = 1024
# For contour plot
num_contours = 8
# How big of a radius are we willing to consider from the center of the
# pick? bigger numbers == slower
contour_size_min = 10
contour_size_limit = 70
# Start in Quick Mode?
quick_mode = False
quick_from_peak = True
# for future use
quick_update_interval = 0.25
quick_drag_only = True
# Star candidate search parameters
radius = 10
# Set threshold to None to auto calculate it
threshold = None
# Minimum and maximum fwhm to be considered a candidate
min_fwhm = 2.0
max_fwhm = 50.0
# Minimum ellipticity to be considered a candidate
min_ellipse = 0.5
# Percentage from edge to be considered a candidate
edge_width = 0.01
# Graphically indicate all possible considered candidates
show_candidates = False
# Center of object is based on FWHM ("fwhm") or centroid ("centroid")
# calculation:
calc_center_alg = 'centroid'
# Fitting function to use for FWHM ("gaussian" or "moffat")
calc_fwhm_alg = 'gaussian'
# Defaults for delta cut levels (in Controls tab)
delta_sky = 0.0
delta_bright = 0.0
# use a different color/intensity map than channel image?
pick_cmap_name = None
pick_imap_name = None
# For Reports tab
record_picks = True
# Set this to a file name, if None a filename will be automatically chosen
report_log_path = None
Ruler¶

Ruler
is a simple plugin designed to measure distances on an image.
Plugin Type: Local
Ruler
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
Ruler
measures distance by calculating a spherical triangulation
via WCS mapping of three points defined by a single line drawn on the image.
By default, the distance is shown in arcminutes of sky, but using the
“Units” control, it can be changed to show degrees or pixel distance instead.
Click and drag to establish a ruler between two points.
Display the “Zoom” tab at the same time to precisely see detail while drawing the ruler, if desired.
To erase the old and make a new ruler, click and drag again.
When another line is drawn, it replaces the first one.
When the plugin is closed, the graphic overlay is removed.
Should you want “sticky rulers”, use the Drawing
plugin
(and choose “Ruler” as the drawing type).
Editing
To edit an existing ruler, click the radio button in the plugin UI labeled “Edit”. If the ruler does not become selected immediately, click on it. This should establish a bounding box around the ruler and show its control points. Drag within the bounding box to move the ruler or click and drag the endpoints to edit the ruler.
Units
The units shown for distance can be selected from the drop-down box in the UI. You have a choice of “arcmin”, “degrees”, or “pixels”. The first two require a valid and working WCS in the image.
MultiDim¶


A plugin to navigate HDUs in a FITS file or planes in a 3D cube or higher dimension dataset.
Plugin Type: Local
MultiDim
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
MultiDim
is a plugin designed to handle data cubes and multi-HDU FITS
files. If you have opened such an image in Ginga, starting this plugin
will enable you to browse to other slices of the cube or view other
HDUs.
For a data cube, you can save a slice as an image using the “Save Slice”
button or create a movie using the “Save Movie” button by entering the
“Start” and “End” slice indices. This feature requires mencoder
to be
installed.
For a FITS table, its data are read in using Astropy table. Column units are displayed right under the main header (“None” if no unit). For masked columns, masked values are replaced with pre-defined fill values.
Browsing HDUs
Use the HDU drop down list in the upper part of the UI to browse and select an HDU to open in the channel.
Navigating Cubes
Use the controls in the lower part of the UI to select the axis and to step through the planes in that axis.
User Configuration
It is customizable using ~/.ginga/plugin_MultiDim.cfg
, where ~
is your HOME directory:
#
# MultiDim plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_MultiDim.cfg"
# If set to True, will auto open the plugin when an image is loaded
# with NAXIS >= 3
auto_start_naxis = False
Cuts¶

A plugin for generating a plot of the values along a line or path.
Plugin Type: Local
Cuts
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
Cuts
plots a simple graph of pixel values vs. index for a line drawn
through the image. Multiple cuts can be plotted.
There are four kinds of cuts available: line, path, freepath and beziercurve:
- The “line” cut is a straight line between two points.
- The “path” cut is drawn like an open polygon, with straight segments in-between.
- The “freepath” cut is like a path cut, but drawn using a free-form stroke following the cursor movement.
- The “beziercurve” path is a cubic Bezier curve.
If a new image is added to the channel while the plugin is active, it will update with the new calculated cuts on the new image.
If the “enable slit” setting is enabled, this plugin will also allow
slit image functionality (for multidimensional images) via a “Slit” tab.
In the tab UI, select one axis from the “Axes” list and draw a line.
This will create a 2D image that assumes the first two axes are
spatial and index the data along the selected axis.
Much like Cuts
, you can view the other slit images using the cut
selection drop down box.
Drawing Cuts
The “New Cut Type” menu let you choose what kind of cut you are going to draw.
Choose “New Cut” from the “Cut” dropdown menu if you want to draw a new cut. Otherwise, if a particular named cut is selected then that will be replaced by any newly drawn cut.
While drawing a path or beziercurve cut, press ‘v’ to add a vertex, or ‘z’ to remove the last vertex added.
Keyboard Shortcuts
While hovering the cursor, press ‘h’ for a full horizontal cut and ‘j’ for a full vertical cut.
Deleting Cuts
To delete a cut, select its name from the “Cut” dropdown and click the “Delete” button. To delete all cuts, press “Delete All”.
Editing Cuts
Using the edit canvas function, it is possible to add new vertices to an existing path and to move vertices around. Click the “Edit” radio button to put the canvas in edit mode. If a cut is not automatically selected, you can now select the line, path, or curve by clicking on it, which should enable the control points at the ends or vertices – you can drag these around. To add a new vertex to a path, hover the cursor carefully on the line where you want the new vertex and press ‘v’. To get rid of a vertex, hover the cursor over it and press ‘z’.
You will notice one extra control point for most objects, which has a center of a different color – this is a movement control point for moving the entire object around the image when in edit mode.
You can also select “Move” to just move a cut unchanged.
Changing Width of Cuts
The width of ‘line’ cuts can be changed using the “Width Type” menu:
- “none” indicates a cut of zero radius; i.e., only showing the pixel values along the line
- “x” will plot the sum of values along the X axis orthogonal to the cut.
- “y” will plot the sum of values along the Y axis orthogonal to the cut.
- “perpendicular” will plot the sum of values along an axis perpendicular to the cut.
The “Width radius” controls the width of the orthogonal summation by an amount on either side of the cut – 1 would be 3 pixels, 2 would be 5 pixels, etc.
Saving Cuts
Use the “Save” button to save the Cuts
plot as as image and
data as a Numpy compressed archive.
User Configuration
It is customizable using ~/.ginga/plugin_Cuts.cfg
, where ~
is your HOME directory:
#
# Cuts plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Cuts.cfg"
# If set to True will always select a cut after drawing it
select_new_cut = True
# If set to True will automatically change to "move" mode after draw
draw_then_move = True
# If set to True will label cuts with a text annotation
label_cuts = True
# If set to True will add a legend to the cuts plot
show_cuts_legend = False
# If set to True will add Slit tab
enable_slit = False
# Default cut colors
colors = ['magenta', 'skyblue2', 'chartreuse2', 'cyan', 'pink', 'burlywood2', 'yellow3', 'turquoise', 'coral1', 'mediumpurple2']
# If set to True, will update graph continuously as cursor is dragged
# around image
drag_update = False
Histogram¶

Histogram
plots a histogram for a region drawn in the image, or for the
entire image.
Plugin Type: Local
Histogram
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
Click and drag to define a region within the image that will be used to calculate the histogram. To take the histogram of the full image, click the button in the UI labeled “Full Image”.
Note
Depending on the size of the image, calculating the full histogram may take time.
If a new image is selected for the channel, the histogram plot will be recalculated based on the current parameters with the new data.
UI Controls
Three radio buttons at the bottom of the UI are used to control the effects of the click/drag action:
- select “Move” to drag the region to a different location
- select “Draw” to draw a new region
- select “Edit” to edit the region
To make a log plot of the histogram, check the “Log Histogram” checkbox. To plot by the full range of values in the image instead of by the range within the cut values, uncheck the “Plot By Cuts” checkbox.
The “NumBins” parameter determines how many bins are used in calculating the histogram. Type a number in the box and press “Enter” to change the default value.
Cut Levels Convenience Controls
Because a histogram is useful feedback for setting the cut levels, controls are provided in the UI for setting the low and high cut levels in the image, as well as for performing an auto cut levels, according to the auto cut levels settings in the channel preferences.
User Configuration
It is customizable using ~/.ginga/plugin_Histogram.cfg
, where ~
is your HOME directory:
#
# Histogram plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Histogram.cfg"
# Switch to "move" mode after selection
draw_then_move = True
# Number of bins for histogram
num_bins = 2048
# Histogram color
hist_color = 'aquamarine'
Crosshair¶

Crosshair
is a simple plugin to draw crosshairs labeled with the
position of the cross in pixels coordinates, WCS coordinates, or
data value at the cross position.
Plugin Type: Local
Crosshair
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
Select the appropriate type of output in the “Format” drop-down box in the UI: “xy” for pixel coordinates, “coords” for the WCS coordinates, and “value” for the value at the crosshair position.
Then, click and drag to position the crosshair.
Overlays¶

A plugin for generating color overlays representing under- and over-exposure in the loaded image.
Plugin Type: Local
Overlays
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
Choose colors from the drop-down menus for the low-limit and/or high-limit (“Lo color” and “Hi color”, respectively). Specify the limits for low and high values in the limit boxes (“Lo limit” and “Hi limit”, respectively). Set the opacity of the overlays with a value between 0 and 1 in the “Opacity” box. Finally, press the “Redo” button.
The color overlay should show areas below the low limit with a low color and the areas above the high limit in the high color. If you omit a limit (leave the box blank), that color won’t be shown in the overlay.
If a new image is selected for the channel, the overlays image will be recalculated based on the current parameters with the new data.
WCSAxes¶

A plugin for generating WCS axes overlay in the loaded image.
Plugin Type: Local
WCSAxes
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
As long as image as a valid WCS, WCS axes will be displayed. Use plugin GUI or configuration file to customize axes display.
It is customizable using ~/.ginga/plugin_WCSAxes.cfg
, where ~
is your HOME directory:
#
# WCSAxes plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_WCSAxes.cfg"
# Color, style, and width of grid lines
linecolor = 'cyan'
linestyle = 'solid'
linewidth = 1
# Alpha (opacity) of grid lines; 1=opaque, 0=transparent
alpha = 1
# Number of RA and DEC lines to draw
n_ra_lines = 10
n_dec_lines = 10
# Show RA and DEC values of grid lines
show_label = True
# Label font size
fontsize = 8
# Label offset from grid lines (pixels)
label_offset = 4
TVMark¶

Mark points from file (non-interative mode) on an image.
Plugin Type: Local
TVMark
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
This plugin allows non-interactive marking of points of interest by
reading in a file containing a table with RA and DEC positions of those points.
Any text or FITS table file that can be read by astropy.table
is acceptable
but user must define the column names correctly in the plugin configuration
file (see below).
An attempt will be made to convert RA and DEC values to degrees.
If the unit conversion fails, they will be assumed to be in degrees already.
Alternately, if the file has columns containing the direct pixel locations, you can read these columns instead by unchecking the “Use RADEC” box. Again, the column names must be correctly defined in the plugin configuration file (see below). Pixel values can be 0- or 1-indexed (i.e., whether the first pixel is 0 or 1) and is configurable (see below). This is useful when you want to mark the physical pixels regardless of WCS (e.g., marking hot pixels on a detector). RA and DEC will still be displayed if the image has WCS information but they will not affect the markings.
To mark different groups (e.g., displaying galaxies as green circles and background as cyan crosses, as shown above):
- Select green circle from the drop-down menus. Alternately, enter desired size or width.
- Make sure “Use RADEC” box is checked, if applicable.
- Using “Load Coords” button, load the file containing RA and DEC (or X and Y) positions for galaxies only.
- Repeat Step 1 but now select cyan cross from the drop-down menus.
- Repeat Step 2 but choose the file containing background positions only.
Selecting an entry (or multiple entries) from the table listing will highlight the marking(s) on the image. The highlight uses the same shape and color, but a slightly thicker line.
You can also highlight all the markings within a region both on the image and the table listing by drawing a rectangle on the image while this plugin is active.
Pressing the “Hide” button will hide the markings but does not clear the plugin’s memory; That is, when you press “Show”, the same markings will reappear on the same image. However, pressing “Forget” will clear the markings both from display and memory; That is, you will need to reload your file(s) to recreate the markings.
To redraw the same positions with different marking parameters, press “Forget” and repeat the steps above, as necessary. However, if you simply wish to change the line width (thickness), pressing “Hide” and then “Show” after you entered the new width value will suffice.
If images of very different pointings/dimensions are displayed in the same channel, markings that belong to one image but fall outside another will not appear in the latter.
To create a table that this plugin can read, one can use results from
the Pick
plugin, in addition to creating a table by hand, using
astropy.table
, etc.
Used together with TVMask
, you can overlay both point sources and masked
regions in Ginga.
It is customizable using ~/.ginga/plugin_TVMark.cfg
, where ~
is your HOME directory:
#
# TVMark plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_TVMark.cfg"
# Marking type -- 'circle' or 'cross'
marktype = 'circle'
# Marking color -- Any color name accepted by Ginga
markcolor = 'green'
# Marking size or radius
marksize = 5
# Marking line width (thickness)
markwidth = 1
# Specify whether pixel values are 0- or 1-indexed
pixelstart = 1
# True -- Use 'ra' and 'dec' columns to extract RA/DEC positions. This option
# uses image WCS to convert to pixel locations.
# False -- Use 'x' and 'y' columns to extract pixel locations directly.
# This does not use WCS.
use_radec = True
# Columns to load into table listing (case-sensitive).
# Whether RA/DEC or X/Y columns are used depend on associated GUI selection.
ra_colname = 'ra'
dec_colname = 'dec'
x_colname = 'x'
y_colname = 'y'
# Extra columns to display; e.g., ['colname1', 'colname2']
extra_columns = []
TVMask¶

Display masks from file (non-interative mode) on an image.
Plugin Type: Local
TVMask
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
This plugin allows non-interactive display of mask by reading in a FITS file, where non-zero is assumed to be masked data.
To display different masks (e.g., some masked as green and some as pink, as shown above):
- Select green from the drop-down menu. Alternately, enter desired alpha value.
- Using “Load Mask” button, load the relevant FITS file.
- Repeat (1) but now select pink from the drop-down menu.
- Repeat (2) but choose another FITS file.
- To display a third mask as pink too, repeat (4) without changing the drop-down menu.
Selecting an entry (or multiple entries) from the table listing will highlight the mask(s) on the image. The highlight uses a pre-defined color and alpha (customizable below).
You can also highlight all the masks within a region both on the image and the table listing by drawing a rectangle on the image while this plugin is active.
Pressing the “Hide” button will hide the masks but does not clear the plugin’s memory; That is, when you press “Show”, the same masks will reappear on the same image. However, pressing “Forget” will clear the masks both from display and memory; That is, you will need to reload your file(s) to recreate the masks.
To redraw the same masks with different color or alpha, press “Forget” and repeat the steps above, as necessary.
If images of very different pointings/dimensions are displayed in the same channel, masks that belong to one image but fall outside another will not appear in the latter.
To create a mask that this plugin can read, one can use results from
the Drawing
plugin (press “Create Mask” after drawing and save the
mask using SaveImage
), in addition to creating a FITS
file by hand using astropy.io.fits
, etc.
Used together with TVMark
, you can overlay both point sources and
masked regions in Ginga.
It is customizable using ~/.ginga/plugin_TVMask.cfg
, where ~
is your HOME directory:
#
# TVMask plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_TVMask.cfg"
# Mask color -- Any color name accepted by Ginga
maskcolor = 'green'
# Mask alpha (transparency) -- 0=transparent, 1=opaque
maskalpha = 0.5
# Highlighted mask color and alpha
hlcolor = 'white'
hlalpha = 1.0
Blink¶

Blink
switches through the images shown in a channel at a rate
chosen by the user. Alternatively, it can switch between channels
in the main workspace. In both cases, the primary purpose is to
compare and contrast the images (within a channel, or across
channels) visually within a short timescale – like blinking your
eyes.
Plugin Type: Local or Global
Blink
can be invoked either as a local plugin, in which case
it cycles through the images in the channel, or as a global
plugin, in which case it cycles through the channels.
Local plugins are started from the “Operations” button, while global plugins are started from the “Plugins” menu.
Usage
Set the interval between image changes in terms of seconds in the box labeled “Interval”. Then, press “Start Blink” to start the timed cycling, and “Stop Blink” to stop the cycling.
You can change the number in “Interval” and press Enter
to
dynamically change the cycle time while the cycle is running.
It is customizable using ~/.ginga/plugin_Blink.cfg
, where ~
is your HOME directory:
#
# Blink plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Blink.cfg"
# Blink channels instead of images within a channel
# PLEASE NOTE: this option is DEPRECATED
blink_channels = False
# the maximum interval for a blink
interval_max = 30.0
# the minimum interval for a blink
interval_min = 0.25
LineProfile¶

A plugin to graph the pixel values along a straight line bisecting a cube.
Plugin Type: Local
LineProfile
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
Warning
There are no restrictions to what axes can be chosen. As such, the plot can be meaningless.
The LineProfile
plugin is used for multidimensional (i.e., 3D or higher)
images. It plots the values of the pixels at the current cursor
position through the selected axis; or if a region is selected, it plots the
mean in each frame. This can be used to create normal spectral line profiles.
A marker is placed at the data point of the currently displayed frame.
Displayed X-axis is constructed using CRVAL*
, CDELT*
, CRPIX*
,
CTYPE*
, and CUNIT*
keywords from FITS header. If any of the keywords
are unavailabled, the axis falls back to NAXIS*
values instead.
Displayed Y-axis is constructed using BTYPE
and BUNIT
. If they are not
available, it simply labels pixel values as “Flux”.
To use this plugin:
- Select an axis.
- Pick a point or draw a region using the cursor.
- Use
MultiDim
to change step values of axes, if applicable.
It is customizable using ~/.ginga/plugin_LineProfile.cfg
, where ~
is your HOME directory:
#
# LineProfile plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_LineProfile.cfg"
# Default mark type. This can be change in the GUI.
mark_type = 'point'
# Properties of a point mark type. Radius can be change in Edit mode.
mark_radius = 10
mark_style='cross'
# Mark color.
mark_color = 'cyan'
PixTable¶

PixTable
provides a way to check or monitor the pixel values in
a region.
Plugin Type: Local
PixTable
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Basic Use
In the most basic use, simply move the cursor around the channel viewer; an array of pixel values will appear in the “Pixel Values” display in the plugin UI. The center value is highlighted, and this corresponds to the value under the cursor.
You can choose a 3x3, 5x5, 7x7, or 9x9 grid from the left-most combobox control. It may help to adjust the “Font Size” control to prevent having the array values cut off on the sides. You can also enlarge the plugin workspace to see more of the table.
Note
The order of the value table shown will not necessarily match to the channel viewer if the images is flipped, transposed, or rotated.
Using Marks
If you click in the channel viewer, it will set a mark. There can be any number of marks, and they are each noted with an “X” annotated with a number. When that mark is selected, it will only show the values around the mark. Simply change the mark control to select a different mark to see the values around it.
The marks will stay in position even if a new image is loaded and they will show the values for the new image. In this way you can monitor the area around a spot if the image is updating frequently.
If the “Pan to mark” checkbox is selected, then when you select a different mark from the mark control, the channel viewer will pan to that mark. This can be useful to inspect the same spots in several different images.
Note
If you change the mark control back to “None”, then the pixel table will again update as you move the cursor around the viewer.
Deleting Marks
To delete a mark, select it in the mark control and then press the button marked “Delete”. To delete all the marks, press the button marked “Delete All”.
User Configuration
It is customizable using ~/.ginga/plugin_PixTable.cfg
, where ~
is your HOME directory:
#
# PixTable plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_PixTable.cfg"
# Default font
font = 'fixed'
# Default font size
fontsize = 12
Preferences¶
Make changes to channel settings graphically in the UI.
Plugin Type: Local
Preferences
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
The Preferences
plugin sets the preferences on a per-channel basis.
The preferences for a given channel are inherited from the “Image”
channel until they are explicitly set and saved using this plugin.
If “Save Settings” is pressed, it will save the settings to the user’s home Ginga folder so that when a channel with the same name is created in future Ginga sessions it will obtain the same settings.
Color Distribution Preferences

“Color Distribution” preferences.
The “Color Distribution” preferences control the preferences used for the data value to color index conversion that occurs after cut levels are applied and just before final color mapping is performed. It concerns how the values between the low and high cut levels are distributed to the color and intensity mapping phase.
The “Algorithm” control is used to set the algorithm used for the mapping. Click the control to show the list, or simply scroll the mouse wheel while hovering the cursor over the control. There are eight algorithms available: linear, log, power, sqrt, squared, asinh, sinh, and histeq. The name of each algorithm is indicative of how the data is mapped to the colors in the color map. “linear” is the default.
Color Mapping Preferences

“Color Mapping” preferences.
The “Color Mapping” preferences control the preferences used for the color map and intensity map, used during the final phase of the color mapping process. Together with the “Color Distribution” preferences, these control the mapping of data values into a 24-bpp RGB visual representation.
The “Colormap” control selects which color map should be loaded and used. Click the control to show the list, or simply scroll the mouse wheel while hovering the cursor over the control.
The “Intensity” control selects which intensity map should be used with the color map. The intensity map is applied just before the color map, and can be used to change the standard linear scale of values into an inverted scale, logarithmic, etc.
Ginga comes with a good selection of color maps, but should you want
more, you can add custom ones or, if matplotlib
is installed, you
can load all the ones that it has.
See “Customizing Ginga” for details.
Zoom Preferences

“Zoom” preferences.
The “Zoom” preferences control Ginga’s zooming/scaling behavior. Ginga supports two zoom algorithms, chosen using the “Zoom Alg” control:
- The “step” algorithm zooms the image inwards in discrete steps of 1X, 2X, 3X, etc. or outwards in steps of 1/2X, 1/3X, 1/4X, etc. This algorithm results in the least artifacts visually, but is a bit slower to zoom over wide ranges when using a scrolling motion because more “throw” is required to achieve a large zoom change (this is not the case if one uses of the shortcut zoom keys, such as the digit keys).
- The “rate” algorithm zooms the image by advancing the scaling at a rate defined by the value in the “Zoom Rate” box. This rate defaults to the square root of 2. Larger numbers cause larger changes in scale between zoom levels. If you like to zoom your images rapidly, at a small cost in image quality, you would likely want to choose this option.
Note that regardless of which method is chosen for the zoom algorithm,
the zoom can be controlled by holding down Ctrl
(coarse) or Shift
(fine) while scrolling to constrain the zoom rate (assuming the default
mouse bindings).
The “Stretch XY” control can be used to stretch one of the axes (X or Y) relative to the other. Select an axis with this control and roll the scroll wheel while hovering over the “Stretch Factor” control to stretch the pixels in the selected axis.
The “Scale X” and “Scale Y” controls offer direct access to the underlying scaling, bypassing the discrete zoom steps. Here, exact values can be typed to scale the image. Conversely, you will see these values change as the image is zoomed.
The “Scale Min” and “Scale Max” controls can be used to place a limit on how much the image can be scaled.
The “Zoom Defaults” button will restore the controls to the Ginga default values.
Pan Preferences

“Pan” preferences.
The “Pan” preferences control Ginga’s panning behavior.
The “Pan X” and “Pan Y” controls offer direct access to set the pan position in the image (the part of the image located at the center of the window) – you can see them change as you pan around the image.
The “Center Image” button sets the pan position to the center of the image, as calculated by halving the dimensions in X and Y.
The “Mark Center” check box, when checked, will cause Ginga to draw a small reticle in the center of the image. This is useful for knowing the pan position and for debugging.
Transform Preferences

“Transform” preferences.
The “Transform” preferences provide for transforming the view of the image by flipping the view in X or Y, swapping the X and Y axes, or rotating the image in arbitrary amounts.
The “Flip X” and “Flip Y” checkboxes cause the image view to be flipped in the corresponding axis.
The “Swap XY” checkbox causes the image view to be altered by swapping the X and Y axes. This can be combined with “Flip X” and “Flip Y” to rotate the image in 90 degree increments. These views will render more quickly than arbitrary rotations using the “Rotate” control.
The “Rotate” control will rotate the image view the specified amount. The value should be specified in degrees. “Rotate” can be specified in conjunction with flipping and swapping.
The “Restore” button will restore the view to the default view, which is unflipped, unswapped, and unrotated.
Auto Cuts Preferences

“Auto Cuts” preferences.
The “Auto Cuts” preferences control the calculation of auto cut levels for the view when the auto cut levels button or key is pressed, or when loading a new image with auto cuts enabled.
The “Auto Method” control is used to choose which auto cuts algorithm used: “minmax” (minimum maximum values), “histogram” (based on an image histogram), “stddev” (based on the standard deviation of pixel values), or “zscale” (based on the ZSCALE algorithm popularized by IRAF). As the algorithm is changed, the boxes under it may also change to allow changes to parameters particular to each algorithm.
WCS Preferences

“WCS” preferences.
The “WCS” preferences control the display preferences for the World Coordinate System (WCS) calculations used to report the cursor position in the image.
The “WCS Coords” control is used to select the coordinate system in which to display the result.
The “WCS Display” control is used to select a sexagesimal (H:M:S
)
readout or a decimal degrees readout.
New Image Preferences

“New Image” preferences.
The “New Images” preferences determine how Ginga reacts when a new image
is loaded into the channel. This includes when an older image is
revisited by clicking on its thumbnail in the Thumbs
plugin pane.
The “Cut New” setting controls whether an automatic cut-level calculation should be performed on the new image, or whether the currently set cut levels should be applied. The possible settings are:
- “on”: calculate a new cut levels always;
- “override”: calculate a new cut levels until the user overrides it by manually setting a cut levels, then turn “off”; or
- “off”: always use the currently set cut levels.
Tip
The “override” setting is provided for the convenience of
having automatic cut levels, while preventing a manually set
cuts from being overridden when a new image is ingested. When
typed in the image window, the semicolon key can be used to
toggle the mode back to override (from “off”), while colon will
set the preference to “on”. The Info
panel shows
the state of this setting.
The “Zoom New” setting controls whether a newly visited image should be zoomed to fit the window. There are three possible values: on, override, and off:
- “on”: the new image is always zoomed to fit;
- “override”: images are automatically fitted until the zoom level is changed manually, then the mode automatically changes to “off”, or
- “off”: always use the currently set zoom levels.
Tip
The “override” setting is provided for the convenience of
having an automatic zoom, while preventing a manually set zoom
level from being overridden when a new image is ingested. When
typed in the image window, the apostrophe (a.k.a. “single quote”)
key can be used to toggle the mode back to “override” (from
“off”), while quote (a.k.a. double quote) will set the preference
to “on”. The global plugin Info
panel shows the state of this
setting.
The “Center New” box, if checked, will cause newly visited images to always have the pan position reset to the center of the image. If unchecked, the pan position is unchanged from the previous image.
The “Follow New” setting is used to control whether Ginga will change
the display if a new image is loaded into the channel. If unchecked,
the image is loaded (as seen, for example, by its appearance in the
Thumbs
tab), but the display will not change to the new image. This
setting is useful in cases where new images are being loaded by some
automated means into a channel and the user wishes to study the current
image without being interrupted.
The “Raise New” setting controls whether Ginga will raise the tab of a channel when an image is loaded into that channel. If unchecked, then Ginga will not raise the tab when an image is loaded into that particular channel.
The “Create Thumbnail” setting controls whether Ginga will create a thumbnail for images loaded into that channel. In cases where many images are being loaded into a channel frequently (e.g., a low frequency video feed), it may be undesirable to create thumbnails for all of them.
Catalogs¶
A plugin for plotting object locations from a catalog on an image.
Plugin Type: Local
Catalogs
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
Before Catalogs
can be used, you need to define at least one catalog or
image server to be queried in ginga_config.py
. Here is an example for
defining three cone search catalogs for guide stars:
def pre_gui_config(ginga):
from ginga.util.catalog import AstroPyCatalogServer
# Add Cone Search services
catalogs = [
('The HST Guide Star Catalog, Version 1.2 (Lasker+ 1996) 1',
'GSC_1.2'),
('The PMM USNO-A1.0 Catalogue (Monet 1997) 1', 'USNO_A1'),
('The USNO-A2.0 Catalogue (Monet+ 1998) 1', 'USNO_A2'),
]
bank = ginga.get_ServerBank()
for longname, shortname in catalogs:
obj = AstroPyCatalogServer(
ginga.logger, longname, shortname, '', shortname)
bank.addCatalogServer(obj)
def post_gui_config(ginga):
pass
Then, start Ginga and then start the Catalogs
local plugin from the
channel you want to perform searchs on. You will see the catalogs listed
in a drop-down menu on the plugin GUI.
Draw a shape on the displayed image and adjust search parameters as desired. When you are ready, press on the button to perform the search. When search results are available, they will be displayed on the image and also listed in a table on the plugin GUI. You can click on either the table or the image to highlight selection.
It is customizable using ~/.ginga/plugin_Catalogs.cfg
, where ~
is your HOME directory:
#
# Catalogs plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Catalogs.cfg"
draw_type = 'circle'
select_color = 'skyblue'
color_outline = 'aquamarine'
click_radius = 10
Mosaic¶
Plugin to create image mosaic.
Plugin Type: Local
Mosaic
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
Warning
This can be very memory intensive.
This plugin is used to automatically create a mosaic in the channel using
images provided by the user (e.g., using FBrowser
).
The position of an image on the mosaic is determined by its WCS without
distortion correction. This is meant as a quick-look tool, not a
replacement for image drizzling that takes account of image distortion, etc.
The mosaic only exists in memory but you can save it out to a
FITS file using SaveImage
.
When a mosaic falls out of memory, it is no longer accessible in Ginga. To avoid this, you must configure your session such that your Ginga data cache is sufficiently large (see “Customizing Ginga” in the manual).
To create a new mosaic, set the FOV and drag files onto the display window. Images must have a working WCS.
It is customizable using ~/.ginga/plugin_Mosaic.cfg
, where ~
is your HOME directory:
#
# Mosaic plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Mosaic.cfg"
# annotate images with their names
annotate_images = False
# default FOV for new mosaics
fov_deg = 0.2
# Try to match backgrounds
match_bg = False
# Number of pixels to trim from edges
trim_px = 0
# Merge (coadd pixels) instead of overlapping tiles
merge = False
# Number of threads to devote to opening images
num_threads = 4
# dropping a new file or files starts a new mosaic
drop_creates_new_mosaic = False
# Set to True when you want to mosaic image HDUs in a file
mosaic_hdus = False
# Limit on skew between X and Y axis after warping tile acceptable for mosaic
skew_limit = 0.1
# Allow the mosaic image to expand if new tiles are added that
# aren't in the region
allow_expand = True
# When expanding an image, pad on a side by this many deg
expand_pad_deg = 0.01
# Maximum delta from center of image (in deg) beyond which new images
# are assumed to start a new mosaic. Set to None if you never want this
# bahavior
max_center_deg_delta = 2.0
# Allow mosaic images to create thumbnail entries
make_thumbs = False
# Reuse existing mosaic for new mosaic (faster)
reuse_image = False
Drawing¶
A plugin for drawing canvas forms (overlaid graphics).
Plugin Type: Local
Drawing
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
This plugin can be used to draw many different shapes on the image display. When it is in “draw” mode, select a shape from the drop-down menu, adjust the shape’s parameters (if needed), and draw on the image by using left mouse button. You can choose to draw in pixel or WCS space.
To move or edit an existing shape, set the plugin on “edit” or “move” mode, respectively.
To save the drawn shape(s) as mask image, click the “Create Mask” button
and you will see a new mask image created in Ginga. Then, use SaveImage
plugin to save it out as single-extension FITS. Note that the mask will
take the size of the displayed image. Therefore, to create masks for
different image dimensions, you need to repeat the steps multiple times.
FBrowser¶
A plugin for browsing the local filesystem and loading files.
Plugin Type: Global or Local
FBrowser
is a hybrid global/local plugin, which means it can be invoked
in either fashion. If invoked as a local plugin then it is associated
with a channel, and an instance can be opened for each channel. It can
also be opened as a global plugin.
Usage
Navigate the directory tree until you come to the location files you want to load. You can double click a file to load it into the associated channel, or drag a file into a channel viewer window to load it into any channel viewer.
Multiple files can be selected by holding down Ctrl
(Command
on Mac),
or Shift
-clicking to select a contiguous range of files.
You may also enter full path to the desired image(s) in the text box as
/my/path/to/image.fits
, /my/path/to/image.fits[ext]
,
/my/path/to/image*.fits
, or /my/path/to/image*.fits[ext]
.
Because it is a local plugin, FBrowser
will remember its last
directory if closed and then restarted.
It is customizable using ~/.ginga/plugin_FBrowser.cfg
, where ~
is your HOME directory:
#
# FBrowser plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_FBrowser.cfg"
# Set to a specific directory to choose a starting point for file exploration.
# If None is given, it defaults to your HOME.
home_path = None
# This controls whether the plugin scans the FITS headers to create the
# listing (slow for large numbers of files)
scan_fits_headers = False
# If the number of files in the listing is greater than this, don't do
# a scan on the headers
scan_limit = 100
# if scan_fits_headers is True, then the keywords provides a map between
# attributes and FITS header keywords to fetch from the header
keywords = [('Object', 'OBJECT'), ('Date', 'DATE-OBS'), ('Time UT', 'UT')]
# columns lists the column headers and attributes to show in the listing.
# If you want to include FITS keywords, be sure to include the attributes
# defined in the keywords preference (i.e., 'Time UT', 'Object')
columns = [('Type', 'icon'), ('Name', 'name'), ('Size', 'st_size_str'), ('Mode', 'st_mode_oct'), ('Last Changed', 'st_mtime_str')]
# If True, color every other row in alternating shades to improve
# readability of long tables
color_alternate_rows = True
# Maximum number of rows that will turn off auto column resizing (for speed)
max_rows_for_col_resize = 5000
Compose¶
A plugin for composing RGB images from constituent monochrome images.
Plugin Type: Local
Compose
is a local plugin, which means it is associated with a
channel. An instance can be opened for each channel.
Usage
Start the Compose
plugin from the “Operations” menu – the tab should
show up under “Dialogs”.
- Select the kind of composition you want to make from the “Compose Type” drop down: “RGB” for composing three monochrome images into a color image, “Alpha” to compose a series of images as layers with different alpha values for each layer.
- Press “New Image” to start composing a new image.
*For RGB composition*
- Drag your three constituent images that will make up the R, G, and B planes to the “Preview” window – drag them in the order R (red), G (green), and B (blue). Alternatively, you can load the images into the channel viewer one by one and after each one pressing “Insert from Channel” (similarly, do these in the order of R, G, and B).
In the plugin GUI, the R, G, and B images should show up as three slider controls in the “Layers” area of the plugin, and the Preview should show a low resolution version of how the composite image looks with the sliders set.
- Play with the alpha levels of each layer using the sliders in the
Compose
plugin; as you adjust a slider the preview image should update. - When you see something you like, you can save it to a file using the “Save As” button (use “jpeg” or “png” as the file extension), or insert it into the channel using the “Save to Channel” button.
*For Alpha composition*
For Alpha-type composition the images are just combined in the order shown in the stack, with Layer 0 being the bottom layer, and successive layers stacked on top. Each layer’s alpha level is adjustible by a slider in the same manner as discussed above.
- Drag your N constituent images that will make up the layers to the “Preview” window, or load the images into the channel viewer one by one and after each one pressing “Insert from Channel” (the first image will be at the bottom of the stack–layer 0).
- Play with the alpha levels of each layer using the sliders in the
Compose
plugin; as you adjust a slider the preview image should update. - When you see something you like, you can save it to a file using the “Save As” button (use “fits” as the file extension), or insert it into the channel using the “Save to Channel” button.
*General Notes*
- The preview window is just a ginga widget, so all the usual bindings apply; you can set color maps, cut levels, etc. with the mouse and key bindings.
PlotTable¶

A plugin to display basic plot for any two selected columns in a table.
Plugin Type: Local
PlotTable
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
PlotTable
is a plugin designed to plot any two selected columns for a given
FITS table HDU (can be accessed via MultiDim
).
For masked columns, masked data is not shown (even if only one of the
(X, Y)
pair is masked).
It is meant as a way to quickly look at table data and not for detailed
scientific analysis.
It is customizable using ~/.ginga/plugin_PlotTable.cfg
, where ~
is your HOME directory:
#
# PlotTable plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_PlotTable.cfg"
# matplotlib options for plotted line
linewidth = 1
linestyle = '-'
linecolor = 'blue'
# matplotlib options for markers
markersize = 6
markerwidth = 0.5
markerstyle = 'o'
markercolor = 'red'
# Show markers (can also be set in GUI)
show_marker = True
# Table column numbers to plot (can also be set in GUI).
# 0 = row indices, not the first table column
x_index = 1
y_index = 2
# Output file suffix (as accepted by matplotlib)
file_suffix = '.png'
Pipeline¶
Simple data reduction pipeline plugin for Ginga.
Note
This plugin is available but not loaded into Ginga reference viewer by default because it is experimental.
Plugin Type: Local
Pipeline
is a local plugin, which means it is associated with a channel.
An instance can be opened for each channel.
Usage
It is customizable using ~/.ginga/plugin_Pipeline.cfg
, where ~
is your HOME directory:
#
# Pipeline plugin preferences file
#
# Place this in file under ~/.ginga with the name "plugin_Pipeline.cfg"
num_threads = 4
ScreenShot¶

Capture PNG or JPEG images of the channel viewer image.
Usage
- Select the RGB graphics type for the snap from the “Type” combo box.
- Press “Snap” when you have the channel image the way you want to capture it.
A copy of the RGB image will be loaded into the ScreenShot
viewer.
You can pan and zoom within the ScreenShot
viewer like a normal Ginga
viewer to examine detail (e.g., see the magnified difference between
JPEG and PNG formats).
- Repeat (1) and (2) until you have the image you want.
- Enter a valid path for a new file into the “Folder” text box.
- Enter a valid name for a new file into the “Name” text box. There is no need to add the file extension; it will be added, if needed.
- Press the “Save” button. The file will be saved where you specified.
Notes
- PNG offers less artifacts for overlaid graphics, but files are larger than JPEG.
- The “Center” button will center the snap image; “Fit” will set the zoom to fit it to the window; and “Clear” will clear the image.
- Press “1” in the screenshot viewer to zoom to 100% pixels.
Customizing Ginga¶
One of the primary guiding concepts behind the Ginga project is to provide convenient ways to build custom viewers. The reference viewer embodies this concept through the use of a flexible layout engine and the use of plugins to implement all the major user interface features. By modifying or replacing the layout and adding, subclassing or removing plugins you can completely change the look, feel and operation of the reference viewer.
This chapter explains how you can customize the Ginga reference viewer in various ways, as a user or a developer.
Configuration Options¶
Ginga examines a configuration directory on startup to check for any configuration files or customization of the default behavior.
Note
The configuration area is determined first by examining the
environment variable GINGA_HOME
. If that is not set, then
$HOME/.ginga
(Mac OS X, Linux) or
$HOMEDRIVE:$HOMEPATH\\.ginga
(Windows) will be used.
Examples of the types of configuration files with comments describing the
effects of the parameters can be found in .../ginga/examples/configs
.
Many of the plugins have their own configuration file, with preferences
that are only changed via that file. You can copy an example
configuration file to your Ginga settings area and change the settings
to your liking.
Usually it is sufficient to simply close the plugin and open it again to pick up any settings changes, but some changes may require a viewer restart to take effect.
Channels also use configuration files to store many different settings
for the channel viewer windows. When a channel is created, the
reference viewer looks to see if there is a configuration file for that
channel in the configuration area; if so, the settings therein are used
to configure it. If not, the settings for the generic startup channel
“Image” are used to configure the new channel. The “Preferences” plugin
can be used to set many of the channel settings. If you set these for
the “Image” channel and use the “Save” button, other channels will
inherit them. You can also manually copy the example file from
.../ginga/examples/configs/channel_Image.cfg
to your configuration
area and edit it if you prefer.
Saving the workspace layout between sessions¶
By default, Ginga will will write its window size, position and some layout
information to a “layout” file in the configuration directory when the
program is closed. Upon a subsequent startup Ginga will attempt to
restore the window to the saved configuration. If this behavior is not
desired you can add the option save_layout = False
to your
general.cfg
file in the Ginga configuration directory.
There is a sample general.cfg
file in .../ginga/examples/configs
.
Invoking the program with the --norestore
option also prevents it from
reading the saved layout file. This may be needed in some cases when
the layout changes in an incompatible way between when the program was
last stopped and when it was started again.
Rebinding Controls¶
One configuration file that many users will be interested in is the one
controlling how keyboard and mouse/touch bindings are assigned. This is
handled by the configuration file bindings.cfg
. Several examples
are stored in .../ginga/examples/bindings
, including an example for
users familiar with the ds9 mouse controls, and an example for users
using a touchpad without a mouse (pinch zoom and scroll panning).
Simply copy the appropriate file to your Ginga settings area as
bindings.cfg
.
Customizing the Reference Viewer During Initialization¶
The reference viewer can be customized during viewer initialization
using a module called ginga_config
, which can be anywhere in the
user’s Python import path, including in the Ginga configuration folder
described above (e.g. $HOME/.ginga/ginga_config.py
).
Specifically, this file will be imported and two methods will be run if
defined: pre_gui_config(ginga_shell)
and
post_gui_config(ginga_shell)
.
The parameter to each function is the main viewer shell. These functions
can be used to define a different viewer layout, add or remove plugins,
add menu entries, add custom image or star catalogs, etc. We will refer
back to these functions in the sections below.
Workspace configuration¶
Ginga has a flexible table-driven layout scheme for dynamically creating
workspaces and mapping the available plugins to workspaces. By changing
a couple of tables via ginga_config.pre_gui_config()
you can change
the way Ginga looks and presents its content.
If you examine the module ginga.rv.main
you will find a layout table
called default_layout
:
default_layout = ['seq', {},
['vbox', dict(name='top', width=1400, height=700),
dict(row=['hbox', dict(name='menu')],
stretch=0),
dict(row=['hpanel', dict(name='hpnl'),
['ws', dict(name='left', wstype='tabs',
width=300, height=-1, group=2),
# (tabname, layout), ...
[("Info", ['vpanel', {},
['ws', dict(name='uleft', wstype='stack',
height=250, group=3)],
['ws', dict(name='lleft', wstype='tabs',
height=330, group=3)],
]
)]],
['vbox', dict(name='main', width=600),
dict(row=['ws', dict(name='channels', wstype='tabs',
group=1, use_toolbar=True)],
stretch=1),
dict(row=['ws', dict(name='cbar', wstype='stack',
group=99)], stretch=0),
dict(row=['ws', dict(name='readout', wstype='stack',
group=99)], stretch=0),
dict(row=['ws', dict(name='operations', wstype='stack',
group=99)], stretch=0),
],
['ws', dict(name='right', wstype='tabs',
width=400, height=-1, group=2),
# (tabname, layout), ...
[("Dialogs", ['ws', dict(name='dialogs', wstype='tabs',
group=2)
]
)]
],
], stretch=1),
dict(row=['ws', dict(name='toolbar', wstype='stack',
height=40, group=2)],
stretch=0),
dict(row=['hbox', dict(name='status')], stretch=0),
]]
This rather arcane-looking table defines the precise layout of the reference viewer shell, including how many workspaces it will have, their characteristics, how they are organized, and their names.
The key point in this section is that you can modify this table or
replace it entirely with one of your own design and set it in the
pre_gui_config()
method described above:
my_layout = [
...
]
def pre_gui_config(ginga_shell):
...
ginga_shell.set_layout(my_layout)
If done in the pre_gui_config()
method (as shown) the new layout will
be the one that is used when the GUI is constructed.
Format of the Layout Table¶
The table consists of a nested list of sublists, tuples and/or dictionaries. The first item in a sublist indicates the type of the container to be constructed. The following types are available:
seq
: defines a sequence of top-level windows to be createdhpanel
: a horizontal panel of containers, with handles to size themvpanel
: a vertical panel of containers, with handles to size themhbox
: a horizontal panel of containers of fixed sizevbox
: a vertical panel of containers of fixed sizews
: a workspace that allows a plugin or a channel viewer to be loaded into it. A workspace can be configured in four ways: as a tabbed notebook (wstype="tabs"
), as a stack (wstype="stack"
), as an MDI (Multiple Document Interface,wstype="mdi"
) or a grid (wstype="grid"
).widget
: a preconstructed widget passed in.
In every case the second item in the sublist is a dictionary that provides some optional parameters that modify the characteristics of the container. If there is no need to override the default parameters the dictionary can simply be empty. The optional third and following items are specifications for nested content.
All types of containers honor the following parameters:
- width: can specify a desired width in pixels for the container.
- height: can specify a desired height in pixels for the container.
- name: specifies a mapping of a name to the created container widget. The name is important especially for workspaces, as they may be referred to as an output destination when registering plugins.
Note
In the above example, we define a top-level window consisting of a vbox (named “top”) with 4 layers: a hbox (“menu”), hpanel (“hpnl”), a workspace (“toolbar”) and another hbox (“status”). The main horizontal panel of three containers: a workspace (“left”) with a width of 300 pixels, a vbox (“main”, 700 pixels) and a workspace (“right”, 400 pixels). The “left” workspace is pre-populated with an “Info” tab containing a vertical panel of two workspaces: “uleft” and “lleft” with heights of 300 and 430 pixels, respectively. The “right” workspace is pre-populated with a “Dialogs” tab containing an empty workspace. The “main” vbox is configured with three rows of workspaces: “channels”, “cbar” and “readout”.
Ginga uses some container names in special ways. For example, Ginga looks for a “channels” workspace as the default workspace for creating channels, and the “dialogs” workspace is where most local plugins are instantiated (when activated), by default. These two names should at least be defined somewhere in default_layout.
Auto-Start Plugins¶
Not all plugins provided by Ginga are automatically started up by default.
A plugin can be started automatically in post_gui_config()
using the
start_global_plugin()
or start_local_plugin()
methods, as appropriate:
def post_gui_config(ginga_shell):
# Auto start global plugins
ginga_shell.start_global_plugin('Zoom')
ginga_shell.start_global_plugin('Header')
# Auto start local plugin
ginga_shell.add_channel('Image')
ginga_shell.start_local_plugin('Image', 'Histogram', None)
Alternately, you can also start plugins via the command line interface using
--plugins
and -modules
for local and global plugins, respectively.
To load multiple plugins at once, use a comma-separated list. For example:
ginga --plugins=MyLocalPlugin,Imexam --modules=MyGlobalPlugin
Adding Plugins¶
A plugin can be added to the reference viewer in pre_gui_config()
using the add_plugin()
method with a specification (“spec”) for
the plugin:
from ginga.misc.Bunch import Bunch
def pre_gui_config(ginga_shell):
...
spec = Bunch(module='DQCheck', klass='DQCheck', workspace='dialogs',
category='Utils', ptype='local')
ginga_shell.add_plugin(spec)
The above call would try to load a local plugin called “DQCheck” from a module called “DQCheck”. When invoked from the Operations menu it would occupy a spot in the “dialogs” workspace (see layout discussion above).
Other keywords that can be used in a spec:
- Global plugins use
ptype='global'
. - If a plugin should be hidden from the menus (e.g. it is started under
program control, not by the user), specify
hidden=True
. - If the plugin should be started when the program starts, specify
start=True
. - To use a different name in the menu for starting the plugin, specify
menu="Custom Name"
. - To use a different name in the tab that is showing the plugin GUI,
specify
tab="Tab Name"
. - To prevent a control icon from appearing in the Operations plugin
manager tray specify
optray=False
.
Disabling Plugins¶
Both local and global plugins can be disabled (thus, not shown in the
reference viewer) using the --disable-plugins
option in the
command line interface. To remove multiple plugins at once,
use a comma-separated list. For example:
ginga --disable-plugins=Zoom,Compose
Alternately, plugins can also be disabled via general.cfg
configuration
file. For example:
disable_plugins = "Zoom,Compose"
Some plugins, like Operations
, when disabled, may result in
inconvenient GUI experience.
Making a Custom Startup Script¶
You can make a custom startup script to make the same reference viewer
configuration available without relying on the ginga_config
module in
a personal settings area. To do this we make use of the main
module:
import sys
from ginga.rv.main import ReferenceViewer
from optparse import OptionParser
my_layout = [ ... ]
plugins = [ ... ]
if __name__ == "__main__":
viewer = ReferenceViewer(layout=my_layout)
# add plugins
for spec in plugins:
viewer.add_plugin(spec)
# Parse command line options with optparse module
usage = "usage: %prog [options] cmd [args]"
optprs = OptionParser(usage=usage)
viewer.add_default_options(optprs)
(options, args) = optprs.parse_args(sys_argv[1:])
viewer.main(options, args)
Developing with Ginga¶
Developers interested in using Ginga in their project will probably follow one of two logical development paths:
- using Ginga toolkit classes in a program of their own design, or
- starting with the full-featured reference viewer that comes with Ginga and customizing it for some special purpose, typically by modifying one of the plugins or writing a new plugin.
The first approach is probably best for when the developer has a custom application in mind, needs a minimal but powerful viewer or wants to develop an entirely new full-featured viewer. Developers interested in this direction should head over to the chapter on the viewer object (see Using the Basic Ginga Viewer Object in Python Programs).
The second approach is probably best for end users or developers that are mostly satisfied with the reference viewer as a general purpose tool and want to add some specific enhancements or functionality. Because the reference viewer is based on a flexible plugin architecture this is fairly straightforward to do.
Writing plugins for the reference viewer¶
The philosophy behind the design of the reference viewer distributed with the Ginga is that it is simply a flexible layout shell for instantiating instances of the Ginga view widgets described in the earlier section. All of the other important pieces of a modern FITS viewer–a panning widget, information panels, zoom widget, analysis panes–are implemented as plugins: encapsulated modules that interface with the viewing shell using a standardized API. This makes it easy to customize and to add, change or remove functionality in a very modular, flexible way.
The Ginga viewer divides the application window GUI into containers that hold either viewing widgets or plugins. The view widgets are called “channels” in the viewer nomenclature, and are a means of organizing images in the viewer, functioning much like “frames” in other viewers. A channel has a name and maintains its own history of images that have cycled through it. The user can create new channels as needed. For example, they might use different channels for different kinds of images: camera vs. spectrograph, or channels organized by CCD, or by target, or raw data vs. quick look, etc. In the default layout, the channel tabs are in the large middle pane, while the plugins occupy the left and right panes. Other layouts are possible, by simply changing a table used in the startup script.
Ginga distinguishes between two types of plugin: global and local. Global plugins are used where the functionality is generally enabled during the entire session with the viewer and where the plugin is active no matter which channel is currently under interaction with the user. Examples of global plugins include a panning view (a small, bird’s-eye view of the image that shows a panning rectangle and allows graphical positioning of the pan region), a zoomed view (that shows an enlarged cutout of the area currently under the cursor), informational displays about world coordinates, FITS headers, thumbnails, etc. Figure Two global plugins: Pan (top) and Info (bottom), shown sharing a tab. shows an example of two global plugins occupying a notebook tab.
Local plugins are used for modal operations with images in specific channels. For example, the Pick plugin is used to perform stellar evaluation of objects, finding the center of the object and giving informational readings of the exact celestial coordinates, image quality, etc. The Pick plugin is only visible while the user has it open, and does not capture the mouse actions unless the channel it is operating on is selected. Thus one can have two different Pick operations going on concurrently on two different channels, for example, or a Pick operation in a camera channel, and a Cuts (line cuts) operation on a spectrograph channel. Figure The Pick local plugin, shown occupying a tab. shows an example of the Pick local plugin occupying a notebook tab.
Anatomy of a Local Ginga Plugin¶
Let’s take a look at a local plugin to understand the API for interfacing to the Ginga shell. In Listing 2, we show a stub for a local plugin.
from ginga import GingaPlugin
class MyPlugin(GingaPlugin.LocalPlugin):
def __init__(self, fv, fitsimage):
super(MyPlugin, self).__init__(fv, fitsimage)
def build_gui(self, container):
pass
def start(self):
pass
def stop(self):
pass
def pause(self):
pass
def resume(self):
pass
def redo(self):
pass
def __str__(self):
return 'myplugin'
A little more fleshed out example: MyLocalPlugin¶
This is a skeleton for a local plugin. It is also good example of something that actually runs and can be copied as a template for a local plugin. This plugin is distributed with the Ginga package and can be loaded and invoked from a terminal:
$ ginga –plugins=MyLocalPlugin –loglevel=20 –log=/tmp/ginga.log
The plugin will be accessible via the “Operation” button in the Plugin Manager bar.
from ginga import GingaPlugin
from ginga.misc import Widgets
# import any other modules you want here--it's a python world!
class MyLocalPlugin(GingaPlugin.LocalPlugin):
def __init__(self, fv, fitsimage):
"""
This method is called when the plugin is loaded for the first
time. ``fv`` is a reference to the Ginga (reference viewer) shell
and ``fitsimage`` is a reference to the specific ImageViewCanvas
object associated with the channel on which the plugin is being
invoked.
You need to call the superclass initializer and then do any local
initialization.
"""
super(MyLocalPlugin, self).__init__(fv, fitsimage)
# your local state and initialization code goes here
def build_gui(self, container):
"""
This method is called when the plugin is invoked. It builds the
GUI used by the plugin into the widget layout passed as
``container``.
This method may be called many times as the plugin is opened and
closed for modal operations. The method may be omitted if there
is no GUI for the plugin.
This specific example uses the GUI widget set agnostic wrappers
to build the GUI, but you can also just as easily use explicit
toolkit calls here if you only want to support one widget set.
"""
top = Widgets.VBox()
top.set_border_width(4)
# this is a little trick for making plugins that work either in
# a vertical or horizontal orientation. It returns a box container,
# a scroll widget and an orientation ('vertical', 'horizontal')
vbox, sw, orientation = Widgets.get_oriented_box(container)
vbox.set_border_width(4)
vbox.set_spacing(2)
# Take a text widget to show some instructions
self.msgFont = self.fv.getFont("sansFont", 12)
tw = Widgets.TextArea(wrap=True, editable=False)
tw.set_font(self.msgFont)
self.tw = tw
# Frame for instructions and add the text widget with another
# blank widget to stretch as needed to fill emp
fr = Widgets.Frame("Instructions")
vbox2 = Widgets.VBox()
vbox2.add_widget(tw)
vbox2.add_widget(Widgets.Label(''), stretch=1)
fr.set_widget(vbox2)
vbox.add_widget(fr, stretch=0)
# Add a spacer to stretch the rest of the way to the end of the
# plugin space
spacer = Widgets.Label('')
vbox.add_widget(spacer, stretch=1)
# scroll bars will allow lots of content to be accessed
top.add_widget(sw, stretch=1)
# A button box that is always visible at the bottom
btns = Widgets.HBox()
btns.set_spacing(3)
# Add a close button for the convenience of the user
btn = Widgets.Button("Close")
btn.add_callback('activated', lambda w: self.close())
btns.add_widget(btn, stretch=0)
btns.add_widget(Widgets.Label(''), stretch=1)
top.add_widget(btns, stretch=0)
# Add our GUI to the container
container.add_widget(top, stretch=1)
# NOTE: if you are building a GUI using a specific widget toolkit
# (e.g. Qt) GUI calls, you need to extract the widget or layout
# from the non-toolkit specific container wrapper and call on that
# to pack your widget, e.g.:
#cw = container.get_widget()
#cw.addWidget(widget, stretch=1)
def close(self):
"""
Example close method. You can use this method and attach it as a
callback to a button that you place in your GUI to close the plugin
as a convenience to the user.
"""
chname = self.fv.get_channel_name(self.fitsimage)
self.fv.stop_local_plugin(chname, str(self))
return True
def start(self):
"""
This method is called just after ``build_gui()`` when the plugin
is invoked. This method may be called many times as the plugin is
opened and closed for modal operations. This method may be omitted
in many cases.
"""
self.tw.set_text("""This plugin doesn't do anything interesting.""")
self.resume()
def pause(self):
"""
This method is called when the plugin loses focus.
It should take any actions necessary to stop handling user
interaction events that were initiated in ``start()`` or
``resume()``.
This method may be called many times as the plugin is focused
or defocused. It may be omitted if there is no user event handling
to disable.
"""
pass
def resume(self):
"""
This method is called when the plugin gets focus.
It should take any actions necessary to start handling user
interaction events for the operations that it does.
This method may be called many times as the plugin is focused or
defocused. The method may be omitted if there is no user event
handling to enable.
"""
pass
def stop(self):
"""
This method is called when the plugin is stopped.
It should perform any special clean up necessary to terminate
the operation. The GUI will be destroyed by the plugin manager
so there is no need for the stop method to do that.
This method may be called many times as the plugin is opened and
closed for modal operations, and may be omitted if there is no
special cleanup required when stopping.
"""
pass
def redo(self):
"""
This method is called when the plugin is active and a new
image is loaded into the associated channel. It can optionally
redo the current operation on the new image. This method may be
called many times as new images are loaded while the plugin is
active. This method may be omitted.
"""
pass
def __str__(self):
"""
This method should be provided and should return the lower case
name of the plugin.
"""
return 'mylocalplugin'
The instance variables “fv” and “fitsimage” will be assigned by the superclass initializer to self.fv and self.fitsimage–these are the reference viewer “shell” and the ginga display object respectively. To interact with the viewer you will be calling methods on one or both of these objects.
The best way to get a feel for these APIs is to look at the source of one of the many plugins distributed with Ginga. Most of them are not very long or complex. Also, a plugin can include any Python packages or modules that it wants and programming one is essentially similar to writing any other Python program.
Launching and Debugging Your Plugin¶
The easiest way to start out is to create a plugins directory under your ginga configuration area. In a terminal:
$ mkdir $HOME/.ginga/plugins
Put your plugin in there (a good one to start with is to modify the MyLocalPlugin example that comes with Ginga):
$ cd …/ginga/examples/reference-viewer $ cp MyLocalPlugin.py $HOME/.ginga/plugins/MyPlugin.py
To load it when the reference viewer starts (and add some logging to stderr as well as to a file):
$ ginga –plugins=MyPlugin –loglevel=20 –stderr –log=/tmp/ginga.log
To start the plugin from within the reference viewer, use the Plugin Manager bar just below the color and readout bars. Use the “Operation” menu to select your plugin and it should be launched in the right panel.
If you don’t see the name of your plugin in the Operation menu, then there was probably an error trying to load it. Examine the log and search for the name of your plugin–you should find some error message associated with it.
If you select your plugin from the menu, but it doesn’t launch a GUI, there may be a problem or error in the plugin file. Again, examine the log and search for the name of your plugin–you should find some error message associated with it. It may help for you to add some debugging messages to your plugin (either using self.logger.debug(“…”) or simple print statements to stdout) to gauge the progress of building the gui and plugin starting.
If the plugin launches, but encounters an error building the GUI, it should show some error messages (and probably a stack trace) in placeholders in the right panel in the container where it tried to build the GUI or possibly under the Errors tab.
Note
Ginga has a feature for quickly reloading plugins to facilitate rapid debugging cycles. If it is not already running, start the “Command” plugin from the “Plugins” menu in the menu bar. If your plugin launched (but has some error), make sure you have closed your plugin by right clicking (or Control + click on Mac touchpad) on the small box representing your plugin in the Plugin Manager bar and selecting “Stop”. In the Command plugin, use the command “reload_local <plugin_name>”–this will reload the python module representing your plugin and you should be able to immediately restart it using the Plugin Manager bar as described above (if the plugin is of the global plugin variety, use the command “reload_global” instead).
If you have edited third party modules that are included in the plugin, this will not be enough to pick up those changes.
A more complex example: The Ruler
Plugin¶
Finally, in Listing 3 we show a completed plugin for Ruler
. The
purpose of this plugin to draw triangulation (distance measurement)
rulers on the image. For reference, you may want to refer to the ruler
shown in The Ruler local plugin GUI, shown occupying a tab..
#
# Ruler.py -- Ruler plugin for Ginga reference viewer
#
from ginga import GingaPlugin
from ginga.gw import Widgets
class Ruler(GingaPlugin.LocalPlugin):
def __init__(self, fv, fitsimage):
# superclass defines some variables for us, like logger
super(Ruler, self).__init__(fv, fitsimage)
self.rulecolor = 'green'
self.layertag = 'ruler-canvas'
self.ruletag = None
self.dc = fv.getDrawClasses()
canvas = self.dc.DrawingCanvas()
canvas.enable_draw(True)
canvas.enable_edit(True)
canvas.set_drawtype('ruler', color='cyan')
canvas.set_callback('draw-event', self.wcsruler)
canvas.set_callback('draw-down', self.clear)
canvas.set_callback('edit-event', self.edit_cb)
canvas.set_draw_mode('draw')
canvas.set_surface(self.fitsimage)
canvas.register_for_cursor_drawing(self.fitsimage)
canvas.name = 'Ruler-canvas'
self.canvas = canvas
self.w = None
self.unittypes = ('arcmin', 'degrees', 'pixels')
self.units = 'arcmin'
def build_gui(self, container):
top = Widgets.VBox()
top.set_border_width(4)
vbox, sw, orientation = Widgets.get_oriented_box(container)
vbox.set_border_width(4)
vbox.set_spacing(2)
self.msgFont = self.fv.getFont("sansFont", 12)
tw = Widgets.TextArea(wrap=True, editable=False)
tw.set_font(self.msgFont)
self.tw = tw
fr = Widgets.Expander("Instructions")
fr.set_widget(tw)
vbox.add_widget(fr, stretch=0)
fr = Widgets.Frame("Ruler")
captions = (('Units:', 'label', 'Units', 'combobox'),
)
w, b = Widgets.build_info(captions, orientation=orientation)
self.w = b
combobox = b.units
for name in self.unittypes:
combobox.append_text(name)
index = self.unittypes.index(self.units)
combobox.set_index(index)
combobox.add_callback('activated', lambda w, idx: self.set_units())
fr.set_widget(w)
vbox.add_widget(fr, stretch=0)
mode = self.canvas.get_draw_mode()
hbox = Widgets.HBox()
btn1 = Widgets.RadioButton("Draw")
btn1.set_state(mode == 'draw')
btn1.add_callback('activated', lambda w, val: self.set_mode_cb('draw', val))
btn1.set_tooltip("Choose this to draw a ruler")
self.w.btn_draw = btn1
hbox.add_widget(btn1)
btn2 = Widgets.RadioButton("Edit", group=btn1)
btn2.set_state(mode == 'edit')
btn2.add_callback('activated', lambda w, val: self.set_mode_cb('edit', val))
btn2.set_tooltip("Choose this to edit a ruler")
self.w.btn_edit = btn2
hbox.add_widget(btn2)
hbox.add_widget(Widgets.Label(''), stretch=1)
vbox.add_widget(hbox, stretch=0)
spacer = Widgets.Label('')
vbox.add_widget(spacer, stretch=1)
top.add_widget(sw, stretch=1)
btns = Widgets.HBox()
btns.set_spacing(3)
btn = Widgets.Button("Close")
btn.add_callback('activated', lambda w: self.close())
btns.add_widget(btn, stretch=0)
btns.add_widget(Widgets.Label(''), stretch=1)
top.add_widget(btns, stretch=0)
container.add_widget(top, stretch=1)
def set_units(self):
index = self.w.units.get_index()
units = self.unittypes[index]
self.canvas.set_drawtype('ruler', color='cyan', units=units)
if self.ruletag is not None:
obj = self.canvas.getObjectByTag(self.ruletag)
if obj.kind == 'ruler':
obj.units = units
self.canvas.redraw(whence=3)
return True
def close(self):
chname = self.fv.get_channelName(self.fitsimage)
self.fv.stop_local_plugin(chname, str(self))
return True
def instructions(self):
self.tw.set_text("""Draw (or redraw) a line with the cursor.
Display the Zoom tab at the same time to precisely see detail while drawing.""")
def start(self):
self.instructions()
# start ruler drawing operation
p_canvas = self.fitsimage.get_canvas()
if not p_canvas.has_object(self.canvas):
p_canvas.add(self.canvas, tag=self.layertag)
self.canvas.delete_all_objects()
self.resume()
def pause(self):
self.canvas.ui_setActive(False)
def resume(self):
self.canvas.ui_setActive(True)
self.fv.showStatus("Draw a ruler with the right mouse button")
def stop(self):
# remove the canvas from the image
p_canvas = self.fitsimage.get_canvas()
try:
p_canvas.delete_object_by_tag(self.layertag)
except:
pass
self.canvas.ui_setActive(False)
self.fv.showStatus("")
def redo(self):
obj = self.canvas.get_object_by_tag(self.ruletag)
if obj.kind != 'ruler':
return True
# redraw updates ruler measurements
self.canvas.redraw(whence=3)
def clear(self, canvas, button, data_x, data_y):
self.canvas.delete_all_objects()
self.ruletag = None
return False
def wcsruler(self, surface, tag):
obj = self.canvas.get_object_by_tag(tag)
if obj.kind != 'ruler':
return True
# remove the old ruler
try:
self.canvas.delete_object_by_tag(self.ruletag)
except:
pass
# change some characteristics of the drawn image and
# save as the new ruler
self.ruletag = tag
obj.color = self.rulecolor
obj.cap = 'ball'
self.canvas.redraw(whence=3)
def edit_cb(self, canvas, obj):
self.redo()
return True
def edit_select_ruler(self):
if self.ruletag is not None:
obj = self.canvas.get_object_by_tag(self.ruletag)
self.canvas.edit_select(obj)
else:
self.canvas.clear_selected()
self.canvas.update_canvas()
def set_mode_cb(self, mode, tf):
if tf:
self.canvas.set_draw_mode(mode)
if mode == 'edit':
self.edit_select_ruler()
return True
def __str__(self):
return 'ruler'
#END
This plugin shows a standard design pattern typical to local plugins.
Often one is wanting to draw or plot something on top of the image
below. The ImageViewCanvas
widget used by Ginga allows this to be
done very cleanly and conveniently by adding a DrawingCanvas
object to the image and drawing on that. Canvases can be layered on top
of each other in a manner analogous to “layers” in an image editing
program. Since each local plugin maintains it’s own canvas, it is very
easy to encapsulate the logic for drawing on and dealing with the
objects associated with that plugin. We use this technique in the Ruler
plugin. When the plugin is loaded (refer to __init__()
method), it
creates a canvas, enables drawing on it, sets the draw type and registers a
callback for drawing events. When start()
is called it adds that canvas
to the widget. When stop()
is called it removes the canvas from the
widget (but does not destroy the canvas). pause()
disables user
interaction on the canvas and resume()
reenables that interaction.
redo()
simply redraws the ruler with new measurements taken from any new
image that may have been loaded. In the __init__()
method you will
notice a setSurface()
call that associates this canvas with a
ImageView
-based widget–this is the key for the canvas to utilize WCS
information for correct plotting.
All the other methods shown are support methods for doing the ruler
drawing operation and interacting with the plugin GUI.
Writing a Global Plugin¶
The last example was focused on writing a local plugin. Global plugins
employ a nearly identical API to that shown in Listing 2, except that
the constructor does not take a fitsimage
parameter.
pause()
and resume()
can safely be omitted. Like local plugins,
build_gui()
can be omitted if there is no GUI associated with the plugin.
A template: MyGlobalPlugin¶
This is a skeleton for a global plugin, and serves as a decent example of something that can be copied as a template for a global plugin. This plugin is distributed with the Ginga package and can be loaded and invoked from a terminal:
$ ginga –modules=MyGlobalPlugin –loglevel=20 –log=/tmp/ginga.log
The plugin will be started at program startup and can be seen in the “MyGlobalPlugin” tab in the right panel. Watch the status message as you create new channels, delete channels or load images into channels.
from ginga import GingaPlugin
from ginga.misc import Widgets
# import any other modules you want here--it's a python world!
class MyGlobalPlugin(GingaPlugin.GlobalPlugin):
def __init__(self, fv):
"""
This method is called when the plugin is loaded for the first
time. ``fv`` is a reference to the Ginga (reference viewer) shell.
You need to call the superclass initializer and then do any local
initialization.
"""
super(MyGlobalPlugin, self).__init__(fv)
# Your initialization here
# Create some variables to keep track of what is happening
# with which channel
self.active = None
# Subscribe to some interesting callbacks that will inform us
# of channel events. You may not need these depending on what
# your plugin does
fv.set_callback('add-channel', self.add_channel)
fv.set_callback('delete-channel', self.delete_channel)
fv.set_callback('active-image', self.focus_cb)
def build_gui(self, container):
"""
This method is called when the plugin is invoked. It builds the
GUI used by the plugin into the widget layout passed as
``container``.
This method could be called several times if the plugin is opened
and closed. The method may be omitted if there is no GUI for the
plugin.
This specific example uses the GUI widget set agnostic wrappers
to build the GUI, but you can also just as easily use explicit
toolkit calls here if you only want to support one widget set.
"""
top = Widgets.VBox()
top.set_border_width(4)
# this is a little trick for making plugins that work either in
# a vertical or horizontal orientation. It returns a box container,
# a scroll widget and an orientation ('vertical', 'horizontal')
vbox, sw, orientation = Widgets.get_oriented_box(container)
vbox.set_border_width(4)
vbox.set_spacing(2)
# Take a text widget to show some instructions
self.msgFont = self.fv.getFont("sansFont", 12)
tw = Widgets.TextArea(wrap=True, editable=False)
tw.set_font(self.msgFont)
self.tw = tw
# Frame for instructions and add the text widget with another
# blank widget to stretch as needed to fill emp
fr = Widgets.Frame("Status")
vbox2 = Widgets.VBox()
vbox2.add_widget(tw)
vbox2.add_widget(Widgets.Label(''), stretch=1)
fr.set_widget(vbox2)
vbox.add_widget(fr, stretch=0)
# Add a spacer to stretch the rest of the way to the end of the
# plugin space
spacer = Widgets.Label('')
vbox.add_widget(spacer, stretch=1)
# scroll bars will allow lots of content to be accessed
top.add_widget(sw, stretch=1)
# A button box that is always visible at the bottom
btns = Widgets.HBox()
btns.set_spacing(3)
# Add a close button for the convenience of the user
btn = Widgets.Button("Close")
btn.add_callback('activated', lambda w: self.close())
btns.add_widget(btn, stretch=0)
btns.add_widget(Widgets.Label(''), stretch=1)
top.add_widget(btns, stretch=0)
# Add our GUI to the container
container.add_widget(top, stretch=1)
# NOTE: if you are building a GUI using a specific widget toolkit
# (e.g. Qt) GUI calls, you need to extract the widget or layout
# from the non-toolkit specific container wrapper and call on that
# to pack your widget, e.g.:
#cw = container.get_widget()
#cw.addWidget(widget, stretch=1)
def get_channel_info(self, fitsimage):
chname = self.fv.get_channelName(fitsimage)
chinfo = self.fv.get_channelInfo(chname)
return chinfo
def set_info(self, text):
self.tw.set_text(text)
# CALLBACKS
def add_channel(self, viewer, chinfo):
"""
Callback from the reference viewer shell when a channel is added.
"""
self.set_info("Channel '%s' has been added" % (
chinfo.name))
# Register for new image callbacks on this channel's canvas
fitsimage = chinfo.fitsimage
fitsimage.set_callback('image-set', self.new_image_cb)
def delete_channel(self, viewer, chinfo):
"""
Callback from the reference viewer shell when a channel is deleted.
"""
self.set_info("Channel '%s' has been deleted" % (
chinfo.name))
return True
def focus_cb(self, viewer, fitsimage):
"""
Callback from the reference viewer shell when the focus changes
between channels.
"""
chinfo = self.get_channel_info(fitsimage)
chname = chinfo.name
if self.active != chname:
# focus has shifted to a different channel than our idea
# of the active one
self.active = chname
self.set_info("Focus is now in channel '%s'" % (
self.active))
return True
def new_image_cb(self, fitsimage, image):
"""
Callback from the reference viewer shell when a new image has
been added to a channel.
"""
chinfo = self.get_channel_info(fitsimage)
chname = chinfo.name
# Only update our GUI if the activity is in the focused
# channel
if self.active == chname:
imname = image.get('name', 'NONAME')
self.set_info("A new image '%s' has been added to channel %s" % (
imname, chname))
return True
def start(self):
"""
This method is called just after ``build_gui()`` when the plugin
is invoked. This method could be called more than once if the
plugin is opened and closed. This method may be omitted
in many cases.
"""
pass
def stop(self):
"""
This method is called when the plugin is stopped.
It should perform any special clean up necessary to terminate
the operation. This method could be called more than once if
the plugin is opened and closed, and may be omitted if there is no
special cleanup required when stopping.
"""
pass
def close(self):
self.fv.stop_global_plugin(str(self))
return True
def __str__(self):
"""
This method should be provided and should return the lower case
name of the plugin.
"""
return 'myglobalplugin'
Writing Separately Installable Plugins¶
If you want to distribute your plugin(s) as a separately installable package and have Ginga discover them when it starts up, you can use the Ginga Plugin Template to write your own package that installs plugins.
You can include as many plugins in your package as you want. You write your plugins in exactly the same way as described above, and they can be either global or local. For details, clone the repo at the link above and follow the directions in the README.
Using the Basic Ginga Viewer Object in Python Programs¶
The core design principle of the Ginga project is to make it possible to easily build powerful image viewers in Python with many possible GUI toolkits.
This chapter is for developers who want to use only the Ginga rendering class in a program of their own design (not customizing the reference viewer).
Using the basic rendering class in new programs¶
Ginga basically follows the Model-View-Controller (MVC) design pattern,
that is described in more detail in the chapter on internals
(see Ginga Internals).
The “view” classes are rooted in the base class ImageView
.
Ginga supports backends for different widget sets through various
subclasses of this class.
Typically, a developer picks a GUI toolkit that has a supported backend
(Gtk 2/3, Qt 4/5, Tk, matplotlib, HTML5 canvas) and writes a GUI program
using that widget set with the typical Python toolkit bindings and API.
Where they want a image view pane they instantiate the appropriate
subclass of ImageView
, and using the get_widget()
call extract
the native widget and insert it into the GUI layout. A reference should
also be kept to the view object, as this is typically what you will be
calling methods on to control the viewer.
Ginga does not create any additional GUI components beyond the image
pane itself, however it does provide a standard set of keyboard and
mouse bindings on the host widget that can be enabled, disabled or
changed. The user interface bindings are configurable via a pluggable
Bindings
class which constitutes the “controller” part of the MVC
design. There are a plethora of callbacks that can be registered,
allowing the user to create their own custom user interface for
manipulating the view. Of course, the developer can add many different
GUI widgets from the selected toolkit to supplement or replace these
built in controls.
Listing 1 shows a code listing for a simple graphical FITS
viewer built using the subclass ImageViewCanvas
from the module
ImageViewCanvasQt
(screenshot in Figure A simple, “bare bones” FITS viewer written in Qt.) written in
around 100 or so lines of Python. It creates a window containing an
image view and two buttons. This example will open FITS files dragged
and dropped on the image window or via a dialog popped up when clicking
the “Open File” button.
#
# example1_qt.py -- Simple FITS viewer using the Ginga toolkit and Qt widgets.
#
import sys, os
import logging
from ginga import AstroImage
from ginga.misc import log
from ginga.qtw.QtHelp import QtGui, QtCore
from ginga.qtw.ImageViewCanvasQt import ImageViewCanvas
class FitsViewer(QtGui.QMainWindow):
def __init__(self, logger):
super(FitsViewer, self).__init__()
self.logger = logger
fi = ImageViewCanvas(self.logger, render='widget')
fi.enable_autocuts('on')
fi.set_autocut_params('zscale')
fi.enable_autozoom('on')
fi.set_callback('drag-drop', self.drop_file)
fi.set_bg(0.2, 0.2, 0.2)
fi.ui_setActive(True)
fi.enable_draw(False)
self.fitsimage = fi
bd = fi.get_bindings()
bd.enable_all(True)
w = fi.get_widget()
w.resize(512, 512)
vbox = QtGui.QVBoxLayout()
vbox.setContentsMargins(QtCore.QMargins(2, 2, 2, 2))
vbox.setSpacing(1)
vbox.addWidget(w, stretch=1)
hbox = QtGui.QHBoxLayout()
hbox.setContentsMargins(QtCore.QMargins(4, 2, 4, 2))
wopen = QtGui.QPushButton("Open File")
wopen.clicked.connect(self.open_file)
wquit = QtGui.QPushButton("Quit")
wquit.clicked.connect(self.quit)
hbox.addStretch(1)
for w in (wopen, wquit):
hbox.addWidget(w, stretch=0)
hw = QtGui.QWidget()
hw.setLayout(hbox)
vbox.addWidget(hw, stretch=0)
vw = QtGui.QWidget()
self.setCentralWidget(vw)
vw.setLayout(vbox)
def load_file(self, filepath):
image = AstroImage.AstroImage(logger=self.logger)
image.load_file(filepath)
self.fitsimage.set_image(image)
self.setWindowTitle(filepath)
def open_file(self):
res = QtGui.QFileDialog.getOpenFileName(self, "Open FITS file",
".", "FITS files (*.fits)")
if isinstance(res, tuple):
fileName = res[0]
else:
fileName = str(res)
if len(fileName) != 0:
self.load_file(fileName)
def drop_file(self, fitsimage, paths):
fileName = paths[0]
self.load_file(fileName)
def quit(self, *args):
self.logger.info("Attempting to shut down the application...")
self.deleteLater()
def main(options, args):
app = QtGui.QApplication(sys.argv)
# ginga needs a logger.
# If you don't want to log anything you can create a null logger by
# using null=True in this call instead of log_stderr=True
logger = log.get_logger("example1", log_stderr=True)
w = FitsViewer(logger)
w.resize(524, 540)
w.show()
app.setActiveWindow(w)
w.raise_()
w.activateWindow()
if len(args) > 0:
w.load_file(args[0])
app.exec_()
if __name__ == '__main__':
main(None, sys.argv[1:])
Looking at the constructor for this particular viewer, you can see where
we create a ImageViewCanvas
object. On this object we enable automatic
cut levels (using the ‘zscale’ algorithm), configure it to auto zoom the
image to fit the window and set a callback function for files dropped on
the window. We extract the user-interface bindings with
get_bindings()
, and on this object enable standard user interactive
controls for all the possible key and mouse operations.
We then extract the platform-specific widget (Qt-based, in this case) using
get_widget()
and pack it into a Qt container along with a couple of
buttons to complete the viewer.
Scanning down the code a bit, we can see that whether by dragging and
dropping or via the click to open, we ultimately call the load_file()
method to get the data into the viewer. As shown, load_file creates
an AstroImage
object (the “model” part of our MVC design). It then
passes this object to the viewer via the set_image() method.
AstroImage
objects have methods for ingesting data via a file path, an
astropy.io.fits
HDU or a bare Numpy
data array.
Many of these sorts of examples for all supported backends are contained
in the examples
directory in the source distribution.
For a list of many methods provided by the viewer object, click on the
module index link at the top of this chapter and then click on the link
for ImageViewBase
.
Graphics plotting with Ginga¶
An ImageViewCanvas
actually combines a view with a canvas object (in
particular a DrawingCanvas
object). You can get more detail about
canvases and the objects they support (see Ginga Canvas Graphics).
A variety of graphical shapes are available, and plotted objects scale,
transform and rotate seamlessly with the viewer.
Rendering into Matplotlib Figures¶
Ginga can also render directly into a Matplotlib Figure, which opens up possibilities for overplotting beyond the limited capabilities of the Ginga canvas items. See the examples under “examples/matplotlib” for ideas, particularly “example4_mpl.py”.
Rendering into HTML5 canvases¶
Ginga can render onto HTML5 canvases displayed in a web browser. This opens up interesting possibilities for server-based remote viewing tools. See the examples under “examples/pg”, particularly “example2_pg.py”.
Writing widget toolkit independent code¶
You can write code that allows the widget set to be abstracted by Ginga’s widget wrappers. This is the same technique used to allow the reference viewer to switch between supported toolkits using the “-t” command line option. Currently only Qt (4/5), Gtk (2/3), and HTML5 (to a more limited degree) are supported, and there are some limitations compared to developing using a native toolkit directly. Nevertheless, the ability to target different platforms just by changing a command line option is a very interesting proposition.
See the examples under “examples/gw”, particularly “example2.py”.
Ginga Internals¶
This chapter explains the secret inner workings of Ginga and its classes so that you can subclass them and use them in your own applications.
Introduction¶
Ginga uses a version of the Model-View-Controller design pattern. The MVC pattern spells out a division of responsibilities and encapsulation where the Model provides various ways to access and interface to the data, the View provides ways to display the data and the Controller provides the methods and user interface hooks for controlling the view.
The Model¶
The Model classes are rooted in the base class BaseImage
. The basic
interface to the data is expected to be a Numpy-like array object that is
obtained via the get_data()
method on the model. It also provides
methods for obtaining scaled, cutouts and transformed views of the data,
and methods for getting and setting key-value like metadata.
There are two subclasses defined on BaseImage: RGBImage
and
AstroImage
. RGBImage is used for displaying 3 channel RGB type
images such as JPEG, TIFF, PNG, etc. AstroImage is the subclass used to
represent astronomical images and its organization is shown in
Figure Hierarchy of Ginga AstroImage class. It has two delegate objects devoted to
handling World Coordinate System transformations and file IO.
There is also a mixin class, LayerImage
that can be used to create
layered images with alpha compositing on each layer.
New models can be created, subclassing from BaseImage or AstroImage.
As long as the model
duck types like a BaseImage
it can be loaded into a view object with the set_image()
method.
AstroImage provides convenience methods for accessing WCS information
that may be necessary when using the model in canvas subclasses of a
View that allow graphics drawing.
The View¶
Figure Class structure of Ginga basic widget viewer shows the class inheritance of the ImageViewZoom class, which is a typical end class to use in a program if one is not planning to do any graphical overplotting. The figure key indicates the base class verses the widget specific classes.
The View classes are rooted in the base class ImageView
, which
handles image display, scaling (zooming), panning, manual cut levels,
auto cut levels, color mapping, transformations, and rotation.
The ImageView is quite powerful compared to base classes in most
inheritance designs, as it actually renders the view all the way out to
RGB image planes in the appropriate sizes for the widget target window.
Ginga supports “backends” for different widget sets (Gtk, Qt, Tk,
etc.) through various subclasses of this base class, which do the actual
painting of the resulting RGB image into a widget in the native widget set.
In this example, ImageViewXYZ
is a class that renders to a native
widget in the “XYZ” toolkit. ImageViewEvent
adds event handlers for
various pointing and keyboard events, but without connecting them to any
particular handling scheme. Finally, ImageViewZoom
provides a
concrete implementation of event handling by connecting the handlers in
the ImageViewEvent class with the logic in the BindingMapper
and
Bindings
delegate objects as will as some logic in the UIMixin
class. This event handling scheme is described in more detail in the
section on the Controller. With this layered class construction, it is
possible to minimize the widget specific code and reuse a large amount
of code across widget sets and platforms.
Because the vast majority of work is done in the base class, and the
outer classes simply inherit the widget-specific ones and mix in the
others, it is a fairly simple matter to port the basic Ginga
functionality to a new widget set. All that is required is that the new
widget set have some kind of native widget that supports painting an RGB
image (like a canvas or image widget) and a way to register for user
interaction events on that widget.
The Controller¶
The control interface is a combination of methods on the view object and
a pluggable Bindings
class which handles the mapping of user input
events such as mouse, gesture and keystrokes into commands on the view.
There are many callback functions that can be registered,
allowing the user to create their own custom user interface for
manipulating the view.
Graphics on Ginga¶
Ginga’s graphics are all rendered from objects placed on a
DrawingCanvas
. All objects that can be put on a DrawingCanvas
are rooted in the CanvasObject
type (including DrawingCanvas
itself).
Miscellaneous Topics¶
I want to use my own World Coordinate System!¶
No problem. Ginga encapsulates the WCS behind a pluggable object used in the AstroImage class. Your WCS should implement this abstract class:
def MyWCS(object):
def __init__(self, logger):
self.logger = logger
def get_keyword(self, key):
return self.header[key]
def get_keywords(self, *args):
return map(lambda key: self.header[key], args)
def load_header(self, header, fobj=None):
pass
def pixtoradec(self, idxs, coords='data'):
# calculate ra_deg, dec_deg
return (ra_deg, dec_deg)
def radectopix(self, ra_deg, dec_deg, coords='data', naxispath=None):
# calculate x, y
return (x, y)
def pixtosystem(self, idxs, system=None, coords='data'):
return (deg1, deg2)
def datapt_to_wcspt(self, datapt, coords='data', naxispath=None):
return [[ra_deg_0, dec_deg_0], [ra_deg_1, dec_deg_1], ...,
[ra_deg_n, dec_deg_n]]
def wcspt_to_datapt(self, wcspt, coords='data', naxispath=None):
return [[x0, y0], [x1, y1], ..., [xn, yn]]
To use your WCS with Ginga create your images like this:
from ginga.AstroImage import AstroImage
AstroImage.set_wcsClass(MyWCS)
...
image = AstroImage()
...
view.set_image(image)
or you can override the WCS on a case-by-case basis:
from ginga.AstroImage import AstroImage
...
image = AstroImage(wcsclass=MyWCS)
...
view.set_image(image)
You could also subclass AstroImage or BaseImage and implement your own WCS handling. There are certain methods in AstroImage used for graphics plotting and plugins, however, so these would need to be supported if you expect the same functionality.
I want to use my own file storage format, not FITS!¶
No problem. Ginga encapsulates the io behind a pluggable object used in the AstroImage class. You should implement this abstract class:
class MyIOHandler(object):
def __init__(self, logger):
self.logger = logger
def register_type(self, name, klass):
self.factory_dict[name.lower()] = klass
def load_file(self, filespec, numhdu=None, dstobj=None, **kwdargs):
# create object of the appropriate type, usually
# an AstroImage or AstroTable, by looking up the correct
# class in self.factory_dict, under the keys 'image' or
# 'table'
return dstobj
def save_as_file(self, path, data, header, **kwdargs):
pass
The save_as_file
method is optional if you will never need to save
a modified file from Ginga.
To use your io handler with Ginga create your images like this:
from ginga.AstroImage import AstroImage
AstroImage.set_ioClass(MyIOHandler)
...
image = AstroImage()
image.load_file(path)
...
view.set_image(image)
or you can override the io handler on a case-by-case basis:
from ginga.AstroImage import AstroImage
...
image = AstroImage(ioclass=MyIOHandler)
image.load_file(path)
...
view.set_image(image)
You could also subclass AstroImage or BaseImage and implement your own I/O handling.
Note
Both naxispath
and numhdu
are valid keyword arguments to
the load_file() method.
You probably want to treat numhdu
as a kind of index into
your file, similarly to the meaning within a FITS file
(although you are free also to ignore it!).
If the user passes a valid numhdu (whatever that means to your load_file method) you simply return that value that they passed as the middle element of the return tuple. If they passed None (default), then you return the index you used to access the data area that you loaded.
You probably want to treat naxispath
as any kind of path
that you would need to take to navigate through your kind of
data area selected by numhdu (above). This is usually used to
describe the path through a data cube of N-dimensionality to
reach a 2D slice.
If the user passes a valid naxispath (whatever that means to your load_file method) you simply return that value that they passed. If they passed None (default), then you return whatever path you used to access the data slice that you returned.
Porting Ginga to a New Widget Set¶
[TBD]
Optimizing Ginga’s Performance¶
There are several ways to optimize the performance of certain aspects of Ginga’s operation.
OpenCL Acceleration¶
Ginga includes support for OpenCL accelerated array operations for some operations (e.g. rotation). This support is not enabled by default.
To enable OpenCL support, install the pyopencl
module, e.g.:
$ pip install pyopencl
If you are building your own program using a ginga viewer widget, simply enable the support by:
from ginga import trcalc
trcalc.use('opencl')
If you are using the reference viewer, you can add the command line
option --opencl
to enable support.
Alternatively, you can add the following line to your Ginga general options configuration file
($HOME/.ginga/general.cfg
):
use_opencl = True
Note
pyopencl
may prompt you if it can’t figure out which device
is the obvious choice to use as for hardware acceleration. If
so, you can set the PYOPENCL_CTX
variable to prevent being
prompted in the future.
Example of being prompted by pyopencl
package:
$ ginga
NVIDIA: no NVIDIA devices found
Choose platform:
[0] <pyopencl.Platform 'Intel(R) OpenCL' at 0x2d95fd0>
[1] <pyopencl.Platform 'Clover' at 0x7f13f3ffcac0>
Choice [0]:
Set the environment variable PYOPENCL_CTX='' to avoid
being asked again.
OpenCv Acceleration¶
Ginga includes support for OpenCv accelerated operations (e.g. rotation and rescaling). This support is not enabled by default.
To enable OpenCv support, install the python opencv
module (you can
find it here).
If you are building your own program using a ginga viewer widget, simply enable the support by:
from ginga import trcalc
trcalc.use('opencv')
If you are using the reference viewer, you can add the command line
option --opencv
to enable support.
Alternatively, you can add the following line to your Ginga general options configuration file
($HOME/.ginga/general.cfg
):
use_opencv = True
numexpr Acceleration¶
Ginga can use the numexpr
package to speed up rotations. However,
this is only used if the OpenCL and OpenCv optimizations are not being
used and the performance gain is not nearly as dramatic as with the
latter.
To enable numexpr
acceleration, simply install the package, e.g.:
$ pip install numexpr
It will be automatically detected and used when appropriate.
Reference/API¶
ginga.canvas.CanvasMixin Module¶
Classes¶
CanvasMixin () |
A CanvasMixin is combined with the CompoundMixin to make a tag-addressible canvas-like interface. |
ginga.canvas.CanvasObject Module¶
Functions¶
get_canvas_type (name) |
|
get_canvas_types () |
|
register_canvas_type (name, klass) |
|
register_canvas_types (klass_dict) |
Classes¶
CanvasObjectBase (**kwdargs) |
This is the abstract base class for a CanvasObject. |
ginga.canvas.CompoundMixin Module¶
Classes¶
CompoundMixin () |
A CompoundMixin is a mixin class that makes an object that is an aggregation of other objects. |
ginga.canvas.coordmap Module¶
Classes¶
NativeMapper (viewer) |
A coordinate mapper that maps to the viewer’s canvas in the viewer’s canvas coordinates. |
WindowMapper (viewer) |
A coordinate mapper that maps to the viewer in ‘window’ coordinates. |
CartesianMapper (viewer) |
A coordinate mapper that maps to the viewer in Cartesian coordinates that do not scale (unlike DataMapper). |
DataMapper (viewer) |
A coordinate mapper that maps to the viewer in data coordinates. |
OffsetMapper (viewer, refobj) |
A coordinate mapper that maps to the viewer in data coordinates that are offsets relative to some other reference object. |
WCSMapper (viewer) |
A coordinate mapper that maps to the viewer in WCS coordinates. |
ginga.canvas.DrawingMixin Module¶
Classes¶
DrawingMixin () |
The DrawingMixin is a mixin class that adds drawing capability for some of the basic CanvasObject-derived types. |
ginga.canvas.types.layer Module¶
Classes¶
CompoundObject (*objects, **kwdargs) |
Compound object on a ImageViewCanvas. |
Canvas (*objects, **kwdargs) |
Class to handle canvas in Ginga. |
DrawingCanvas (**kwdargs) |
Drawing canvas. |
Class Inheritance Diagram¶
ginga.ImageView Module¶
This module handles image viewers.
Classes¶
ImageViewBase ([logger, rgbmap, settings]) |
An abstract base class for displaying images represented by Numpy data arrays. |
ginga.rv.main Module¶
This module handles the main reference viewer.
Classes¶
ReferenceViewer ([layout]) |
This class exists solely to be able to customize the reference viewer startup. |
ginga.util.wcsmod Package¶
We are fortunate to have several possible choices for a python WCS package compatible with Ginga: astlib, kapteyn, starlink and astropy. kapteyn and astropy wrap Mark Calabretta’s “WCSLIB”, astLib wraps Jessica Mink’s “wcstools”, and I’m not sure what starlink uses (their own?).
Note that astlib requires pyfits (or astropy) in order to create a WCS object from a FITS header.
To force the use of one, do:
from ginga.util import wcsmod
wcsmod.use('kapteyn')
before you load any images. Otherwise Ginga will try to pick one for you.
Note that you can register custom WCS types using:
from ginga.util.wcsmod.common import register_wcs
register_wcs('mywcs', MyWCSClass, list_of_coord_types)
Look at the implemented WCS wrappers for details.
ginga.util.wcs Module¶
This module handles calculations based on world coordinate system.
Functions¶
hmsToDeg (h, m, s) |
Convert RA hours, minutes, seconds into an angle in degrees. |
dmsToDeg (sign, deg, min, sec) |
Convert dec sign, degrees, minutes, seconds into a signed angle in degrees. |
decTimeToDeg (sign_sym, deg, min, sec) |
Convert dec sign, degrees, minutes, seconds into a signed angle in degrees. |
degToHms (ra) |
Converts the ra (in degrees) to HMS three tuple. |
degToDms (dec[, isLatitude]) |
Convert the dec, in degrees, to an (sign,D,M,S) tuple. |
arcsecToDeg (arcsec) |
Convert numeric arcseconds (aka DMS seconds) to degrees of arc. |
hmsStrToDeg (ra) |
Convert a string representation of RA into a float in degrees. |
dmsStrToDeg (dec) |
Convert a string representation of DEC into a float in degrees. |
raDegToString (ra_deg[, format]) |
|
decDegToString (dec_deg[, format]) |
|
trans_coeff (eq, x, y, z) |
This function is provided by MOKA2 Development Team (1996.xx.xx) and used in SOSS system. |
eqToEq2000 (ra_deg, dec_deg, eq) |
Convert Eq to Eq 2000. |
get_xy_rotation_and_scale (header) |
CREDIT: See IDL code at http://www.astro.washington.edu/docs/idl/cgi-bin/getpro/library32.html?GETROT |
get_rotation_and_scale (header[, skew_threshold]) |
Calculate rotation and CDELT. |
get_relative_orientation (image, ref_image) |
Computes the relative orientation and scale of an image to a reference image. |
simple_wcs (px_x, px_y, ra_deg, dec_deg, …) |
Calculate a set of WCS keywords for a 2D simple instrument FITS file with a ‘standard’ RA/DEC pixel projection. |
deg2fmt (ra_deg, dec_deg, format) |
Format coordinates. |
dispos (dra0, decd0, dra, decd) |
Compute distance and position angle solving a spherical triangle (no approximations). |
deltaStarsRaDecDeg1 (ra1_deg, dec1_deg, …) |
Spherical triangulation. |
deltaStarsRaDecDeg2 (ra1_deg, dec1_deg, …) |
|
get_starsep_RaDecDeg (ra1_deg, dec1_deg, …) |
Calculate separation. |
add_offset_radec (ra_deg, dec_deg, …) |
Algorithm to compute RA/Dec from RA/Dec base position plus tangent plane offsets. |
get_RaDecOffsets (ra1_deg, dec1_deg, ra2_deg, …) |
Calculate offset. |
lon_to_deg (lon) |
Convert longitude to degrees. |
lat_to_deg (lat) |
Convert latitude to degrees. |
Some training videos are available in the downloads page on Github.
Be sure to also check out the Ginga wiki.
Bug Reports¶
Please file an issue with the issue tracker on Github.
Ginga has a logging facility, and it would be most helpful if you can invoke Ginga with the logging options to capture any logged errors:
$ ginga --loglevel=20 --log=ginga.log
If the difficulty is with non-display or non-working World Coordinate System (WCS) for a particular image file please be ready to supply the file for our aid in debugging.
Developer Info¶
In the source code examples/*
directories, see example{1,2}_gtk.py
(Gtk),
example{1,2}_qt.py
(Qt), example{1,2}_tk.py
(Tk) or
example{1,2,3,4,5}_mpl.py
(Matplotlib).
There is more information for developers in the The Ginga Viewer and Toolkit Manual.
See also the Module Index for a complete list of the available modules.
Etymology¶
“Ginga” is the romanized spelling of the Japanese word “銀河” (Hiragana: ぎんが), meaning “galaxy” (in general) and, more familiarly, the Milky Way. This viewer was written by software engineers at Subaru Telescope, National Astronomical Observatory of Japan—thus the connection.
Pronunciation¶
Ginga the viewer may be pronounced “ging-ga” (proper Japanese) or “jing-ga” (perhaps easier for Westerners). The latter pronunciation has meaning in the Brazilian dance/martial art Capoeira: a fundamental rocking or back and forth swinging motion. Pronunciation as “jin-ja” is considered poor form.