Skip to content

Commit

Permalink
Refactor and unify the interface for the raster image, contours, and …
Browse files Browse the repository at this point in the history
…vector overlay. (#123)

* Add apply_vector_overlay and clear_vector_overlay

* Add set_vector_overlay_color and set_vector_overlay_colormap

* Minor modification

* Add configure_vector_overlay

* Minor modification for comments

* Deduce pixel_averaging_enabled and threshold_enabled

* Deduce debiasing and modify description

* Minor modification

* Add set_style plot set_visible show hide for vector overlay

* Minor modification

* Modify plot_vector_overlay

* Minor modification

* Modify setIntensityRange and setLengthRange

* Modification of setting intensity range in set_vector_overlay_style

* Monor modification

* Replace None with non-empty string

* Adopt macro in configure_vector_overlay

* Modification to set_vector_overlay_style

* Modify plot_vector_overlay

* Logic modification to set_vector_overlay_style

* Minor modification to description

* Modify validate check for intensity_max and intensity_min

* Move bias and contrast fom set_colormap to set_scaling

* Update outdated syntax

* Add Undefined class in util

* Simplify intensity_min and intensity_max definition

* Modification to description and setIntensityRange logic

* Description modified

* Add colormap default description

* Add default value for color

* Format fix

* Fix complaint in latest flake8

* Make all parameters to set_scaling optional; set alpha and gamma regardless of scaling parameter; require Auto.AUTO to reset contrast and bias, otherwise leave unmodified

* Updated descriptions for alpha and gamma

* Added some min/max validation; added unit tests

* formatting pass and flake8 fix

* Added some magic for specifying optional and repeated validation parameters more cleanly. Did some refactoring for legibility. Still to be tested.

* Some tests; minor fixes and refactoring

* Simplified optional parameters

* Moved vector overlay functions to sub-object.

* Refactored plot function to avoid unnecessary calls. Completed vector overlay tests.

* Added check for subobjects on image

* Added missing module to docs.

* First pass to split up image subobjects. Contour and raster tests to be completed. Refactored tests to reuse common fixtures.

* Removed unnecessary fixture

* Refactored raster functions. Moved contours histogram flag to contours class. Completed unit tests for raster.

* formatting pass

* Finished refactoring vector overlay and test. Added helper function for copying validation parameters from other functions.

* Refactored contours and added contour tests

* Factored WCS overlay functions out of session and into subobject

* Moved WCS overlay settings out of session into a subobject, and refactored the interface.

* Fixed syntax bug.

* Added basic tests for overlay functions, and fixed some bugs.

* Updated quickstart examples for refactored interface

* Split contour dash mode and thickness into two functions.

* Renamed beam.beam_type and beam.set_beam_type to remove extra beam

* Removed histogram functions based on feedback

* Fixed global_ name in docs.

* Set session attribute on overlay components correctly. Escape backslash in docstring.

* Correctly pass the session to the overlay component constructor(s)

* Rename session's overlay attribute to wcs

* Fixed names of beam type property and action

* Remove bogus custom text from colorbar numbers component

* Fixed broken font style pattern

* Added missing font size functionality to overlay components with fonts

* Remove bogus visibility settings from ticks

* Remove ticks from visibility tests

* Fixed path of method to enable custom colorbar label text. Added tests for both custom text functions in image.

* Refactored and expanded image-specific WCS overlay properties

* Rename wcs subobject in instructions

* Make custom text API match the beam API

* Added session.raster with pixel grid controls; fixed test logic for comparing enum return values

* remove outdated TODO comments

* Added spectral conversion for PV images to image class

* Added missing modules to generated docs

* Updated docstrings for spectral conversion functions.

* remove function for toggling labels

---------

Co-authored-by: Adrianna Pińska <[email protected]>
  • Loading branch information
I-Chenn and confluence authored Jun 18, 2024
1 parent 16f3e7a commit acf0044
Show file tree
Hide file tree
Showing 18 changed files with 3,848 additions and 762 deletions.
102 changes: 97 additions & 5 deletions carta/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class LabelType(StrEnum):

class BeamType(StrEnum):
"""Beam types."""
OPEN = "Open"
SOLID = "Solid"
OPEN = "open"
SOLID = "solid"


# BlueprintJS colour palettes (2 and 4)
Expand Down Expand Up @@ -103,7 +103,7 @@ class BeamType(StrEnum):


class PaletteColor(StrEnum):
"""Palette colours used for overlay elements.
"""Palette colours used for WCS overlay elements.
Members of this enum class have additional attributes.
Expand All @@ -129,9 +129,9 @@ def __init__(self, value):


Overlay = StrEnum('Overlay', [(c.upper(), c) for c in ("global", "title", "grid", "border", "ticks", "axes", "numbers", "labels", "colorbar")] + [('BEAM', 'beam.settingsForDisplay')])
Overlay.__doc__ = """Overlay elements.
Overlay.__doc__ = """WCS overlay elements.
Member values are paths to stores corresponding to these elements, relative to the overlay store.
Member values are paths to stores corresponding to these elements, relative to the WCS overlay store.
"""


Expand Down Expand Up @@ -214,3 +214,95 @@ class GridMode(StrEnum):
"""Grid modes."""
DYNAMIC = "dynamic"
FIXED = "fixed"


class FontFamily(IntEnum):
"""Font family used in WCS overlay components."""
SANS_SERIF = 0
TIMES = 1
ARIAL = 2
PALATINO = 3
COURIER_NEW = 4


class FontStyle(IntEnum):
"""Font style used in WCS overlay components."""
NORMAL = 0
ITALIC = 1
BOLD = 2
BOLD_ITALIC = 3


class ColorbarPosition(StrEnum):
"""Colorbar positions."""
RIGHT = "right"
TOP = "top"
BOTTOM = "bottom"


class SpectralSystem(StrEnum):
"""Spectral systems."""
LSRK = "LSRK"
LSRD = "LSRD"
BARY = "BARYCENT"
TOPO = "TOPOCENT"


class SpectralUnit(StrEnum):
"""Spectral units."""
KMS = "km/s"
MS = "m/s"
GHZ = "GHz"
MHZ = "MHz"
KHZ = "kHz"
HZ = "Hz"
M = "m"
MM = "mm"
UM = "um"
NM = "nm"
ANGSTROM = "Angstrom"


SPECTRAL_TYPE_DESCRIPTION = {
"VRAD": "Radio velocity",
"VOPT": "Optical velocity",
"FREQ": "Frequency",
"WAVE": "Vacuum wavelength",
"AWAV": "Air wavelength",
}


SPECTRAL_TYPE_UNITS = {
"VRAD": (SpectralUnit.KMS, SpectralUnit.MS),
"VOPT": (SpectralUnit.KMS, SpectralUnit.MS),
"FREQ": (SpectralUnit.GHZ, SpectralUnit.MHZ, SpectralUnit.KHZ, SpectralUnit.HZ),
"WAVE": (SpectralUnit.MM, SpectralUnit.M, SpectralUnit.UM, SpectralUnit.NM, SpectralUnit.ANGSTROM),
"AWAV": (SpectralUnit.MM, SpectralUnit.M, SpectralUnit.UM, SpectralUnit.NM, SpectralUnit.ANGSTROM),
}


class SpectralType(StrEnum):
"""Spectral types.
Members of this enum class have additional attributes.
Attributes
----------
description : string
The human-readable description of this type.
units : set of :obj:`carta.constants.SpectralUnit`
The units supported for this type.
default_unit : :obj:`carta.constants.SpectralUnit`
The default unit for this type.
"""

def __init__(self, value):
self.description = SPECTRAL_TYPE_DESCRIPTION[self.name]
self.units = set(SPECTRAL_TYPE_UNITS[self.name])
self.default_unit = SPECTRAL_TYPE_UNITS[self.name][0]

VRAD = "VRAD",
VOPT = "VOPT",
FREQ = "FREQ",
WAVE = "WAVE",
AWAV = "AWAV",
186 changes: 186 additions & 0 deletions carta/contours.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
"""This module contains functionality for interacting with the contours of an image. The class in this module should not be instantiated directly. When an image object is created, a contours object is automatically created as a property."""

from .util import BasePathMixin
from .constants import Colormap, SmoothingMode, ContourDashMode
from .validation import validate, Number, Color, Constant, Boolean, IterableOf, all_optional, vargs


class Contours(BasePathMixin):
"""Utility object for collecting image functions related to contours.
Parameters
----------
image : :obj:`carta.image.Image` object
The image associated with this contours object.
Attributes
----------
image : :obj:`carta.image.Image` object
The image associated with this contours object.
session : :obj:`carta.session.Session` object
The session object associated with this contours object.
"""

def __init__(self, image):
self.image = image
self.session = image.session
self._base_path = f"{image._base_path}.contourConfig"

@validate(*all_optional(IterableOf(Number()), Constant(SmoothingMode), Number()))
def configure(self, levels=None, smoothing_mode=None, smoothing_factor=None):
"""Configure contours.
Parameters
----------
levels : {0}
The contour levels. This may be a numeric numpy array; e.g. the output of ``arange``. If this is unset, the current configured levels will be used.
smoothing_mode : {1}
The smoothing mode. If this is unset, the frontend default will be used.
smoothing_factor : {2}
The smoothing kernel size in pixels. If this is unset, the frontend default will be used.
"""
if levels is not None or smoothing_mode is not None or smoothing_factor is not None:
if levels is None:
levels = self.macro("", "levels")
if smoothing_mode is None:
smoothing_mode = self.macro("", "smoothingMode")
if smoothing_factor is None:
smoothing_factor = self.macro("", "smoothingFactor")
self.call_action("setContourConfiguration", levels, smoothing_mode, smoothing_factor)

@validate(Constant(ContourDashMode))
def set_dash_mode(self, dash_mode):
"""Set the contour dash mode.
Parameters
----------
dash_mode : {0}
The dash mode.
"""
self.call_action("setDashMode", dash_mode)

@validate(Number())
def set_thickness(self, thickness):
"""Set the contour thickness.
Parameters
----------
thickness : {0}
The thickness.
"""
self.call_action("setThickness", thickness)

@validate(Color())
def set_color(self, color):
"""Set the contour color.
This automatically disables use of the contour colormap.
Parameters
----------
color : {0}
The color. The default is green.
"""
self.call_action("setColor", color)
self.call_action("setColormapEnabled", False)

@validate(Constant(Colormap))
def set_colormap(self, colormap):
"""Set the contour colormap.
This also automatically enables the colormap.
Parameters
----------
colormap : {0}
The colormap. The default is :obj:`carta.constants.Colormap.VIRIDIS`.
"""
self.call_action("setColormap", colormap)
self.call_action("setColormapEnabled", True)

@validate(*all_optional(Number(-1, 1), Number(0, 2)))
def set_bias_and_contrast(self, bias=None, contrast=None):
"""Set the contour bias and contrast.
Parameters
----------
bias : {0}
The colormap bias. The initial value is ``0``.
contrast : {1}
The colormap contrast. The initial value is ``1``.
"""
if bias is not None:
self.call_action("setColormapBias", bias)
if contrast is not None:
self.call_action("setColormapContrast", contrast)

def apply(self):
"""Apply the contour configuration."""
self.image.call_action("applyContours")

@validate(*all_optional(*vargs(configure, set_dash_mode, set_thickness, set_color, set_colormap, set_bias_and_contrast)))
def plot(self, levels=None, smoothing_mode=None, smoothing_factor=None, dash_mode=None, thickness=None, color=None, colormap=None, bias=None, contrast=None):
"""Configure contour levels, scaling, dash, and colour or colourmap; and apply contours; in a single step.
If both a colour and a colourmap are provided, the colourmap will be visible.
Parameters
----------
levels : {0}
The contour levels. This may be a numeric numpy array; e.g. the output of ``arange``. If this is unset, the current configured levels will be used.
smoothing_mode : {1}
The smoothing mode. If this is unset, the frontend default will be used.
smoothing_factor : {2}
The smoothing kernel size in pixels. If this is unset, the frontend default will be used.
dash_mode : {3}
The dash mode.
thickness : {4}
The thickness.
color : {5}
The color. The default is green.
colormap : {6}
The colormap. The default is :obj:`carta.constants.Colormap.VIRIDIS`.
bias : {7}
The colormap bias.
contrast : {8}
The colormap contrast.
"""
changes_made = False

for method, args in [
(self.configure, (levels, smoothing_mode, smoothing_factor)),
(self.set_dash_mode, (dash_mode,)),
(self.set_thickness, (thickness,)),
(self.set_color, (color,)),
(self.set_colormap, (colormap,)),
(self.set_bias_and_contrast, (bias, contrast)),
]:
if any(a is not None for a in args):
method(*args)
changes_made = True

if changes_made:
self.apply()

def clear(self):
"""Clear the contours."""
self.image.call_action("clearContours", True)

@validate(Boolean())
def set_visible(self, state):
"""Set the contour visibility.
Parameters
----------
state : {0}
The desired visibility state.
"""
self.call_action("setVisible", state)

def show(self):
"""Show the contours."""
self.set_visible(True)

def hide(self):
"""Hide the contours."""
self.set_visible(False)
Loading

0 comments on commit acf0044

Please sign in to comment.