Ginga Image Viewer Operations
This chapter describes the operations supported by the basic Ginga image viewer and how to access them programatically.
Manipulating the view programatically
The sections below describe how to manipulate the view programatically.
For all of these API examples we assume the viewer object is contained
in variable v
. One way to create one:
>>> from ginga import toolkit
>>> toolkit.use('qt5')
>>> from ginga.gw import Viewers
>>> from ginga.misc import log
>>> logger = log.get_logger("viewer1", log_stderr=True, level=40)
>>> v = Viewers.CanvasView(logger=logger)
Many of the API calls simply set a value in the viewer’s settings object; if so, we note the associated keyword for that setting.
Loading the Viewer
The image viewer can load data in a number of formats, but all formats are wrapped with a class that corresponds to the model part of the model-view-controller design used by Ginga. For more information on creating an image wrapper object, see Image Data Wrappers.
Once you have successfully loaded an image wrapper, you can set it into the image viewer:
>>> v.set_image(img)
Scaling
In Ginge lexicon, “scaling” is setting a precise scale factor for pixels. For example a scale factor of 2.0 means that two pixels are shown in the viewer for every one pixel of data.
Ginga allows different scale factors for the X and Y axes.
Set a precise scale for X and Y:
>>> v.set_scale((0.5, 0.5))
Note
Corresponds to the viewer setting scale
.
Get the scale for X and Y:
>>> v.get_scale_xy()
(0.5, 0.5)
If the scale factors are always set to the same value and adjusted equally in tandem, then you can obtain the general scale value as:
>>> v.get_scale_max()
0.5
Scaling Limits
Ginga places a limit on the scale when the scale would result in an aberrant viewing condition. For example, it will cease to increase the scale when the pixel size approaches the window size.
Ginga has a feature for setting arbitrary hard limits on the minimum and maximum scale.
To get the scale limits (returns minimum and maximum scale):
>>> v.get_scale_limits()
(1e-05, 10000.0)
To set the scale limits:
>>> v.set_scale_limits(min_scale, max_scale)
The limits apply to all dimensions. A value of None
(the default)
means that no artificial limit will be imposed.
Zooming
Although Ginga uses scale factors to accomplish image scaling, it also supports the concept of zooming via levels. It does this by mapping a zoom level to a scale factor according to the zoom algorithm (see following section) in use.
Zoom algorithms assume that a 1:1 scale is always zoom level 0. Providing a negative zoom level zooms “out” (smaller scale) while a positive value zooms “in” (larger scale).
Set a zoom level:
>>> v.zoom_to(4)
Zoom in one level:
>>> v.zoom_in()
Zoom out three levels:
>>> v.zoom_out(3)
Zoom so that the loaded image fits the window:
>>> v.zoom_fit()
Get the current zoom level corresponding to the current scale:
>>> v.get_zoom()
-8.544
Note
Zoom levels need not be integers, and there should be an invertable mapping between scale and zoom level defined by the zoom algorithm.
Zoom Algorithms
There are two main zoom algorithms, “step” and “rate”, for determining zoom levels and corresponding scales. The step algorithm just zooms in integer multiples of the pixels: 1, 2, 3, 4, … or 1/2, 1/3, 1/4, etc. The rate algorithm simply applies a multiplier to the current scale to arrive at the new scale. This can be more appropriate to achieve a faster (or slower) rate of zoom than stepping.
Get the zoom algorithm in use:
>>> v.get_zoom_algorithm()
'step'
Set the zoom algorithm:
>>> v.set_zoom_algorithm('rate')
Note
Corresponds to the viewer setting zoom_algorithm
.
Get the zoom rate:
>>> v.get_zoomrate()
1.4142135623730951
Set the zoom rate:
>>> v.set_zoomrate(1.1)
Note
Corresponds to the viewer setting zoom_rate
.
The zoom rate should be defined as a value greater than 1.
This value is ignored when the “step” algorithm is in use.
Panning
The “pan position” defines the point on which the viewer should be centered. Normally this is specified in data coordinates, but it can also be specified in world coordinates if a valid WCS is available in an image that is loaded.
Get the pan position in data coordinates (the default):
>>> v.get_pan()
(1136.0, 2136.5)
Set the pan position:
>>> v.set_pan((500.0, 1500.0))
Get the pan position in world coordinates (in this case, degrees):
>>> v.get_pan(coord='wcs')
(300.16929984148425, 22.80602873666544)
Set the pan position in world coordinates:
>>> v.set_pan((298.21, 24.6), coord='wcs')
Note
Corresponds to the viewer settings pan
and pan_coord
.
Pan to 25% of the X axis and 75% of the Y axis:
>>> v.panset_pct(0.25, 0.75)
Center the image (i.e., pan to center):
>>> v.center_image()
Get the coordinates in the actual data corresponding to the area shown in the display for the current zoom level and pan:
>>> v.get_pan_rect()
array([[ 886. , 1886.5],
[ 886. , 2386.5],
[1386. , 2386.5],
[1386. , 1886.5]])
The values are returned as corners lower-left, upper-left, upper-right, lower-right.
Transforms
The Ginga viewer provides three quick transforms in addition to rotation (described below). These are flipping in the X axis, flipping in the Y axis, and swapping axes. These three transforms can be set in a single call, with three booleans, in the order just listed.
Flip the view in the X dimension:
>>> v.transform(True, False, False)
Flip the view in the Y dimension:
>>> v.transform(False, True, False)
Flip the view in the X dimension and swap the X and Y axes:
>>> v.transform(True, False, True)
Get the existing transforms:
>>> v.get_transforms()
(True, False, True)
Note
Corresponds to the viewer settings flip_x
, flip_y
and
swap_xy
.
Attempt to orient the viewer according to the image loaded (may set transforms to accomplish this):
>>> v.auto_orient()
Rotation
The Ginga viewer can also rotate the image. Values are specified in degrees.
Rotate the view 45 degrees:
>>> v.rotate(45.0)
Get current rotation:
>>> v.get_rotation()
45.0
Note
Corresponds to the viewer setting rot_deg
.
Cut Levels
The cut levels are Ginga’s lexicon for the low and high values used to establish the mapping from data values to the minimum and maximum pixel luminance values in the viewer. Values in the data below the low cut value will be driven to the bottom luminance value and values above the high cut value will be driven to the top luminance value. The values in between are scaled to the range between these values.
Setting cut levels on the viewer:
>>> v.cut_levels(lo_val, hi_val)
Get current cut levels:
>>> v.get_cut_levels()
(440.6118816303353, 606.8032622632695)
Note
Corresponds to the viewer setting cuts
.
Auto cut levels
Calculating and applying an auto cut levels (aka “auto levels”), using the current algorithm setting and parameters:
>>> v.auto_levels()
Find out what automatic cut levels algorithms are available:
>>> v.get_autocut_methods()
('minmax', 'median', 'histogram', 'stddev', 'zscale')
Set viewer to use a specific algorithm, with parameters:
>>> v.set_autocut_params('histogram', pct=0.90)
Note
Every auto cuts algorithm is encapsulated into an auto cuts class. The parameters can vary according to the parameters of the algorithm and are passed as keyword parameters to this call.
Retrieve the current autocuts object:
>>> v.autocuts
<ginga.AutoCuts.Histogram at 0x7fb404a19dd8>
Explicitly set the autocuts object directly:
>>> from ginga.AutoCuts import ZScale
>>> ac = ZScale(v.get_logger(), contrast=0.4)
>>> v.set_autocuts(ac)
Note
Unless you are using a custom autocuts class it is generally easier to just use the set_autocut_params() method.
Color Distribution
The color distribution algorithm distributes the values in the image after the cut levels to the colors defined by the color map. This normally describes a mapping curve such as linear, logarithmic, etc.
Find out what color distribution algorithms are available:
>>> v.get_color_algorithms()
['linear', 'log', 'power', 'sqrt', 'squared', 'asinh', 'sinh', 'histeq']
Set a specific color distribution algorithm:
>>> v.set_color_algorithm('log')
Find out which one is being used:
>>> v.get_settings().get('color_algorithm')
'log'
Color Map
Find out what color maps are available:
>>> from ginga import cmap
>>> cmap.get_names()
['Accent',
'Accent_r',
'afmhot',
'afmhot_r',
...
'YlOrBr_r',
'YlOrRd',
'YlOrRd_r']
Set a color map:
>>> v.set_color_map('YlOrBr_r')
Find out which one is being used:
>>> v.get_settings().get('color_map')
'YlOrBr_r'
Enable matplotlib color maps to be available (if matplotlib
is installed):
>>> cmap.add_matplotlib_cmaps()
Invert the color map:
>>> v.invert_cmap()
Shift the color map by pct
percent:
>>> v.shift_cmap(0.2)
Stretch/shrink and shift color map:
>>> v.scale_and_shift_cmap(scale_pct, shift_pct)
Intensity Map
Note
Intensity maps are a feature that largely duplicates the functionality of color distributions (see above). It performs a remapping of the colors after the color mapping phase has been applied. We suggest that most users will want to leave the default setting of ‘ramp’, which is leaves the color map as is.
Find out what intensity maps are available:
>>> from ginga import imap
>>> imap.get_names()
['equa',
'expo',
'gamma',
'jigsaw',
'lasritt',
'log',
'neg',
'neglog',
'null',
'ramp',
'stairs',
'ultrasmooth']
Set an intensity map:
>>> v.set_intensity_map('lasritt')
Find out which one is being used:
>>> v.get_settings().get('intensity_map')
'lasritt'
Auto configuration
Ginga has some settings that control whether certain initializations are performed when a new image is set in the viewer.
Enable auto orientation of new image (see auto_orient()
under
“Transforms”):
>>> v.enable_auto_orient(True)
Note
Corresponds to the viewer setting auto_orient
.
Enable auto centering (pan to center of new image):
>>> v.enable_autocenter('on')
Note
Corresponds to the viewer setting autocenter
.
Enable auto cuts (calculate and set cut levels of new image):
>>> v.enable_autocuts('on')
Note
Corresponds to the viewer setting autocuts
.
Enable auto zoom (scale to fit new image to window):
>>> v.enable_autozoom('on')
Note
Corresponds to the viewer setting autozoom
.
The autocenter, autocuts, and autozoom settings allow the following values:
‘on’: apply to every new image
‘once’: apply to the first image set only, then turn ‘off’
‘override’: apply to each image until the user overrides manually, then turn ‘off’, and
‘off’: never apply
Miscellaneous Operations
Set the background color of the viewer:
>>> v.set_bg(0.2, 0.2, 0.2)
Note
Corresponds to the viewer setting color_bg
.
Set the foreground color of the viewer (used for some text overlays):
>>> v.set_fg(0.8, 0.9, 0.7)
Note
Corresponds to the viewer setting color_fg
.
Put a message onscreen for 2 seconds:
>>> v.onscreen_message("Hello, world!", delay=2.0)
Get the last position of the cursor in data coordinates:
>>> v.get_last_data_xy()
(782.4466094067262, 2136.5)
Whether the viewer widget should take focus when the cursor enters the window:
>>> v.set_enter_focus(True)
Note
Corresponds to the viewer setting enter_focus
.
Get the bounding box of viewer extents (returns lower-left and upper-right corners of the bounding box):
>>> v.get_limits()
((0.0, 0.0), (2272.0, 4273.0))
Note
Normally the limits are defined by an image that is loaded, if any. But they can also be overridden, as shown below.
Set explicit limits for the viewer:
>>> v.set_limits(((250.0, 250.0), (2500.0, 2500.0)))
Note
Corresponds to the viewer setting limits
.