Module pyaurorax.tools
Data analysis toolkit for working with all-sky imager data available within the AuroraX platform.
This portion of the PyAuroraX library allows you to easily generate basic plots for ASI data, and common manipulations. These include things like displaying single images, making keograms, projecting ASI data onto maps, and extracting metrics for a given lat/lon bounding box.
Example
For shorter function calls, you can initialize the tools submodule using like so:
import pyaurorax
aurorax = pyaurorax.PyAuroraX()
at = aurorax.tools
Sub-modules
pyaurorax.tools.bounding_box
-
Methods for working with data in a specific bounding box.
pyaurorax.tools.calibration
-
Perform various calibration procedures on image data.
pyaurorax.tools.ccd_contour
-
Obtain contours in pixel coordinates from a skymap for plotting over CCD images.
pyaurorax.tools.classes
-
Class definitions for data analysis objects.
pyaurorax.tools.grid_files
-
Prepare grid data for plotting.
pyaurorax.tools.keogram
-
Generate keograms.
pyaurorax.tools.montage
-
Create montages.
pyaurorax.tools.mosaic
-
Prepare data and create mosaics.
pyaurorax.tools.spectra
-
Work with spectrograph data.
Classes
class Keogram (data: numpy.ndarray,
timestamp: List[datetime.datetime],
instrument_type: str,
slice_idx: int | None = None,
ccd_y: numpy.ndarray | None = None,
mag_y: numpy.ndarray | None = None,
geo_y: numpy.ndarray | None = None)-
Expand source code
@dataclass class Keogram: """ Class representation for a keogram Attributes: data (numpy.ndarray): The derived keogram data. timestamp (List[datetime.datetime]): Timestamps corresponding to each keogram slice. instrument_type (str): String giving instrument type, either 'asi' or 'spectrograph'. ccd_y (numpy.ndarray): The y-axis representing CCD Y coordinates for the keogram. mag_y (numpy.ndarray): The y-axis representing magnetic latitude for the keogram. geo_y (numpy.ndarray): The y-axis representing geographic latitude for the keogram. """ def __init__(self, data: np.ndarray, timestamp: List[datetime.datetime], instrument_type: str, slice_idx: Optional[int] = None, ccd_y: Optional[np.ndarray] = None, mag_y: Optional[np.ndarray] = None, geo_y: Optional[np.ndarray] = None): # public vars self.data = data self.timestamp = timestamp self.instrument_type = instrument_type self.ccd_y = ccd_y self.mag_y = mag_y self.geo_y = geo_y # private vars self.__slice_idx = slice_idx def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: data_str = "array(dims=%s, dtype=%s)" % (self.data.shape, self.data.dtype) timestamp_str = "[%d datetime objects]" % (len(self.timestamp)) ccd_y_str = "None" if self.ccd_y is None else "array(%d values)" % (self.ccd_y.shape[0]) mag_y_str = "None" if self.mag_y is None else "array(%d values)" % (self.mag_y.shape[0]) geo_y_str = "None" if self.geo_y is None else "array(%d values)" % (self.geo_y.shape[0]) return "Keogram(data=%s, timestamp=%s, ccd_y=%s, mag_y=%s, geo_y=%s)" % (data_str, timestamp_str, ccd_y_str, mag_y_str, geo_y_str) def pretty_print(self): """ A special print output for this class. """ # set special strings data_str = "array(dims=%s, dtype=%s)" % (self.data.shape, self.data.dtype) timestamp_str = "[%d datetime objects]" % (len(self.timestamp)) ccd_y_str = "None" if self.ccd_y is None else "array(%d values)" % (self.ccd_y.shape[0]) mag_y_str = "None" if self.mag_y is None else "array(%d values)" % (self.mag_y.shape[0]) geo_y_str = "None" if self.geo_y is None else "array(%d values)" % (self.geo_y.shape[0]) # print print("Keogram:") print(" %-17s: %s" % ("data", data_str)) print(" %-17s: %s" % ("timestamp", timestamp_str)) print(" %-17s: %s" % ("instrument_type", self.instrument_type)) print(" %-17s: %s" % ("ccd_y", ccd_y_str)) print(" %-17s: %s" % ("geo_y", geo_y_str)) print(" %-17s: %s" % ("mag_y", mag_y_str)) def set_geographic_latitudes(self, skymap: Skymap, altitude_km: Optional[Union[int, float]] = None) -> None: """ Set the geographic latitude values for this keogram, using the specified skymap data. The data will be set to the geo_y attribute of this Keogram object, which can then be used for plotting and/or further analysis. Args: skymap (pyaurorax.data.ucalgary.Skymap): The skymap object to use. This parameter is required. altitude_km (int): The altitude to use, in kilometers. If not specified, it will use the default in the skymap object. If the specified altitude is not valid, a ValueError will be raised. Returns: None. The Keogram object's `geo_y` attribute will be updated. Raises: ValueError: Issues with specified altitude. """ # check for slice idx if (self.__slice_idx is None): raise ValueError("Unable to set the geographic latitudes since the private slice_idx is None. If this keogram " + "object was created as part of the custom_keogram routines or is a spectrogaph keogram, " + "this is expected and performing this action is not supported at this time.") # determine altitude index to use if (altitude_km is not None): # Obtain lat/lon arrays from skymap if (altitude_km * 1000.0 in skymap.full_map_altitude): altitude_idx = np.where(altitude_km * 1000.0 == skymap.full_map_altitude) self.geo_y = np.squeeze(skymap.full_map_latitude[altitude_idx, :, self.__slice_idx]).copy() else: # Make sure altitude is in range that can be interpolated if (altitude_km * 1000.0 < skymap.full_map_altitude[0]) or (altitude_km * 1000.0 > skymap.full_map_altitude[2]): raise ValueError("Altitude " + str(altitude_km) + " outside valid range of " + str((skymap.full_map_altitude[0] / 1000.0, skymap.full_map_altitude[2] / 1000.0))) # Initialze empty lat/lon arrays lats = np.full(np.squeeze(skymap.full_map_latitude[0, :, :]).shape, np.nan, dtype=skymap.full_map_latitude[0, :, :].dtype) # Interpolate lats and lons at desired altitude for i in range(skymap.full_map_latitude.shape[1]): for j in range(skymap.full_map_latitude.shape[2]): lats[i, j] = np.interp(altitude_km * 1000.0, skymap.full_map_altitude, skymap.full_map_latitude[:, i, j]) self.geo_y = lats[:, self.__slice_idx].copy() else: # use default middle altitude self.geo_y = np.squeeze(skymap.full_map_latitude[1, :, self.__slice_idx]).copy() def set_magnetic_latitudes(self, skymap: Skymap, timestamp: datetime.datetime, altitude_km: Optional[Union[int, float]] = None) -> None: """ Set the magnetic latitude values for this keogram, using the specified skymap data. AACGMv2 will be utilized to perform the calculations. The resulting data will be set to the mag_y attribute of this Keogram object, which can then be used for plotting and/or further analysis. Args: skymap (pyaurorax.data.ucalgary.Skymap): The skymap object to use. This parameter is required. timestamp (datetime.datetime): The timestamp to use when converting skymap data to magnetic coordinates. Utilizes AACGMv2 to do the conversion. altitude_km (int): The altitude to use. If not specified, it will use the default in the skymap object. If the specified altitude is not valid, a ValueError will be raised. Returns: None. The Keogram object's `mag_y` attribute will be updated. Raises: ValueError: Issues with specified altitude. """ # check for slice idx if (self.__slice_idx is None): raise ValueError("Unable to set the geographic latitudes since the slice_idx is None. If this keogram " + "object was created as part of the custom_keogram routines or is a spectrogaph keogram, " + "this is expected and performing this action is not supported at this time.") # determine altitude index to use if (altitude_km is not None): # Obtain lat/lon arrays from skymap if (altitude_km * 1000.0 in skymap.full_map_altitude): altitude_idx = np.where(altitude_km * 1000.0 == skymap.full_map_altitude) lats = np.squeeze(skymap.full_map_latitude[altitude_idx, :, :]) lons = np.squeeze(skymap.full_map_longitude[altitude_idx, :, :]) lons[np.where(lons > 180)] -= 360.0 else: # Make sure altitude is in range that can be interpolated if (altitude_km * 1000.0 < skymap.full_map_altitude[0]) or (altitude_km * 1000.0 > skymap.full_map_altitude[2]): raise ValueError("Altitude " + str(altitude_km) + " outside valid range of " + str((skymap.full_map_altitude[0] / 1000.0, skymap.full_map_altitude[2] / 1000.0))) # Initialze empty lat/lon arrays lats = np.full(np.squeeze(skymap.full_map_latitude[0, :, :]).shape, np.nan, dtype=skymap.full_map_latitude[0, :, :].dtype) lons = lats.copy() # Interpolate lats and lons at desired altitude for i in range(skymap.full_map_latitude.shape[1]): for j in range(skymap.full_map_latitude.shape[2]): lats[i, j] = np.interp(altitude_km * 1000.0, skymap.full_map_altitude, skymap.full_map_latitude[:, i, j]) lons[i, j] = np.interp(altitude_km * 1000.0, skymap.full_map_altitude, skymap.full_map_longitude[:, i, j]) lons[np.where(lons > 180)] -= 360.0 # Convert lats and lons to geomagnetic coordinates mag_lats, mag_lons, mag_alts = aacgmv2.convert_latlon_arr(lats.flatten(), lons.flatten(), (lons * 0.0).flatten(), timestamp, method_code='G2A') mag_lats = np.reshape(mag_lats, lats.shape) mag_lons = np.reshape(mag_lons, lons.shape) # Set the y axis to the desired slice index of the magnetic latitudes self.mag_y = mag_lats[:, self.__slice_idx].copy() else: # Convert middle altitude lats and lons to geomagnetic coordinates mag_lats, mag_lons, mag_alts = aacgmv2.convert_latlon_arr(np.squeeze(skymap.full_map_latitude[1, :, :]).flatten(), np.squeeze(skymap.full_map_longitude[1, :, :]).flatten(), (skymap.full_map_longitude[1, :, :] * 0.0).flatten(), timestamp, method_code='G2A') mag_lats = np.reshape(mag_lats, np.squeeze(skymap.full_map_latitude[1, :, :]).shape) mag_lons = np.reshape(mag_lons, np.squeeze(skymap.full_map_longitude[1, :, :]).shape) # Set the y axis to the desired slice index of the magnetic latitudes self.mag_y = mag_lats[:, self.__slice_idx].copy() def plot(self, y_type: Literal["ccd", "mag", "geo"] = "ccd", title: Optional[str] = None, figsize: Optional[Tuple[int, int]] = None, cmap: Optional[str] = None, aspect: Optional[Union[Literal["equal", "auto"], float]] = None, axes_visible: bool = True, xlabel: str = "Time (UTC)", ylabel: Optional[str] = None, xtick_increment: Optional[int] = None, ytick_increment: Optional[int] = None, returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Generate a plot of the keogram data. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: y_type (str): Type of y-axis to use when plotting. Options are `ccd`, `mag`, or `geo`. The default is `ccd`. This parameter is required. title (str): The title to display above the plotted keogram. Default is no title. figsize (tuple): The matplotlib figure size to use when plotting. For example `figsize=(14,4)`. cmap (str): The matplotlib colormap to use. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). aspect (str or float): The matplotlib imshow aspect ration to use. A common value for this is `auto`. All valid values can be found on the [matplotlib documentation](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html). axes_visible (bool): Display the axes. Default is `True`. xlabel (str): The x-axis label to use. Default is `Time (UTC)`. ylabel (str): The y-axis label to use. Default is based on y_type. xtick_increment (int): The x-axis tick increment to use. Default is 100. ytick_increment (int): The y-axis tick increment to use. Default is 50. returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed keogram, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: ValueError: issues encountered with the y-axis choice """ # check return mode if (returnfig is True and savefig is True): raise ValueError("Only one of returnfig or savefig can be set to True") if returnfig is True and (savefig_filename is not None or savefig_quality is not None): show_warning("The figure will be returned, but a savefig option parameter was supplied. Consider " + "removing the savefig option parameter(s) as they will be ignored.", stacklevel=1) elif savefig is False and (savefig_filename is not None or savefig_quality is not None): show_warning("A savefig option parameter was supplied, but the savefig parameter is False. The " + "savefig option parameters will be ignored.", stacklevel=1) # init figure and plot data fig = plt.figure(figsize=figsize) ax = fig.add_axes((0, 0, 1, 1)) ax.imshow(self.data, origin="lower", cmap=cmap, aspect=aspect) # set title if (title is not None): ax.set_title(title) # set axes if (axes_visible is True): # do checks for y-axis that was chosen if (y_type == "geo" and self.geo_y is None): raise ValueError("Unable to plot using geo_y data. The geo_y attribute is currently None, so either populate " "it with data using the set_geographic_latitudes() function, or choose a different y_type") elif (y_type == "mag" and self.mag_y is None): raise ValueError("Unable to plot using mag_y data. The mag_y attribute is currently None, so either populate " "it with data using the set_magnetic_latitudes() function, or choose a different y_type") # set y axis data, and y label y_axis_data = self.ccd_y if (y_type == "mag"): y_axis_data = self.mag_y if (ylabel is None): ylabel = "Magnetic latitude" elif (y_type == "geo"): y_axis_data = self.geo_y if (ylabel is None): ylabel = "Geographic latitude" else: if (ylabel is None): ylabel = "CCD Y" # print labels ax.set_xlabel(xlabel, fontsize=14) ax.set_ylabel(ylabel, fontsize=14) # generate x ticks and labels # # TODO: make this more dynamic if (xtick_increment is None): xtick_increment = 100 # assume data is 3 second cadence; good enough for now x_ticks = np.arange(0, self.data.shape[1], xtick_increment) x_labels = self.timestamp[::xtick_increment] for i in range(0, len(x_labels)): x_labels[i] = x_labels[i].strftime("%H:%M") # type: ignore ax.set_xticks(x_ticks, x_labels) # type: ignore # do check for ccd_y if (self.ccd_y is None): show_warning( "Unable to plot y-axis. If this keogram object was create as part of the custom_keogram " + "routines, this is expected and plotting a custom keogram with axes is not supported at this time.", stacklevel=1, ) else: # generate y ticks and labels if (y_type == "ccd"): # TODO: make this more dynamic if (ytick_increment is None): ytick_increment = 50 # generate y ticks and labels y_ticks = y_axis_data[::ytick_increment] # type: ignore y_labels = y_axis_data[::ytick_increment] # type: ignore # apply yticks ax.set_yticks(y_ticks, y_labels) # type: ignore elif (y_type == "geo" and self.geo_y is not None) or (y_type == "mag" and self.mag_y is not None): # set tick increments if (ytick_increment is None): ytick_increment = 50 # generate y ticks and labels y_ticks = self.ccd_y[25::ytick_increment] y_labels = np.round( y_axis_data, # type: ignore 1).astype(str)[25::ytick_increment] y_labels[np.where(y_labels == 'nan')] = '' # apply yticks ax.set_yticks(y_ticks, y_labels) else: # disable axes ax.set_axis_off() # save figure or show it if (savefig is True): # check that filename has been set if (savefig_filename is None): raise ValueError("The savefig_filename parameter is missing, but required since savefig was set to True.") # save the figure f_extension = os.path.splitext(savefig_filename)[-1].lower() if (".jpg" == f_extension or ".jpeg" == f_extension): # check quality setting if (savefig_quality is not None): # pragma: nocover plt.savefig(savefig_filename, quality=savefig_quality, bbox_inches="tight") else: plt.savefig(savefig_filename, bbox_inches="tight") else: if (savefig_quality is not None): # quality specified, but output filename is not a JPG, so show a warning show_warning("The savefig_quality parameter was specified, but is only used for saving JPG files. The " + "savefig_filename parameter was determined to not be a JPG file, so the quality will be ignored", stacklevel=1) plt.savefig(savefig_filename, bbox_inches="tight") # clean up by closing the figure plt.close(fig) elif (returnfig is True): # return the figure and axis objects return (fig, ax) else: # show the figure plt.show(fig) # cleanup by closing the figure plt.close(fig) # return return None
Class representation for a keogram
Attributes
data
:numpy.ndarray
- The derived keogram data.
timestamp
:List[datetime.datetime]
- Timestamps corresponding to each keogram slice.
instrument_type
:str
- String giving instrument type, either 'asi' or 'spectrograph'.
ccd_y
:numpy.ndarray
- The y-axis representing CCD Y coordinates for the keogram.
mag_y
:numpy.ndarray
- The y-axis representing magnetic latitude for the keogram.
geo_y
:numpy.ndarray
- The y-axis representing geographic latitude for the keogram.
Methods
def plot(self,
y_type: Literal['ccd', 'mag', 'geo'] = 'ccd',
title: str | None = None,
figsize: Tuple[int, int] | None = None,
cmap: str | None = None,
aspect: Literal['equal', 'auto'] | float | None = None,
axes_visible: bool = True,
xlabel: str = 'Time (UTC)',
ylabel: str | None = None,
xtick_increment: int | None = None,
ytick_increment: int | None = None,
returnfig: bool = False,
savefig: bool = False,
savefig_filename: str | None = None,
savefig_quality: int | None = None) ‑> Any-
Expand source code
def plot(self, y_type: Literal["ccd", "mag", "geo"] = "ccd", title: Optional[str] = None, figsize: Optional[Tuple[int, int]] = None, cmap: Optional[str] = None, aspect: Optional[Union[Literal["equal", "auto"], float]] = None, axes_visible: bool = True, xlabel: str = "Time (UTC)", ylabel: Optional[str] = None, xtick_increment: Optional[int] = None, ytick_increment: Optional[int] = None, returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Generate a plot of the keogram data. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: y_type (str): Type of y-axis to use when plotting. Options are `ccd`, `mag`, or `geo`. The default is `ccd`. This parameter is required. title (str): The title to display above the plotted keogram. Default is no title. figsize (tuple): The matplotlib figure size to use when plotting. For example `figsize=(14,4)`. cmap (str): The matplotlib colormap to use. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). aspect (str or float): The matplotlib imshow aspect ration to use. A common value for this is `auto`. All valid values can be found on the [matplotlib documentation](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html). axes_visible (bool): Display the axes. Default is `True`. xlabel (str): The x-axis label to use. Default is `Time (UTC)`. ylabel (str): The y-axis label to use. Default is based on y_type. xtick_increment (int): The x-axis tick increment to use. Default is 100. ytick_increment (int): The y-axis tick increment to use. Default is 50. returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed keogram, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: ValueError: issues encountered with the y-axis choice """ # check return mode if (returnfig is True and savefig is True): raise ValueError("Only one of returnfig or savefig can be set to True") if returnfig is True and (savefig_filename is not None or savefig_quality is not None): show_warning("The figure will be returned, but a savefig option parameter was supplied. Consider " + "removing the savefig option parameter(s) as they will be ignored.", stacklevel=1) elif savefig is False and (savefig_filename is not None or savefig_quality is not None): show_warning("A savefig option parameter was supplied, but the savefig parameter is False. The " + "savefig option parameters will be ignored.", stacklevel=1) # init figure and plot data fig = plt.figure(figsize=figsize) ax = fig.add_axes((0, 0, 1, 1)) ax.imshow(self.data, origin="lower", cmap=cmap, aspect=aspect) # set title if (title is not None): ax.set_title(title) # set axes if (axes_visible is True): # do checks for y-axis that was chosen if (y_type == "geo" and self.geo_y is None): raise ValueError("Unable to plot using geo_y data. The geo_y attribute is currently None, so either populate " "it with data using the set_geographic_latitudes() function, or choose a different y_type") elif (y_type == "mag" and self.mag_y is None): raise ValueError("Unable to plot using mag_y data. The mag_y attribute is currently None, so either populate " "it with data using the set_magnetic_latitudes() function, or choose a different y_type") # set y axis data, and y label y_axis_data = self.ccd_y if (y_type == "mag"): y_axis_data = self.mag_y if (ylabel is None): ylabel = "Magnetic latitude" elif (y_type == "geo"): y_axis_data = self.geo_y if (ylabel is None): ylabel = "Geographic latitude" else: if (ylabel is None): ylabel = "CCD Y" # print labels ax.set_xlabel(xlabel, fontsize=14) ax.set_ylabel(ylabel, fontsize=14) # generate x ticks and labels # # TODO: make this more dynamic if (xtick_increment is None): xtick_increment = 100 # assume data is 3 second cadence; good enough for now x_ticks = np.arange(0, self.data.shape[1], xtick_increment) x_labels = self.timestamp[::xtick_increment] for i in range(0, len(x_labels)): x_labels[i] = x_labels[i].strftime("%H:%M") # type: ignore ax.set_xticks(x_ticks, x_labels) # type: ignore # do check for ccd_y if (self.ccd_y is None): show_warning( "Unable to plot y-axis. If this keogram object was create as part of the custom_keogram " + "routines, this is expected and plotting a custom keogram with axes is not supported at this time.", stacklevel=1, ) else: # generate y ticks and labels if (y_type == "ccd"): # TODO: make this more dynamic if (ytick_increment is None): ytick_increment = 50 # generate y ticks and labels y_ticks = y_axis_data[::ytick_increment] # type: ignore y_labels = y_axis_data[::ytick_increment] # type: ignore # apply yticks ax.set_yticks(y_ticks, y_labels) # type: ignore elif (y_type == "geo" and self.geo_y is not None) or (y_type == "mag" and self.mag_y is not None): # set tick increments if (ytick_increment is None): ytick_increment = 50 # generate y ticks and labels y_ticks = self.ccd_y[25::ytick_increment] y_labels = np.round( y_axis_data, # type: ignore 1).astype(str)[25::ytick_increment] y_labels[np.where(y_labels == 'nan')] = '' # apply yticks ax.set_yticks(y_ticks, y_labels) else: # disable axes ax.set_axis_off() # save figure or show it if (savefig is True): # check that filename has been set if (savefig_filename is None): raise ValueError("The savefig_filename parameter is missing, but required since savefig was set to True.") # save the figure f_extension = os.path.splitext(savefig_filename)[-1].lower() if (".jpg" == f_extension or ".jpeg" == f_extension): # check quality setting if (savefig_quality is not None): # pragma: nocover plt.savefig(savefig_filename, quality=savefig_quality, bbox_inches="tight") else: plt.savefig(savefig_filename, bbox_inches="tight") else: if (savefig_quality is not None): # quality specified, but output filename is not a JPG, so show a warning show_warning("The savefig_quality parameter was specified, but is only used for saving JPG files. The " + "savefig_filename parameter was determined to not be a JPG file, so the quality will be ignored", stacklevel=1) plt.savefig(savefig_filename, bbox_inches="tight") # clean up by closing the figure plt.close(fig) elif (returnfig is True): # return the figure and axis objects return (fig, ax) else: # show the figure plt.show(fig) # cleanup by closing the figure plt.close(fig) # return return None
Generate a plot of the keogram data.
Either display it (default behaviour), save it to disk (using the
savefig
parameter), or return the matplotlib plot object for further usage (using thereturnfig
parameter).Args
y_type
:str
- Type of y-axis to use when plotting. Options are
ccd
,mag
, orgeo
. The default isccd
. This parameter is required. title
:str
- The title to display above the plotted keogram. Default is no title.
figsize
:tuple
- The matplotlib figure size to use when plotting. For example
figsize=(14,4)
. cmap
:str
-
The matplotlib colormap to use.
Commonly used colormaps are:
- REGO:
gist_heat
- THEMIS ASI:
gray
- TREx Blue:
Blues_r
- TREx NIR:
gray
- TREx RGB:
None
A list of all available colormaps can be found on the matplotlib documentation.
- REGO:
aspect
:str
orfloat
- The matplotlib imshow aspect ration to use. A common value for this is
auto
. All valid values can be found on the matplotlib documentation. axes_visible
:bool
- Display the axes. Default is
True
. xlabel
:str
- The x-axis label to use. Default is
Time (UTC)
. ylabel
:str
- The y-axis label to use. Default is based on y_type.
xtick_increment
:int
- The x-axis tick increment to use. Default is 100.
ytick_increment
:int
- The y-axis tick increment to use. Default is 50.
returnfig
:bool
-
Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default.
Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing
plt.close(fig)
.Note that this method cannot be used in combination with
savefig
. savefig
:bool
- Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if
this parameter is set to True. Defaults to
False
. savefig_filename
:str
- Filename to save the image to. Must be specified if the savefig parameter is set to True.
savefig_quality
:int
- Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%.
Returns
The displayed keogram, by default. If
savefig
is set to True, nothing will be returned. Ifreturnfig
is set to True, the plotting variables(fig, ax)
will be returned.Raises
ValueError
- issues encountered with the y-axis choice
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings data_str = "array(dims=%s, dtype=%s)" % (self.data.shape, self.data.dtype) timestamp_str = "[%d datetime objects]" % (len(self.timestamp)) ccd_y_str = "None" if self.ccd_y is None else "array(%d values)" % (self.ccd_y.shape[0]) mag_y_str = "None" if self.mag_y is None else "array(%d values)" % (self.mag_y.shape[0]) geo_y_str = "None" if self.geo_y is None else "array(%d values)" % (self.geo_y.shape[0]) # print print("Keogram:") print(" %-17s: %s" % ("data", data_str)) print(" %-17s: %s" % ("timestamp", timestamp_str)) print(" %-17s: %s" % ("instrument_type", self.instrument_type)) print(" %-17s: %s" % ("ccd_y", ccd_y_str)) print(" %-17s: %s" % ("geo_y", geo_y_str)) print(" %-17s: %s" % ("mag_y", mag_y_str))
A special print output for this class.
def set_geographic_latitudes(self,
skymap: pyucalgarysrs.data.classes.Skymap,
altitude_km: int | float | None = None) ‑> None-
Expand source code
def set_geographic_latitudes(self, skymap: Skymap, altitude_km: Optional[Union[int, float]] = None) -> None: """ Set the geographic latitude values for this keogram, using the specified skymap data. The data will be set to the geo_y attribute of this Keogram object, which can then be used for plotting and/or further analysis. Args: skymap (pyaurorax.data.ucalgary.Skymap): The skymap object to use. This parameter is required. altitude_km (int): The altitude to use, in kilometers. If not specified, it will use the default in the skymap object. If the specified altitude is not valid, a ValueError will be raised. Returns: None. The Keogram object's `geo_y` attribute will be updated. Raises: ValueError: Issues with specified altitude. """ # check for slice idx if (self.__slice_idx is None): raise ValueError("Unable to set the geographic latitudes since the private slice_idx is None. If this keogram " + "object was created as part of the custom_keogram routines or is a spectrogaph keogram, " + "this is expected and performing this action is not supported at this time.") # determine altitude index to use if (altitude_km is not None): # Obtain lat/lon arrays from skymap if (altitude_km * 1000.0 in skymap.full_map_altitude): altitude_idx = np.where(altitude_km * 1000.0 == skymap.full_map_altitude) self.geo_y = np.squeeze(skymap.full_map_latitude[altitude_idx, :, self.__slice_idx]).copy() else: # Make sure altitude is in range that can be interpolated if (altitude_km * 1000.0 < skymap.full_map_altitude[0]) or (altitude_km * 1000.0 > skymap.full_map_altitude[2]): raise ValueError("Altitude " + str(altitude_km) + " outside valid range of " + str((skymap.full_map_altitude[0] / 1000.0, skymap.full_map_altitude[2] / 1000.0))) # Initialze empty lat/lon arrays lats = np.full(np.squeeze(skymap.full_map_latitude[0, :, :]).shape, np.nan, dtype=skymap.full_map_latitude[0, :, :].dtype) # Interpolate lats and lons at desired altitude for i in range(skymap.full_map_latitude.shape[1]): for j in range(skymap.full_map_latitude.shape[2]): lats[i, j] = np.interp(altitude_km * 1000.0, skymap.full_map_altitude, skymap.full_map_latitude[:, i, j]) self.geo_y = lats[:, self.__slice_idx].copy() else: # use default middle altitude self.geo_y = np.squeeze(skymap.full_map_latitude[1, :, self.__slice_idx]).copy()
Set the geographic latitude values for this keogram, using the specified skymap data. The data will be set to the geo_y attribute of this Keogram object, which can then be used for plotting and/or further analysis.
Args
skymap
:Skymap
- The skymap object to use. This parameter is required.
altitude_km
:int
- The altitude to use, in kilometers. If not specified, it will use the default in the skymap object. If the specified altitude is not valid, a ValueError will be raised.
Returns
None. The Keogram object's
geo_y
attribute will be updated.Raises
ValueError
- Issues with specified altitude.
def set_magnetic_latitudes(self,
skymap: pyucalgarysrs.data.classes.Skymap,
timestamp: datetime.datetime,
altitude_km: int | float | None = None) ‑> None-
Expand source code
def set_magnetic_latitudes(self, skymap: Skymap, timestamp: datetime.datetime, altitude_km: Optional[Union[int, float]] = None) -> None: """ Set the magnetic latitude values for this keogram, using the specified skymap data. AACGMv2 will be utilized to perform the calculations. The resulting data will be set to the mag_y attribute of this Keogram object, which can then be used for plotting and/or further analysis. Args: skymap (pyaurorax.data.ucalgary.Skymap): The skymap object to use. This parameter is required. timestamp (datetime.datetime): The timestamp to use when converting skymap data to magnetic coordinates. Utilizes AACGMv2 to do the conversion. altitude_km (int): The altitude to use. If not specified, it will use the default in the skymap object. If the specified altitude is not valid, a ValueError will be raised. Returns: None. The Keogram object's `mag_y` attribute will be updated. Raises: ValueError: Issues with specified altitude. """ # check for slice idx if (self.__slice_idx is None): raise ValueError("Unable to set the geographic latitudes since the slice_idx is None. If this keogram " + "object was created as part of the custom_keogram routines or is a spectrogaph keogram, " + "this is expected and performing this action is not supported at this time.") # determine altitude index to use if (altitude_km is not None): # Obtain lat/lon arrays from skymap if (altitude_km * 1000.0 in skymap.full_map_altitude): altitude_idx = np.where(altitude_km * 1000.0 == skymap.full_map_altitude) lats = np.squeeze(skymap.full_map_latitude[altitude_idx, :, :]) lons = np.squeeze(skymap.full_map_longitude[altitude_idx, :, :]) lons[np.where(lons > 180)] -= 360.0 else: # Make sure altitude is in range that can be interpolated if (altitude_km * 1000.0 < skymap.full_map_altitude[0]) or (altitude_km * 1000.0 > skymap.full_map_altitude[2]): raise ValueError("Altitude " + str(altitude_km) + " outside valid range of " + str((skymap.full_map_altitude[0] / 1000.0, skymap.full_map_altitude[2] / 1000.0))) # Initialze empty lat/lon arrays lats = np.full(np.squeeze(skymap.full_map_latitude[0, :, :]).shape, np.nan, dtype=skymap.full_map_latitude[0, :, :].dtype) lons = lats.copy() # Interpolate lats and lons at desired altitude for i in range(skymap.full_map_latitude.shape[1]): for j in range(skymap.full_map_latitude.shape[2]): lats[i, j] = np.interp(altitude_km * 1000.0, skymap.full_map_altitude, skymap.full_map_latitude[:, i, j]) lons[i, j] = np.interp(altitude_km * 1000.0, skymap.full_map_altitude, skymap.full_map_longitude[:, i, j]) lons[np.where(lons > 180)] -= 360.0 # Convert lats and lons to geomagnetic coordinates mag_lats, mag_lons, mag_alts = aacgmv2.convert_latlon_arr(lats.flatten(), lons.flatten(), (lons * 0.0).flatten(), timestamp, method_code='G2A') mag_lats = np.reshape(mag_lats, lats.shape) mag_lons = np.reshape(mag_lons, lons.shape) # Set the y axis to the desired slice index of the magnetic latitudes self.mag_y = mag_lats[:, self.__slice_idx].copy() else: # Convert middle altitude lats and lons to geomagnetic coordinates mag_lats, mag_lons, mag_alts = aacgmv2.convert_latlon_arr(np.squeeze(skymap.full_map_latitude[1, :, :]).flatten(), np.squeeze(skymap.full_map_longitude[1, :, :]).flatten(), (skymap.full_map_longitude[1, :, :] * 0.0).flatten(), timestamp, method_code='G2A') mag_lats = np.reshape(mag_lats, np.squeeze(skymap.full_map_latitude[1, :, :]).shape) mag_lons = np.reshape(mag_lons, np.squeeze(skymap.full_map_longitude[1, :, :]).shape) # Set the y axis to the desired slice index of the magnetic latitudes self.mag_y = mag_lats[:, self.__slice_idx].copy()
Set the magnetic latitude values for this keogram, using the specified skymap data. AACGMv2 will be utilized to perform the calculations. The resulting data will be set to the mag_y attribute of this Keogram object, which can then be used for plotting and/or further analysis.
Args
skymap
:Skymap
- The skymap object to use. This parameter is required.
timestamp
:datetime.datetime
- The timestamp to use when converting skymap data to magnetic coordinates. Utilizes AACGMv2 to do the conversion.
altitude_km
:int
- The altitude to use. If not specified, it will use the default in the skymap object. If the specified altitude is not valid, a ValueError will be raised.
Returns
None. The Keogram object's
mag_y
attribute will be updated.Raises
ValueError
- Issues with specified altitude.
class Montage (data: numpy.ndarray, timestamp: List[datetime.datetime], n_channels: int)
-
Expand source code
@dataclass class Montage: """ Class representation for a montage Attributes: data (numpy.ndarray): The derived montage data. timestamp (List[datetime.datetime]): Timestamps corresponding to each montage image. """ def __init__(self, data: np.ndarray, timestamp: List[datetime.datetime], n_channels: int): # public vars self.data = data self.timestamp = timestamp # private vars self.__n_channels = n_channels def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: data_str = "array(dims=%s, dtype=%s)" % (self.data.shape, self.data.dtype) timestamp_str = "[%d datetime objects]" % (len(self.timestamp)) return "Montage(data=%s, timestamp=%s)" % (data_str, timestamp_str) def pretty_print(self): """ A special print output for this class. """ # set special strings data_str = "array(dims=%s, dtype=%s)" % (self.data.shape, self.data.dtype) timestamp_str = "[%d datetime objects]" % (len(self.timestamp)) # print print("Montage:") print(" %-11s: %s" % ("data", data_str)) print(" %-11s: %s" % ("timestamp", timestamp_str)) def plot(self, rows: int, cols: int, timestamps_display: bool = True, timestamps_format: str = "%Y-%m-%d %H:%M:%S", timestamps_fontsize: int = 11, figsize: Optional[Tuple[int, int]] = None, title: Optional[str] = None, cmap: Optional[str] = None, returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Generate a plot of the montage data. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: rows (int): The number of rows to use when displaying the images as a montage. The product of the `rows` and `cols` parameters must match the number of images supplied when creating the `Montage` object. If not, a ValueError will be raised. This parameter is required. cols (int): The number of columns to use when displaying the images as a montage. The product of the `rows` and `cols` parameters must match the number of images supplied when creating the `Montage` object. If not, a ValueError will be raised. This parameter is required. timestamps_display (bool): Display the timestamps on each montage image. Defaults to True. This parameter is optional. timestamps_format (str): The format of the timestamps when being displayed. This is the same format string as when using the `strftime()` function for a `datetime` object. Default format string is `%Y-%m-%d %H:%M:%S`. Refer to the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) for further information. This parameter is optional. timestamps_fontsize (int): The font size for the displayed timestamps. Default is size 11. This parameter is optional. figsize (tuple): The matplotlib figure size to use when plotting. For example `figsize=(14,4)`. title (str): The title to display above the plotted montage. Default is no title. cmap (str): The matplotlib colormap to use. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed montage, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: ValueError: issues with the y-axis choice, or rows/cols choice. """ # check rows and cols if (rows * cols != self.data.shape[-1]): raise ValueError(("Invalid choice of rows and columns. The %d images in this Montage object " + "cannot be organized into a %dx%d grid (%d * %d != %d)") % ( self.data.shape[-1], rows, cols, rows, cols, self.data.shape[-1], )) # check return mode if (returnfig is True and savefig is True): raise ValueError("Only one of returnfig or savefig can be set to True") if (returnfig is True and (savefig_filename is not None or savefig_quality is not None)): show_warning("The figure will be returned, but a savefig option parameter was supplied. Consider " + "removing the savefig option parameter(s) as they will be ignored.", stacklevel=1) elif (savefig is False and (savefig_filename is not None or savefig_quality is not None)): show_warning("A savefig option parameter was supplied, but the savefig parameter is False. The " + "savefig option parameters will be ignored.", stacklevel=1) # init figure fig, axs = plt.subplots(nrows=rows, ncols=cols, figsize=figsize) # set title if (title is not None): fig.suptitle(title) # for each image for ax, i in zip(axs.flat, range(0, len(self.timestamp))): # type: ignore if (self.__n_channels == 1): # single channel ax.imshow(self.data[:, :, i], cmap=cmap, origin="lower", interpolation="nearest") elif (self.__n_channels == 3): # single channel ax.imshow(self.data[:, :, :, i], cmap=cmap, origin="lower", interpolation="nearest") else: # pragma: nocover raise ValueError("Can only plot 3 or 4 dimensional data (series of single-channel or RGB mages), but found data of shape %s" % (self.data.shape)) ax.set_axis_off() # show timestamp if (timestamps_display is True): ax.text( int(np.floor(self.data.shape[1] / 2.)), 5, self.timestamp[i].strftime(timestamps_format), ha="center", fontsize=timestamps_fontsize, ) plt.tight_layout(h_pad=0, w_pad=0) # save figure or show it if (savefig is True): # check that filename has been set if (savefig_filename is None): raise ValueError("The savefig_filename parameter is missing, but required since savefig was set to True.") # save the figure f_extension = os.path.splitext(savefig_filename)[-1].lower() if (".jpg" == f_extension or ".jpeg" == f_extension): # check quality setting if (savefig_quality is not None): # pragma: nocover plt.savefig(savefig_filename, quality=savefig_quality, bbox_inches="tight") else: plt.savefig(savefig_filename, bbox_inches="tight") else: if (savefig_quality is not None): # quality specified, but output filename is not a JPG, so show a warning show_warning("The savefig_quality parameter was specified, but is only used for saving JPG files. The " + "savefig_filename parameter was determined to not be a JPG file, so the quality will be ignored", stacklevel=1) plt.savefig(savefig_filename, bbox_inches="tight") # clean up by closing the figure plt.close(fig) elif (returnfig is True): # return the figure and axis objects return (fig, axs) else: # show the figure plt.show(fig) # cleanup by closing the figure plt.close(fig) # return return None
Class representation for a montage
Attributes
data
:numpy.ndarray
- The derived montage data.
timestamp
:List[datetime.datetime]
- Timestamps corresponding to each montage image.
Methods
def plot(self,
rows: int,
cols: int,
timestamps_display: bool = True,
timestamps_format: str = '%Y-%m-%d %H:%M:%S',
timestamps_fontsize: int = 11,
figsize: Tuple[int, int] | None = None,
title: str | None = None,
cmap: str | None = None,
returnfig: bool = False,
savefig: bool = False,
savefig_filename: str | None = None,
savefig_quality: int | None = None) ‑> Any-
Expand source code
def plot(self, rows: int, cols: int, timestamps_display: bool = True, timestamps_format: str = "%Y-%m-%d %H:%M:%S", timestamps_fontsize: int = 11, figsize: Optional[Tuple[int, int]] = None, title: Optional[str] = None, cmap: Optional[str] = None, returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Generate a plot of the montage data. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: rows (int): The number of rows to use when displaying the images as a montage. The product of the `rows` and `cols` parameters must match the number of images supplied when creating the `Montage` object. If not, a ValueError will be raised. This parameter is required. cols (int): The number of columns to use when displaying the images as a montage. The product of the `rows` and `cols` parameters must match the number of images supplied when creating the `Montage` object. If not, a ValueError will be raised. This parameter is required. timestamps_display (bool): Display the timestamps on each montage image. Defaults to True. This parameter is optional. timestamps_format (str): The format of the timestamps when being displayed. This is the same format string as when using the `strftime()` function for a `datetime` object. Default format string is `%Y-%m-%d %H:%M:%S`. Refer to the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) for further information. This parameter is optional. timestamps_fontsize (int): The font size for the displayed timestamps. Default is size 11. This parameter is optional. figsize (tuple): The matplotlib figure size to use when plotting. For example `figsize=(14,4)`. title (str): The title to display above the plotted montage. Default is no title. cmap (str): The matplotlib colormap to use. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed montage, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: ValueError: issues with the y-axis choice, or rows/cols choice. """ # check rows and cols if (rows * cols != self.data.shape[-1]): raise ValueError(("Invalid choice of rows and columns. The %d images in this Montage object " + "cannot be organized into a %dx%d grid (%d * %d != %d)") % ( self.data.shape[-1], rows, cols, rows, cols, self.data.shape[-1], )) # check return mode if (returnfig is True and savefig is True): raise ValueError("Only one of returnfig or savefig can be set to True") if (returnfig is True and (savefig_filename is not None or savefig_quality is not None)): show_warning("The figure will be returned, but a savefig option parameter was supplied. Consider " + "removing the savefig option parameter(s) as they will be ignored.", stacklevel=1) elif (savefig is False and (savefig_filename is not None or savefig_quality is not None)): show_warning("A savefig option parameter was supplied, but the savefig parameter is False. The " + "savefig option parameters will be ignored.", stacklevel=1) # init figure fig, axs = plt.subplots(nrows=rows, ncols=cols, figsize=figsize) # set title if (title is not None): fig.suptitle(title) # for each image for ax, i in zip(axs.flat, range(0, len(self.timestamp))): # type: ignore if (self.__n_channels == 1): # single channel ax.imshow(self.data[:, :, i], cmap=cmap, origin="lower", interpolation="nearest") elif (self.__n_channels == 3): # single channel ax.imshow(self.data[:, :, :, i], cmap=cmap, origin="lower", interpolation="nearest") else: # pragma: nocover raise ValueError("Can only plot 3 or 4 dimensional data (series of single-channel or RGB mages), but found data of shape %s" % (self.data.shape)) ax.set_axis_off() # show timestamp if (timestamps_display is True): ax.text( int(np.floor(self.data.shape[1] / 2.)), 5, self.timestamp[i].strftime(timestamps_format), ha="center", fontsize=timestamps_fontsize, ) plt.tight_layout(h_pad=0, w_pad=0) # save figure or show it if (savefig is True): # check that filename has been set if (savefig_filename is None): raise ValueError("The savefig_filename parameter is missing, but required since savefig was set to True.") # save the figure f_extension = os.path.splitext(savefig_filename)[-1].lower() if (".jpg" == f_extension or ".jpeg" == f_extension): # check quality setting if (savefig_quality is not None): # pragma: nocover plt.savefig(savefig_filename, quality=savefig_quality, bbox_inches="tight") else: plt.savefig(savefig_filename, bbox_inches="tight") else: if (savefig_quality is not None): # quality specified, but output filename is not a JPG, so show a warning show_warning("The savefig_quality parameter was specified, but is only used for saving JPG files. The " + "savefig_filename parameter was determined to not be a JPG file, so the quality will be ignored", stacklevel=1) plt.savefig(savefig_filename, bbox_inches="tight") # clean up by closing the figure plt.close(fig) elif (returnfig is True): # return the figure and axis objects return (fig, axs) else: # show the figure plt.show(fig) # cleanup by closing the figure plt.close(fig) # return return None
Generate a plot of the montage data.
Either display it (default behaviour), save it to disk (using the
savefig
parameter), or return the matplotlib plot object for further usage (using thereturnfig
parameter).Args
rows
:int
- The number of rows to use when displaying the images as a montage. The product of
the
rows
andcols
parameters must match the number of images supplied when creating theMontage
object. If not, a ValueError will be raised. This parameter is required. cols
:int
- The number of columns to use when displaying the images as a montage. The product of
the
rows
andcols
parameters must match the number of images supplied when creating theMontage
object. If not, a ValueError will be raised. This parameter is required. timestamps_display
:bool
- Display the timestamps on each montage image. Defaults to True. This parameter is optional.
timestamps_format
:str
- The format of the timestamps when being displayed. This is the same format string
as when using the
strftime()
function for adatetime
object. Default format string is%Y-%m-%d %H:%M:%S
. Refer to the Python documentation for further information. This parameter is optional. timestamps_fontsize
:int
- The font size for the displayed timestamps. Default is size 11. This parameter is optional.
figsize
:tuple
- The matplotlib figure size to use when plotting. For example
figsize=(14,4)
. title
:str
- The title to display above the plotted montage. Default is no title.
cmap
:str
-
The matplotlib colormap to use.
Commonly used colormaps are:
- REGO:
gist_heat
- THEMIS ASI:
gray
- TREx Blue:
Blues_r
- TREx NIR:
gray
- TREx RGB:
None
A list of all available colormaps can be found on the matplotlib documentation.
- REGO:
returnfig
:bool
-
Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default.
Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing
plt.close(fig)
.Note that this method cannot be used in combination with
savefig
. savefig
:bool
- Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if
this parameter is set to True. Defaults to
False
. savefig_filename
:str
- Filename to save the image to. Must be specified if the savefig parameter is set to True.
savefig_quality
:int
- Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%.
Returns
The displayed montage, by default. If
savefig
is set to True, nothing will be returned. Ifreturnfig
is set to True, the plotting variables(fig, ax)
will be returned.Raises
ValueError
- issues with the y-axis choice, or rows/cols choice.
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings data_str = "array(dims=%s, dtype=%s)" % (self.data.shape, self.data.dtype) timestamp_str = "[%d datetime objects]" % (len(self.timestamp)) # print print("Montage:") print(" %-11s: %s" % ("data", data_str)) print(" %-11s: %s" % ("timestamp", timestamp_str))
A special print output for this class.
class Mosaic (polygon_data: matplotlib.collections.PolyCollection | List[matplotlib.collections.PolyCollection],
cartopy_projection: cartopy.crs.Projection,
contour_data: Dict[str, List[Any]] | None = None,
spect_cmap: str | None = None,
spect_intensity_scale: Tuple[int, int] | None = None)-
Expand source code
@dataclass class Mosaic: """ Class representation for a generated mosaic. Attributes: polygon_data (matplotlib.collections.PolyCollection): Generated polygons containing rendered data. cartopy_projection (cartopy.crs.Projection): Cartopy projection to utilize. contour_data (Dict[str, List[Any]]): Generated contour data. spect_cmap (str): String giving the cmap to use for spect legend. spect_intensity_scale (Tuple[int]): The min and max values that spectrograph data is scaled to in the mosaic, if any is present. """ polygon_data: Union[PolyCollection, List[PolyCollection]] cartopy_projection: Projection contour_data: Optional[Dict[str, List[Any]]] = None spect_cmap: Optional[str] = None spect_intensity_scale: Optional[Tuple[int, int]] = None def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: if isinstance(self.polygon_data, list): polycollection_str = "[PolyCollection(...), ...]" else: polycollection_str = "PolyCollection(...)" if self.contour_data is not None: return "Mosaic(polygon_data=PolyCollection(...), cartopy_projection=Projection(%s), %d Contours)" % ( self.cartopy_projection.to_string(), len(self.contour_data.get("x", [])), ) else: return "Mosaic(polygon_data=" + polycollection_str + ", cartopy_projection=Projection(%s))" % (self.cartopy_projection.to_string()) def pretty_print(self): """ A special print output for this class. """ # set special strings if isinstance(self.polygon_data, list): polycollection_str = "[PolyCollection(...), ...]" else: polycollection_str = "PolyCollection(...)" cartopy_projection_str = "Projection(%s)" % (self.cartopy_projection.to_string()) if self.contour_data is not None: contour_data_str = "%d Contours" % (len(self.contour_data.get("x", [])), ) else: contour_data_str = "None" # print print("Mosaic:") print(" %-23s: %s" % ("polygon_data", polycollection_str)) print(" %-23s: %s" % ("cartopy_projection", cartopy_projection_str)) print(" %-23s: %s" % ("contour_data", contour_data_str)) print(" %-23s: %s" % ("spect_cmap", self.spect_cmap)) print(" %-23s: %s" % ("spect_intensity_scale", self.spect_intensity_scale)) def plot( self, map_extent: Sequence[Union[float, int]], figsize: Optional[Tuple[int, int]] = None, rayleighs: bool = False, max_rayleighs: int = 20000, title: Optional[str] = None, ocean_color: Optional[str] = None, land_color: str = "gray", land_edgecolor: str = "#8A8A8A", borders_color: str = "#AEAEAE", borders_disable: bool = False, colorbar_title: Optional[str] = None, # deprecated in v1.11.0, use cbar_title instead cbar_title: Optional[str] = None, cbar_colormap: str = "", returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Generate a plot of the mosaic data. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: map_extent (List[int]): Latitude/longitude range to be visible on the rendered map. This is a list of 4 integers and/or floats, in the order of [min_lon, max_lon, min_lat, max_lat]. figsize (tuple): The matplotlib figure size to use when plotting. For example `figsize=(14,4)`. rayleighs (bool): Set to `True` if the data being plotted is in Rayleighs. Defaults to `False`. max_rayleighs (int): Max intensity scale for Rayleighs. Defaults to `20000`. title (str): The title to display above the plotted mosaic. Default is no title. ocean_color (str): Colour of the ocean. Default is cartopy's default shade of blue. Colours can be supplied as a word, or hexcode prefixed with a '#' character (ie. `#55AADD`). land_color (str): Colour of the land. Default is `gray`. Colours can be supplied as a word, or hexcode prefixed with a '#' character (ie. `#41BB87`). land_edgecolor (str): Color of the land edges. Default is `#8A8A8A`. Colours can be supplied as a word, or hexcode prefixed with a '#' character. borders_color (str): Color of the country borders. Default is `AEAEAE`. Colours can be supplied as a word, or hexcode prefixed with a '#' character. borders_disable (bool): Disbale rendering of the borders. Default is `False`. cbar_title (str): Title for the colorbar. Default is no title. colorbar_title (str): Deprecated as of v1.10.0. Use 'cbar_title' instead in the exact same way. cbar_colormap (str): The matplotlib colormap to use for the plotted color bar. Default is `gray`, unless mosaic was created with spectrograph data, in which case defaults to the colormap used for spectrograph data.. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed montage, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: """ # handle deprecation warnings if (colorbar_title is not None): show_warning("The parameter 'colorbar_title' was deprecated in v1.11.0. Please use 'cbar_title' instead (usage is identical).", stacklevel=1) cbar_title = colorbar_title # check return mode if (returnfig is True and savefig is True): raise ValueError("Only one of returnfig or savefig can be set to True") if returnfig is True and (savefig_filename is not None or savefig_quality is not None): show_warning("The figure will be returned, but a savefig option parameter was supplied. Consider " + "removing the savefig option parameter(s) as they will be ignored.", stacklevel=1) elif (savefig is False and (savefig_filename is not None or savefig_quality is not None)): show_warning("A savefig option parameter was supplied, but the savefig parameter is False. The " + "savefig option parameters will be ignored.", stacklevel=1) # get colormap if there is spectrograph data if self.spect_cmap is not None: cbar_colormap = self.spect_cmap # initialize figure fig = plt.figure(figsize=figsize) ax = fig.add_axes((0, 0, 1, 1), projection=self.cartopy_projection) ax.set_extent(map_extent, crs=cartopy.crs.Geodetic()) # type: ignore # add ocean # # NOTE: we use the default ocean color if (ocean_color is not None): ax.add_feature( # type: ignore cartopy.feature.OCEAN, facecolor=ocean_color, zorder=0) else: ax.add_feature(cartopy.feature.OCEAN, zorder=0) # type: ignore # add land ax.add_feature( # type: ignore cartopy.feature.LAND, facecolor=land_color, edgecolor=land_edgecolor, zorder=0) # add borders if (borders_disable is False): ax.add_feature( # type: ignore cartopy.feature.BORDERS, edgecolor=borders_color, zorder=0) # add polygon data # # NOTE: it seems that when running this function a second time, the polygon # data is not too happy. So to handle this, we plot a copy of the polygon data if isinstance(self.polygon_data, list): for polygon_data in self.polygon_data: ax.add_collection(copy(polygon_data)) else: ax.add_collection(copy(self.polygon_data)) if self.contour_data is not None: for i in range(len(self.contour_data["x"])): ax.plot(self.contour_data["x"][i], self.contour_data["y"][i], color=self.contour_data["color"][i], linewidth=self.contour_data["linewidth"][i], linestyle=self.contour_data["linestyle"][i], marker=self.contour_data["marker"][i], zorder=self.contour_data["zorder"][i]) # set title if (title is not None): ax.set_title(title) # add text if (rayleighs is True): if isinstance(self.polygon_data, list): raise ValueError("Rayleighs Keyword is currently not available for mosaics with multiple sets of data.") # Create a colorbar, in Rayleighs, that accounts for the scaling limit we applied cbar_ticks = [float(j) / 5. for j in range(0, 6)] cbar_ticknames = [str(int(max_rayleighs / 5) * j) for j in range(0, 6)] # Any pixels with the max Rayleigh value could be greater than it, so we include the plus sign cbar_ticknames[-1] += "+" self.polygon_data.set_cmap(cbar_colormap) cbar = plt.colorbar(self.polygon_data, shrink=0.5, ticks=cbar_ticks, ax=ax) cbar.ax.set_yticklabels(cbar_ticknames) plt.text(1.025, 0.5, "Intensity (Rayleighs)", fontsize=14, transform=ax.transAxes, va="center", rotation="vertical", weight="bold", style="oblique") if (self.spect_cmap) is not None: if (self.spect_intensity_scale) is None: intensity_max = np.nan intensity_min = np.nan else: intensity_max = self.spect_intensity_scale[1] intensity_min = self.spect_intensity_scale[0] # Create a colorbar, in Rayleighs, that accounts for the scaling limit we applied cbar_ticks = [float(j) / 5. for j in range(0, 6)] cbar_ticknames = [str(int((intensity_max / 5) + intensity_min) * j) for j in range(0, 6)] # Any specrograph bins with the max intensity value could be greater than it, so we include the plus sign cbar_ticknames[-1] += "+" if isinstance(self.polygon_data, list): self.polygon_data[0].set_cmap(cbar_colormap) else: self.polygon_data.set_cmap(cbar_colormap) if isinstance(self.polygon_data, list): cbar = plt.colorbar(self.polygon_data[0], shrink=0.5, ticks=cbar_ticks, ax=ax) else: cbar = plt.colorbar(self.polygon_data, shrink=0.5, ticks=cbar_ticks, ax=ax) cbar.ax.set_yticklabels(cbar_ticknames) if (cbar_title is None): plt.text(1.025, 0.5, "Spectrograph Intensity (Rayleighs)", fontsize=10, transform=ax.transAxes, va="center", rotation="vertical", weight="bold", style="oblique") else: plt.text(1.025, 0.5, cbar_title, fontsize=10, transform=ax.transAxes, va="center", rotation="vertical", weight="bold", style="oblique") # save figure or show it if (savefig is True): # check that filename has been set if (savefig_filename is None): raise ValueError("The savefig_filename parameter is missing, but required since savefig was set to True.") # save the figure f_extension = os.path.splitext(savefig_filename)[-1].lower() if (".jpg" == f_extension or ".jpeg" == f_extension): # check quality setting if (savefig_quality is not None): plt.savefig(savefig_filename, quality=savefig_quality, bbox_inches="tight") else: plt.savefig(savefig_filename, bbox_inches="tight") else: if (savefig_quality is not None): # quality specified, but output filename is not a JPG, so show a warning show_warning("The savefig_quality parameter was specified, but is only used for saving JPG files. The " + "savefig_filename parameter was determined to not be a JPG file, so the quality will be ignored", stacklevel=1) plt.savefig(savefig_filename, bbox_inches="tight") # clean up by closing the figure plt.close(fig) elif (returnfig is True): # return the figure and axis objects return (fig, ax) else: # show the figure plt.show(fig) # cleanup by closing the figure plt.close(fig) # return return None def add_geo_contours(self, lats: Optional[Union[ndarray, list]] = None, lons: Optional[Union[ndarray, list]] = None, constant_lats: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, constant_lons: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, color: str = "black", linewidth: Union[float, int] = 1, linestyle: str = "solid", marker: str = "", bring_to_front: bool = False): """ Add geographic contours to a mosaic. Args: lats (ndarray or list): Sequence of geographic latitudes defining a contour. lons (ndarray or list): Sequence of geographic longitudes defining a contour. constant_lats (float, int, or Sequence): Geographic Latitude(s) at which to add line(s) of constant latitude. constant_lons (float, int, or Sequence): Geographic Longitude(s) at which to add line(s) of constant longitude. color (str): The matplotlib color used for the contour(s). linewidth (float or int): The contour thickness. linestyle (str): The matplotlib linestyle used for the contour(s). marker (str): The matplotlib marker used for the contour(s). bring_to_front (bool): Plots the contour on top of all other currently plotted objects. Returns: The object's contour_data parameter is populated appropriately. Raises: ValueError: issues encountered with supplied parameters. """ # Make sure some form of lat/lon is provided if (constant_lats is None) and (constant_lons is None) and (lats is None) and (lons is None): raise ValueError("No latitudes or longitudes provided.") # If manually passing in lats & lons, make sure both are provided if (lats is not None or lons is not None) and (lats is None or lons is None): raise (ValueError("Manually supplying contour requires both lats and lons.")) # Check that color exists in matplotlib if color not in matplotlib.colors.CSS4_COLORS: raise ValueError(f"Color '{color}' not recognized by matplotlib.") # Check that linestyle is valid if linestyle not in ["-", "--", "-.", ":", "solid", "dashed", "dashdot", "dotted"]: raise ValueError(f"Linestyle '{linestyle}' not recognized by matplotlib.") # Check that linewidth is valid if linewidth <= 0: raise ValueError("Linewidth must be greater than zero.") # Check that marker is valid if marker not in ["", "o", ".", "p", "*", "x", "+", "X"]: raise ValueError(f"Marker '{marker}' is not currently supported.") # Convert numerics to lists if necessary if constant_lats is not None: if isinstance(constant_lats, (float, int)): constant_lats = [constant_lats] if constant_lons is not None: if isinstance(constant_lons, (float, int)): constant_lons = [constant_lons] # Initialize contour data dict if it doesn't exist yet if self.contour_data is None: self.contour_data = {"x": [], "y": [], "color": [], "linewidth": [], "linestyle": [], "marker": [], "zorder": []} # Obtain the mosaic's projection source_proj = pyproj.CRS.from_user_input(cartopy.crs.Geodetic()) mosaic_proj = pyproj.CRS.from_user_input(self.cartopy_projection) transformer = pyproj.Transformer.from_crs(source_proj, mosaic_proj, always_xy=True) # First handling manually supplied lat/lon arrays if (lats is not None) and (lons is not None): # Convert lists to ndarrays if necessary if isinstance(lats, list): lats = np.array(lats) if isinstance(lons, list): lons = np.array(lons) if len(lats) != len(lons): raise ValueError("Lat/Lon data must be of the same size.") # Create specified contour from geographic coords x, y = transformer.transform(lons, lats) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(x) self.contour_data["y"].append(y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Next handling lines of constant latitude if constant_lats is not None: # Generate longitudinal domain of the lat line (full globe) lon_domain = np.arange(-180, 180 + 0.2, 0.2) # Iterate through all lines of constant lat requested for lat in constant_lats: # Create line of constant lat const_lat_x, const_lat_y = (lon_domain, lon_domain * 0 + lat) sort_idx = np.argsort(const_lat_x) const_lat_y = const_lat_y[sort_idx] const_lat_x = const_lat_x[sort_idx] const_lat_x, const_lat_y = transformer.transform(const_lat_x, const_lat_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lat_x) self.contour_data["y"].append(const_lat_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Now handling lines of constant longitude if constant_lons is not None: # Generate latitudinal domain of the lon line (full globe) lat_domain = np.arange(-90, 90 + 0.1, 0.1) # Iterate through all lines of constant lon requested for lon in constant_lons: # Create line of constant lon and add to dict const_lon_x, const_lon_y = (lat_domain * 0 + lon, lat_domain) sort_idx = np.argsort(const_lon_y) const_lon_x = const_lon_x[sort_idx] const_lon_y = const_lon_y[sort_idx] const_lon_x, const_lon_y = transformer.transform(const_lon_x, const_lon_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lon_x) self.contour_data["y"].append(const_lon_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) def add_mag_contours(self, timestamp: datetime.datetime, constant_lats: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, constant_lons: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, lats: Optional[Union[ndarray, list]] = None, lons: Optional[Union[ndarray, list]] = None, color: str = "black", linewidth: Union[float, int] = 1, linestyle: str = "solid", marker: str = "", bring_to_front: bool = False): """ Add geomagnetic contours to a mosaic. Args: timestamp (datetime.datetime): The timestamp used in computing AACGM coordinates. lats (ndarray or list): Sequence of geomagnetic latitudes defining a contour. lons (ndarray or list): Sequence of geomagnetic longitudes defining a contour. constant_lats (float, int, Sequence): Geomagnetic latitude(s) at which to add contour(s) of constant latitude. constant_lons (float, int, Sequence): Geomagnetic longitude(s) at which to add contours(s) of constant longitude. color (str): The matplotlib color used for the contour(s). linewidth (float or int): The contour thickness. linestyle (str): The matplotlib linestyle used for the contour(s). marker (str): The matplotlib marker used for the contour(s). bring_to_front (bool): Plots the contour on top of all other currently plotted objects. Returns: The object's contour_data parameter is populated appropriately. Raises: ValueError: issues encountered with supplied parameters """ # Make sure some form of lat/lon is provided if (constant_lats is None) and (constant_lons is None) and (lats is None) and (lons is None): raise ValueError("No latitudes or longitudes provided.") # If manually passing in lats & lons, make sure both are provided if (lats is not None or lons is not None) and (lats is None or lons is None): raise ValueError("Manually supplying contour requires both lats and lons.") # Check that color exists in matplotlib if color not in matplotlib.colors.CSS4_COLORS: raise ValueError(f"Color '{color}' not recognized by matplotlib.") # Check that linestyle is valid if linestyle not in ["-", "--", "-.", ":", "solid", "dashed", "dashdot", "dotted"]: raise ValueError(f"Linestyle '{linestyle}' not recognized by matplotlib.") # Check that linewidth is valid if linewidth <= 0: raise ValueError("linewidth must be greater than zero.") # Convert numerics to lists if necessary if constant_lats is not None: if isinstance(constant_lats, (float, int)): constant_lats = [constant_lats] if constant_lons is not None: if isinstance(constant_lons, (float, int)): constant_lons = [constant_lons] # Initialize contour data dict if it doesn't exist yet if self.contour_data is None: self.contour_data = {"x": [], "y": [], "color": [], "linewidth": [], "linestyle": [], "marker": [], "zorder": []} # Obtain the mosaic's projection source_proj = pyproj.CRS.from_user_input(cartopy.crs.Geodetic()) mosaic_proj = pyproj.CRS.from_user_input(self.cartopy_projection) transformer = pyproj.Transformer.from_crs(source_proj, mosaic_proj, always_xy=True) # First handling manually supplied lat/lon arrays if (lats is not None) and (lons is not None): # Convert lists to ndarrays if necessary if isinstance(lats, list): lats = np.array(lats) if isinstance(lons, list): lons = np.array(lons) if len(lats) != len(lons): raise ValueError("Lat/Lon data must be of the same size.") # Create specified contour from magnetic coords y, x, alt = aacgmv2.convert_latlon_arr(lats, lons, lats * 0.0, timestamp, method_code="A2G") x, y = transformer.transform(x, y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(x) self.contour_data["y"].append(y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Next handling lines of constant latitude if constant_lats is not None: # Generate longitudinal domain of the lat line (full globe) lon_domain = np.arange(-180, 180 + 0.2, 0.2) # iterate through all lines of constant lat requested for lat in constant_lats: # Create line of constant lat from magnetic coords const_lat_x, const_lat_y = (lon_domain, lon_domain * 0 + lat) const_lat_y, const_lat_x, alt = aacgmv2.convert_latlon_arr(const_lat_y, const_lat_x, const_lat_x * 0.0, timestamp, method_code="A2G") sort_idx = np.argsort(const_lat_x) const_lat_y = const_lat_y[sort_idx] const_lat_x = const_lat_x[sort_idx] const_lat_x, const_lat_y = transformer.transform(const_lat_x, const_lat_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lat_x) self.contour_data["y"].append(const_lat_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Now handling lines of constant longitude if constant_lons is not None: # Generate latitudinal domain of the lon line (full globe) lat_domain = np.arange(-90, 90 + 0.1, 0.1) # iterate through all lines of constant lon requested for lon in constant_lons: # Create line of constant lon from magnetic coords const_lon_x, const_lon_y = (lat_domain * 0 + lon, lat_domain) const_lon_y, const_lon_x, alt = aacgmv2.convert_latlon_arr(const_lon_y, const_lon_x, const_lon_x * 0.0, timestamp, method_code="A2G") sort_idx = np.argsort(const_lon_y) const_lon_x = const_lon_x[sort_idx] const_lon_y = const_lon_y[sort_idx] const_lon_x, const_lon_y = transformer.transform(const_lon_x, const_lon_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lon_x) self.contour_data["y"].append(const_lon_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front))
Class representation for a generated mosaic.
Attributes
polygon_data
:matplotlib.collections.PolyCollection
- Generated polygons containing rendered data.
cartopy_projection
:cartopy.crs.Projection
- Cartopy projection to utilize.
contour_data
:Dict[str, List[Any]]
- Generated contour data.
spect_cmap
:str
- String giving the cmap to use for spect legend.
spect_intensity_scale
:Tuple[int]
- The min and max values that spectrograph data is scaled to in the mosaic, if any is present.
Class variables
var cartopy_projection : cartopy.crs.Projection
var contour_data : Dict[str, List[Any]] | None
var polygon_data : matplotlib.collections.PolyCollection | List[matplotlib.collections.PolyCollection]
var spect_cmap : str | None
var spect_intensity_scale : Tuple[int, int] | None
Methods
def add_geo_contours(self,
lats: numpy.ndarray | list | None = None,
lons: numpy.ndarray | list | None = None,
constant_lats: float | int | Sequence[float | int] | numpy.ndarray | None = None,
constant_lons: float | int | Sequence[float | int] | numpy.ndarray | None = None,
color: str = 'black',
linewidth: float | int = 1,
linestyle: str = 'solid',
marker: str = '',
bring_to_front: bool = False)-
Expand source code
def add_geo_contours(self, lats: Optional[Union[ndarray, list]] = None, lons: Optional[Union[ndarray, list]] = None, constant_lats: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, constant_lons: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, color: str = "black", linewidth: Union[float, int] = 1, linestyle: str = "solid", marker: str = "", bring_to_front: bool = False): """ Add geographic contours to a mosaic. Args: lats (ndarray or list): Sequence of geographic latitudes defining a contour. lons (ndarray or list): Sequence of geographic longitudes defining a contour. constant_lats (float, int, or Sequence): Geographic Latitude(s) at which to add line(s) of constant latitude. constant_lons (float, int, or Sequence): Geographic Longitude(s) at which to add line(s) of constant longitude. color (str): The matplotlib color used for the contour(s). linewidth (float or int): The contour thickness. linestyle (str): The matplotlib linestyle used for the contour(s). marker (str): The matplotlib marker used for the contour(s). bring_to_front (bool): Plots the contour on top of all other currently plotted objects. Returns: The object's contour_data parameter is populated appropriately. Raises: ValueError: issues encountered with supplied parameters. """ # Make sure some form of lat/lon is provided if (constant_lats is None) and (constant_lons is None) and (lats is None) and (lons is None): raise ValueError("No latitudes or longitudes provided.") # If manually passing in lats & lons, make sure both are provided if (lats is not None or lons is not None) and (lats is None or lons is None): raise (ValueError("Manually supplying contour requires both lats and lons.")) # Check that color exists in matplotlib if color not in matplotlib.colors.CSS4_COLORS: raise ValueError(f"Color '{color}' not recognized by matplotlib.") # Check that linestyle is valid if linestyle not in ["-", "--", "-.", ":", "solid", "dashed", "dashdot", "dotted"]: raise ValueError(f"Linestyle '{linestyle}' not recognized by matplotlib.") # Check that linewidth is valid if linewidth <= 0: raise ValueError("Linewidth must be greater than zero.") # Check that marker is valid if marker not in ["", "o", ".", "p", "*", "x", "+", "X"]: raise ValueError(f"Marker '{marker}' is not currently supported.") # Convert numerics to lists if necessary if constant_lats is not None: if isinstance(constant_lats, (float, int)): constant_lats = [constant_lats] if constant_lons is not None: if isinstance(constant_lons, (float, int)): constant_lons = [constant_lons] # Initialize contour data dict if it doesn't exist yet if self.contour_data is None: self.contour_data = {"x": [], "y": [], "color": [], "linewidth": [], "linestyle": [], "marker": [], "zorder": []} # Obtain the mosaic's projection source_proj = pyproj.CRS.from_user_input(cartopy.crs.Geodetic()) mosaic_proj = pyproj.CRS.from_user_input(self.cartopy_projection) transformer = pyproj.Transformer.from_crs(source_proj, mosaic_proj, always_xy=True) # First handling manually supplied lat/lon arrays if (lats is not None) and (lons is not None): # Convert lists to ndarrays if necessary if isinstance(lats, list): lats = np.array(lats) if isinstance(lons, list): lons = np.array(lons) if len(lats) != len(lons): raise ValueError("Lat/Lon data must be of the same size.") # Create specified contour from geographic coords x, y = transformer.transform(lons, lats) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(x) self.contour_data["y"].append(y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Next handling lines of constant latitude if constant_lats is not None: # Generate longitudinal domain of the lat line (full globe) lon_domain = np.arange(-180, 180 + 0.2, 0.2) # Iterate through all lines of constant lat requested for lat in constant_lats: # Create line of constant lat const_lat_x, const_lat_y = (lon_domain, lon_domain * 0 + lat) sort_idx = np.argsort(const_lat_x) const_lat_y = const_lat_y[sort_idx] const_lat_x = const_lat_x[sort_idx] const_lat_x, const_lat_y = transformer.transform(const_lat_x, const_lat_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lat_x) self.contour_data["y"].append(const_lat_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Now handling lines of constant longitude if constant_lons is not None: # Generate latitudinal domain of the lon line (full globe) lat_domain = np.arange(-90, 90 + 0.1, 0.1) # Iterate through all lines of constant lon requested for lon in constant_lons: # Create line of constant lon and add to dict const_lon_x, const_lon_y = (lat_domain * 0 + lon, lat_domain) sort_idx = np.argsort(const_lon_y) const_lon_x = const_lon_x[sort_idx] const_lon_y = const_lon_y[sort_idx] const_lon_x, const_lon_y = transformer.transform(const_lon_x, const_lon_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lon_x) self.contour_data["y"].append(const_lon_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front))
Add geographic contours to a mosaic.
Args
lats
:ndarray
orlist
- Sequence of geographic latitudes defining a contour.
lons
:ndarray
orlist
- Sequence of geographic longitudes defining a contour.
constant_lats
:float, int,
orSequence
- Geographic Latitude(s) at which to add line(s) of constant latitude.
constant_lons
:float, int,
orSequence
- Geographic Longitude(s) at which to add line(s) of constant longitude.
color
:str
- The matplotlib color used for the contour(s).
linewidth
:float
orint
- The contour thickness.
linestyle
:str
- The matplotlib linestyle used for the contour(s).
marker
:str
- The matplotlib marker used for the contour(s).
bring_to_front
:bool
- Plots the contour on top of all other currently plotted objects.
Returns
The object's contour_data parameter is populated appropriately.
Raises
ValueError
- issues encountered with supplied parameters.
def add_mag_contours(self,
timestamp: datetime.datetime,
constant_lats: float | int | Sequence[float | int] | numpy.ndarray | None = None,
constant_lons: float | int | Sequence[float | int] | numpy.ndarray | None = None,
lats: numpy.ndarray | list | None = None,
lons: numpy.ndarray | list | None = None,
color: str = 'black',
linewidth: float | int = 1,
linestyle: str = 'solid',
marker: str = '',
bring_to_front: bool = False)-
Expand source code
def add_mag_contours(self, timestamp: datetime.datetime, constant_lats: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, constant_lons: Optional[Union[float, int, Sequence[Union[float, int]], ndarray]] = None, lats: Optional[Union[ndarray, list]] = None, lons: Optional[Union[ndarray, list]] = None, color: str = "black", linewidth: Union[float, int] = 1, linestyle: str = "solid", marker: str = "", bring_to_front: bool = False): """ Add geomagnetic contours to a mosaic. Args: timestamp (datetime.datetime): The timestamp used in computing AACGM coordinates. lats (ndarray or list): Sequence of geomagnetic latitudes defining a contour. lons (ndarray or list): Sequence of geomagnetic longitudes defining a contour. constant_lats (float, int, Sequence): Geomagnetic latitude(s) at which to add contour(s) of constant latitude. constant_lons (float, int, Sequence): Geomagnetic longitude(s) at which to add contours(s) of constant longitude. color (str): The matplotlib color used for the contour(s). linewidth (float or int): The contour thickness. linestyle (str): The matplotlib linestyle used for the contour(s). marker (str): The matplotlib marker used for the contour(s). bring_to_front (bool): Plots the contour on top of all other currently plotted objects. Returns: The object's contour_data parameter is populated appropriately. Raises: ValueError: issues encountered with supplied parameters """ # Make sure some form of lat/lon is provided if (constant_lats is None) and (constant_lons is None) and (lats is None) and (lons is None): raise ValueError("No latitudes or longitudes provided.") # If manually passing in lats & lons, make sure both are provided if (lats is not None or lons is not None) and (lats is None or lons is None): raise ValueError("Manually supplying contour requires both lats and lons.") # Check that color exists in matplotlib if color not in matplotlib.colors.CSS4_COLORS: raise ValueError(f"Color '{color}' not recognized by matplotlib.") # Check that linestyle is valid if linestyle not in ["-", "--", "-.", ":", "solid", "dashed", "dashdot", "dotted"]: raise ValueError(f"Linestyle '{linestyle}' not recognized by matplotlib.") # Check that linewidth is valid if linewidth <= 0: raise ValueError("linewidth must be greater than zero.") # Convert numerics to lists if necessary if constant_lats is not None: if isinstance(constant_lats, (float, int)): constant_lats = [constant_lats] if constant_lons is not None: if isinstance(constant_lons, (float, int)): constant_lons = [constant_lons] # Initialize contour data dict if it doesn't exist yet if self.contour_data is None: self.contour_data = {"x": [], "y": [], "color": [], "linewidth": [], "linestyle": [], "marker": [], "zorder": []} # Obtain the mosaic's projection source_proj = pyproj.CRS.from_user_input(cartopy.crs.Geodetic()) mosaic_proj = pyproj.CRS.from_user_input(self.cartopy_projection) transformer = pyproj.Transformer.from_crs(source_proj, mosaic_proj, always_xy=True) # First handling manually supplied lat/lon arrays if (lats is not None) and (lons is not None): # Convert lists to ndarrays if necessary if isinstance(lats, list): lats = np.array(lats) if isinstance(lons, list): lons = np.array(lons) if len(lats) != len(lons): raise ValueError("Lat/Lon data must be of the same size.") # Create specified contour from magnetic coords y, x, alt = aacgmv2.convert_latlon_arr(lats, lons, lats * 0.0, timestamp, method_code="A2G") x, y = transformer.transform(x, y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(x) self.contour_data["y"].append(y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Next handling lines of constant latitude if constant_lats is not None: # Generate longitudinal domain of the lat line (full globe) lon_domain = np.arange(-180, 180 + 0.2, 0.2) # iterate through all lines of constant lat requested for lat in constant_lats: # Create line of constant lat from magnetic coords const_lat_x, const_lat_y = (lon_domain, lon_domain * 0 + lat) const_lat_y, const_lat_x, alt = aacgmv2.convert_latlon_arr(const_lat_y, const_lat_x, const_lat_x * 0.0, timestamp, method_code="A2G") sort_idx = np.argsort(const_lat_x) const_lat_y = const_lat_y[sort_idx] const_lat_x = const_lat_x[sort_idx] const_lat_x, const_lat_y = transformer.transform(const_lat_x, const_lat_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lat_x) self.contour_data["y"].append(const_lat_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front)) # Now handling lines of constant longitude if constant_lons is not None: # Generate latitudinal domain of the lon line (full globe) lat_domain = np.arange(-90, 90 + 0.1, 0.1) # iterate through all lines of constant lon requested for lon in constant_lons: # Create line of constant lon from magnetic coords const_lon_x, const_lon_y = (lat_domain * 0 + lon, lat_domain) const_lon_y, const_lon_x, alt = aacgmv2.convert_latlon_arr(const_lon_y, const_lon_x, const_lon_x * 0.0, timestamp, method_code="A2G") sort_idx = np.argsort(const_lon_y) const_lon_x = const_lon_x[sort_idx] const_lon_y = const_lon_y[sort_idx] const_lon_x, const_lon_y = transformer.transform(const_lon_x, const_lon_y) # Add contour to dict, along with color and linewidth self.contour_data["x"].append(const_lon_x) self.contour_data["y"].append(const_lon_y) self.contour_data["color"].append(color) self.contour_data["linewidth"].append(linewidth) self.contour_data["linestyle"].append(linestyle) self.contour_data["marker"].append(marker) self.contour_data["zorder"].append(int(bring_to_front))
Add geomagnetic contours to a mosaic.
Args
timestamp
:datetime.datetime
- The timestamp used in computing AACGM coordinates.
lats
:ndarray
orlist
- Sequence of geomagnetic latitudes defining a contour.
lons
:ndarray
orlist
- Sequence of geomagnetic longitudes defining a contour.
constant_lats
:float, int, Sequence
- Geomagnetic latitude(s) at which to add contour(s) of constant latitude.
constant_lons
:float, int, Sequence
- Geomagnetic longitude(s) at which to add contours(s) of constant longitude.
color
:str
- The matplotlib color used for the contour(s).
linewidth
:float
orint
- The contour thickness.
linestyle
:str
- The matplotlib linestyle used for the contour(s).
marker
:str
- The matplotlib marker used for the contour(s).
bring_to_front
:bool
- Plots the contour on top of all other currently plotted objects.
Returns
The object's contour_data parameter is populated appropriately.
Raises
ValueError
- issues encountered with supplied parameters
def plot(self,
map_extent: Sequence[float | int],
figsize: Tuple[int, int] | None = None,
rayleighs: bool = False,
max_rayleighs: int = 20000,
title: str | None = None,
ocean_color: str | None = None,
land_color: str = 'gray',
land_edgecolor: str = '#8A8A8A',
borders_color: str = '#AEAEAE',
borders_disable: bool = False,
colorbar_title: str | None = None,
cbar_title: str | None = None,
cbar_colormap: str = '',
returnfig: bool = False,
savefig: bool = False,
savefig_filename: str | None = None,
savefig_quality: int | None = None) ‑> Any-
Expand source code
def plot( self, map_extent: Sequence[Union[float, int]], figsize: Optional[Tuple[int, int]] = None, rayleighs: bool = False, max_rayleighs: int = 20000, title: Optional[str] = None, ocean_color: Optional[str] = None, land_color: str = "gray", land_edgecolor: str = "#8A8A8A", borders_color: str = "#AEAEAE", borders_disable: bool = False, colorbar_title: Optional[str] = None, # deprecated in v1.11.0, use cbar_title instead cbar_title: Optional[str] = None, cbar_colormap: str = "", returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Generate a plot of the mosaic data. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: map_extent (List[int]): Latitude/longitude range to be visible on the rendered map. This is a list of 4 integers and/or floats, in the order of [min_lon, max_lon, min_lat, max_lat]. figsize (tuple): The matplotlib figure size to use when plotting. For example `figsize=(14,4)`. rayleighs (bool): Set to `True` if the data being plotted is in Rayleighs. Defaults to `False`. max_rayleighs (int): Max intensity scale for Rayleighs. Defaults to `20000`. title (str): The title to display above the plotted mosaic. Default is no title. ocean_color (str): Colour of the ocean. Default is cartopy's default shade of blue. Colours can be supplied as a word, or hexcode prefixed with a '#' character (ie. `#55AADD`). land_color (str): Colour of the land. Default is `gray`. Colours can be supplied as a word, or hexcode prefixed with a '#' character (ie. `#41BB87`). land_edgecolor (str): Color of the land edges. Default is `#8A8A8A`. Colours can be supplied as a word, or hexcode prefixed with a '#' character. borders_color (str): Color of the country borders. Default is `AEAEAE`. Colours can be supplied as a word, or hexcode prefixed with a '#' character. borders_disable (bool): Disbale rendering of the borders. Default is `False`. cbar_title (str): Title for the colorbar. Default is no title. colorbar_title (str): Deprecated as of v1.10.0. Use 'cbar_title' instead in the exact same way. cbar_colormap (str): The matplotlib colormap to use for the plotted color bar. Default is `gray`, unless mosaic was created with spectrograph data, in which case defaults to the colormap used for spectrograph data.. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed montage, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: """ # handle deprecation warnings if (colorbar_title is not None): show_warning("The parameter 'colorbar_title' was deprecated in v1.11.0. Please use 'cbar_title' instead (usage is identical).", stacklevel=1) cbar_title = colorbar_title # check return mode if (returnfig is True and savefig is True): raise ValueError("Only one of returnfig or savefig can be set to True") if returnfig is True and (savefig_filename is not None or savefig_quality is not None): show_warning("The figure will be returned, but a savefig option parameter was supplied. Consider " + "removing the savefig option parameter(s) as they will be ignored.", stacklevel=1) elif (savefig is False and (savefig_filename is not None or savefig_quality is not None)): show_warning("A savefig option parameter was supplied, but the savefig parameter is False. The " + "savefig option parameters will be ignored.", stacklevel=1) # get colormap if there is spectrograph data if self.spect_cmap is not None: cbar_colormap = self.spect_cmap # initialize figure fig = plt.figure(figsize=figsize) ax = fig.add_axes((0, 0, 1, 1), projection=self.cartopy_projection) ax.set_extent(map_extent, crs=cartopy.crs.Geodetic()) # type: ignore # add ocean # # NOTE: we use the default ocean color if (ocean_color is not None): ax.add_feature( # type: ignore cartopy.feature.OCEAN, facecolor=ocean_color, zorder=0) else: ax.add_feature(cartopy.feature.OCEAN, zorder=0) # type: ignore # add land ax.add_feature( # type: ignore cartopy.feature.LAND, facecolor=land_color, edgecolor=land_edgecolor, zorder=0) # add borders if (borders_disable is False): ax.add_feature( # type: ignore cartopy.feature.BORDERS, edgecolor=borders_color, zorder=0) # add polygon data # # NOTE: it seems that when running this function a second time, the polygon # data is not too happy. So to handle this, we plot a copy of the polygon data if isinstance(self.polygon_data, list): for polygon_data in self.polygon_data: ax.add_collection(copy(polygon_data)) else: ax.add_collection(copy(self.polygon_data)) if self.contour_data is not None: for i in range(len(self.contour_data["x"])): ax.plot(self.contour_data["x"][i], self.contour_data["y"][i], color=self.contour_data["color"][i], linewidth=self.contour_data["linewidth"][i], linestyle=self.contour_data["linestyle"][i], marker=self.contour_data["marker"][i], zorder=self.contour_data["zorder"][i]) # set title if (title is not None): ax.set_title(title) # add text if (rayleighs is True): if isinstance(self.polygon_data, list): raise ValueError("Rayleighs Keyword is currently not available for mosaics with multiple sets of data.") # Create a colorbar, in Rayleighs, that accounts for the scaling limit we applied cbar_ticks = [float(j) / 5. for j in range(0, 6)] cbar_ticknames = [str(int(max_rayleighs / 5) * j) for j in range(0, 6)] # Any pixels with the max Rayleigh value could be greater than it, so we include the plus sign cbar_ticknames[-1] += "+" self.polygon_data.set_cmap(cbar_colormap) cbar = plt.colorbar(self.polygon_data, shrink=0.5, ticks=cbar_ticks, ax=ax) cbar.ax.set_yticklabels(cbar_ticknames) plt.text(1.025, 0.5, "Intensity (Rayleighs)", fontsize=14, transform=ax.transAxes, va="center", rotation="vertical", weight="bold", style="oblique") if (self.spect_cmap) is not None: if (self.spect_intensity_scale) is None: intensity_max = np.nan intensity_min = np.nan else: intensity_max = self.spect_intensity_scale[1] intensity_min = self.spect_intensity_scale[0] # Create a colorbar, in Rayleighs, that accounts for the scaling limit we applied cbar_ticks = [float(j) / 5. for j in range(0, 6)] cbar_ticknames = [str(int((intensity_max / 5) + intensity_min) * j) for j in range(0, 6)] # Any specrograph bins with the max intensity value could be greater than it, so we include the plus sign cbar_ticknames[-1] += "+" if isinstance(self.polygon_data, list): self.polygon_data[0].set_cmap(cbar_colormap) else: self.polygon_data.set_cmap(cbar_colormap) if isinstance(self.polygon_data, list): cbar = plt.colorbar(self.polygon_data[0], shrink=0.5, ticks=cbar_ticks, ax=ax) else: cbar = plt.colorbar(self.polygon_data, shrink=0.5, ticks=cbar_ticks, ax=ax) cbar.ax.set_yticklabels(cbar_ticknames) if (cbar_title is None): plt.text(1.025, 0.5, "Spectrograph Intensity (Rayleighs)", fontsize=10, transform=ax.transAxes, va="center", rotation="vertical", weight="bold", style="oblique") else: plt.text(1.025, 0.5, cbar_title, fontsize=10, transform=ax.transAxes, va="center", rotation="vertical", weight="bold", style="oblique") # save figure or show it if (savefig is True): # check that filename has been set if (savefig_filename is None): raise ValueError("The savefig_filename parameter is missing, but required since savefig was set to True.") # save the figure f_extension = os.path.splitext(savefig_filename)[-1].lower() if (".jpg" == f_extension or ".jpeg" == f_extension): # check quality setting if (savefig_quality is not None): plt.savefig(savefig_filename, quality=savefig_quality, bbox_inches="tight") else: plt.savefig(savefig_filename, bbox_inches="tight") else: if (savefig_quality is not None): # quality specified, but output filename is not a JPG, so show a warning show_warning("The savefig_quality parameter was specified, but is only used for saving JPG files. The " + "savefig_filename parameter was determined to not be a JPG file, so the quality will be ignored", stacklevel=1) plt.savefig(savefig_filename, bbox_inches="tight") # clean up by closing the figure plt.close(fig) elif (returnfig is True): # return the figure and axis objects return (fig, ax) else: # show the figure plt.show(fig) # cleanup by closing the figure plt.close(fig) # return return None
Generate a plot of the mosaic data.
Either display it (default behaviour), save it to disk (using the
savefig
parameter), or return the matplotlib plot object for further usage (using thereturnfig
parameter).Args
map_extent
:List[int]
- Latitude/longitude range to be visible on the rendered map. This is a list of 4 integers and/or floats, in the order of [min_lon, max_lon, min_lat, max_lat].
figsize
:tuple
- The matplotlib figure size to use when plotting. For example
figsize=(14,4)
. rayleighs
:bool
- Set to
True
if the data being plotted is in Rayleighs. Defaults toFalse
. max_rayleighs
:int
- Max intensity scale for Rayleighs. Defaults to
20000
. title
:str
- The title to display above the plotted mosaic. Default is no title.
ocean_color
:str
- Colour of the ocean. Default is cartopy's default shade of blue. Colours can be supplied
as a word, or hexcode prefixed with a '#' character (ie.
#55AADD
). land_color
:str
- Colour of the land. Default is
gray
. Colours can be supplied as a word, or hexcode prefixed with a '#' character (ie.#41BB87
). land_edgecolor
:str
- Color of the land edges. Default is
#8A8A8A
. Colours can be supplied as a word, or hexcode prefixed with a '#' character. borders_color
:str
- Color of the country borders. Default is
AEAEAE
. Colours can be supplied as a word, or hexcode prefixed with a '#' character. borders_disable
:bool
- Disbale rendering of the borders. Default is
False
. cbar_title
:str
- Title for the colorbar. Default is no title.
colorbar_title
:str
- Deprecated as of v1.10.0. Use 'cbar_title' instead in the exact same way.
cbar_colormap
:str
-
The matplotlib colormap to use for the plotted color bar. Default is
gray
, unless mosaic was created with spectrograph data, in which case defaults to the colormap used for spectrograph data..Commonly used colormaps are:
- REGO:
gist_heat
- THEMIS ASI:
gray
- TREx Blue:
Blues_r
- TREx NIR:
gray
- TREx RGB:
None
A list of all available colormaps can be found on the matplotlib documentation.
- REGO:
returnfig
:bool
-
Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default.
Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing
plt.close(fig)
.Note that this method cannot be used in combination with
savefig
. savefig
:bool
- Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if
this parameter is set to True. Defaults to
False
. savefig_filename
:str
- Filename to save the image to. Must be specified if the savefig parameter is set to True.
savefig_quality
:int
- Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%.
Returns
The displayed montage, by default. If
savefig
is set to True, nothing will be returned. Ifreturnfig
is set to True, the plotting variables(fig, ax)
will be returned. Raises: def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings if isinstance(self.polygon_data, list): polycollection_str = "[PolyCollection(...), ...]" else: polycollection_str = "PolyCollection(...)" cartopy_projection_str = "Projection(%s)" % (self.cartopy_projection.to_string()) if self.contour_data is not None: contour_data_str = "%d Contours" % (len(self.contour_data.get("x", [])), ) else: contour_data_str = "None" # print print("Mosaic:") print(" %-23s: %s" % ("polygon_data", polycollection_str)) print(" %-23s: %s" % ("cartopy_projection", cartopy_projection_str)) print(" %-23s: %s" % ("contour_data", contour_data_str)) print(" %-23s: %s" % ("spect_cmap", self.spect_cmap)) print(" %-23s: %s" % ("spect_intensity_scale", self.spect_intensity_scale))
A special print output for this class.
class MosaicData (site_uid_list: List[str],
timestamps: List[datetime.datetime],
images: Dict[str, numpy.ndarray],
images_dimensions: Dict[str, Tuple],
data_types: List[str])-
Expand source code
@dataclass class MosaicData: """ Prepared image data for use by mosaic routines. Attributes: site_uid_list (List[str]): List of site unique identifiers contained within this object. timestamps (List[datetime.datetime]): Timestamps of corresponding images. images (Dict[str, numpy.ndarray]): Image data prepared into the necessary format; a dictionary. Keys are the site UID, ndarray is the prepared data. images_dimensions (Dict[str, Tuple]): The image dimensions. data_types (List[str]): The data types for each data object. """ site_uid_list: List[str] timestamps: List[datetime.datetime] images: Dict[str, ndarray] images_dimensions: Dict[str, Tuple] data_types: List[str] def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: # set special strings unique_dimensions_str = str(list(dict.fromkeys(self.images_dimensions.values()))).replace("[", "").replace("]", "").replace("), (", "),(") images_str = "Dict[%d sites of array(dims=%s)]" % (len(self.images.keys()), unique_dimensions_str) timestamps_str = "[%d timestamps]" % (len(self.timestamps)) # return return "MosaicData(images=%s, timestamps=%s, site_uid_list=%s)" % (images_str, timestamps_str, self.site_uid_list.__repr__()) def pretty_print(self): """ A special print output for this class. """ # set special strings unique_dimensions_str = str(list(dict.fromkeys(self.images_dimensions.values()))).replace("[", "").replace("]", "").replace("), (", "),(") images_str = "Dict[%d sites of array(dims=%s)]" % (len(self.images.keys()), unique_dimensions_str) timestamps_str = "[%d timestamps]" % (len(self.timestamps)) # print print("MosaicData:") print(" %-19s: %s" % ("site_uid_list", self.site_uid_list)) print(" %-19s: %s" % ("timestamps", timestamps_str)) print(" %-19s: %s" % ("images", images_str)) print(" %-19s: %s" % ("images_dimensions", self.images_dimensions)) print(" %-19s: %s" % ("data_types", self.data_types))
Prepared image data for use by mosaic routines.
Attributes
site_uid_list
:List[str]
- List of site unique identifiers contained within this object.
timestamps
:List[datetime.datetime]
- Timestamps of corresponding images.
images
:Dict[str, numpy.ndarray]
- Image data prepared into the necessary format; a dictionary. Keys are the site UID, ndarray is the prepared data.
images_dimensions
:Dict[str, Tuple]
- The image dimensions.
data_types
:List[str]
- The data types for each data object.
Class variables
var data_types : List[str]
var images : Dict[str, numpy.ndarray]
var images_dimensions : Dict[str, Tuple]
var site_uid_list : List[str]
var timestamps : List[datetime.datetime]
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings unique_dimensions_str = str(list(dict.fromkeys(self.images_dimensions.values()))).replace("[", "").replace("]", "").replace("), (", "),(") images_str = "Dict[%d sites of array(dims=%s)]" % (len(self.images.keys()), unique_dimensions_str) timestamps_str = "[%d timestamps]" % (len(self.timestamps)) # print print("MosaicData:") print(" %-19s: %s" % ("site_uid_list", self.site_uid_list)) print(" %-19s: %s" % ("timestamps", timestamps_str)) print(" %-19s: %s" % ("images", images_str)) print(" %-19s: %s" % ("images_dimensions", self.images_dimensions)) print(" %-19s: %s" % ("data_types", self.data_types))
A special print output for this class.
class MosaicSkymap (site_uid_list: List[str],
elevation: List[numpy.ndarray],
polyfill_lat: List[numpy.ndarray],
polyfill_lon: List[numpy.ndarray])-
Expand source code
@dataclass class MosaicSkymap: """ Prepared skymap data for use by mosaic routines. Attributes: site_uid_list (List[str]): List of site unique identifiers contained within this object. elevation (List[numpy.ndarray]): List of elevation data, with each element corresponding to each site. Order matches that of the `site_uid_list` attribute. polyfill_lat (List[numpy.ndarray]): List of latitude polygon data, with each element corresponding to each site. Order matches that of the `site_uid_list` attribute. polyfill_lon (List[numpy.ndarray]): List of longitude polygon data, with each element corresponding to each site. Order matches that of the `site_uid_list` attribute. """ site_uid_list: List[str] elevation: List[ndarray] polyfill_lat: List[ndarray] polyfill_lon: List[ndarray] def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: # set special strings unique_polyfill_lat_dims = str(list(dict.fromkeys(fill_arr.shape for fill_arr in self.polyfill_lat))).replace("[", "").replace("]", "").replace("), (", "),(") unique_polyfill_lon_dims = str(list(dict.fromkeys(fill_arr.shape for fill_arr in self.polyfill_lon))).replace("[", "").replace("]", "").replace("), (", "),(") unique_elevation_dims = str(list(dict.fromkeys(el.shape for el in self.elevation))).replace("[", "").replace("]", "").replace("), (", "),(") polyfill_lat_str = "array(dims=%s, dtype=%s)" % (unique_polyfill_lat_dims, self.polyfill_lat[0].dtype) polyfill_lon_str = "array(dims=%s, dtype=%s)" % (unique_polyfill_lon_dims, self.polyfill_lon[0].dtype) elevation_str = "array(dims=%s, dtype=%s)" % (unique_elevation_dims, self.elevation[0].dtype) # return return "MosaicSkymap(polyfill_lat=%s, polyfill_lon=%s, elevation=%s, site_uid_list=%s)" % ( polyfill_lat_str, polyfill_lon_str, elevation_str, self.site_uid_list.__repr__(), ) def pretty_print(self): """ A special print output for this class. """ unique_polyfill_lat_dims = str(list(dict.fromkeys(fill_arr.shape for fill_arr in self.polyfill_lat))).replace("[", "").replace("]", "").replace("), (", "),(") unique_polyfill_lon_dims = str(list(dict.fromkeys(fill_arr.shape for fill_arr in self.polyfill_lon))).replace("[", "").replace("]", "").replace("), (", "),(") unique_elevation_dims = str(list(dict.fromkeys(el.shape for el in self.elevation))).replace("[", "").replace("]", "").replace("), (", "),(") polyfill_lat_str = "array(dims=%s, dtype=%s)" % (unique_polyfill_lat_dims, self.polyfill_lat[0].dtype) polyfill_lon_str = "array(dims=%s, dtype=%s)" % (unique_polyfill_lon_dims, self.polyfill_lon[0].dtype) elevation_str = "array(dims=%s, dtype=%s)" % (unique_elevation_dims, self.elevation[0].dtype) # print print("MosaicSkymap:") print(" %-15s: %s" % ("polyfill_lat", polyfill_lat_str)) print(" %-15s: %s" % ("polyfill_lon", polyfill_lon_str)) print(" %-15s: %s" % ("elevation", elevation_str)) print(" %-15s: %s" % ("site_uid_list", self.site_uid_list))
Prepared skymap data for use by mosaic routines.
Attributes
site_uid_list
:List[str]
- List of site unique identifiers contained within this object.
elevation
:List[numpy.ndarray]
- List of elevation data, with each element corresponding to each site. Order
matches that of the
site_uid_list
attribute. polyfill_lat
:List[numpy.ndarray]
- List of latitude polygon data, with each element corresponding to each site.
Order matches that of the
site_uid_list
attribute. polyfill_lon
:List[numpy.ndarray]
- List of longitude polygon data, with each element corresponding to each site.
Order matches that of the
site_uid_list
attribute.
Class variables
var elevation : List[numpy.ndarray]
var polyfill_lat : List[numpy.ndarray]
var polyfill_lon : List[numpy.ndarray]
var site_uid_list : List[str]
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ unique_polyfill_lat_dims = str(list(dict.fromkeys(fill_arr.shape for fill_arr in self.polyfill_lat))).replace("[", "").replace("]", "").replace("), (", "),(") unique_polyfill_lon_dims = str(list(dict.fromkeys(fill_arr.shape for fill_arr in self.polyfill_lon))).replace("[", "").replace("]", "").replace("), (", "),(") unique_elevation_dims = str(list(dict.fromkeys(el.shape for el in self.elevation))).replace("[", "").replace("]", "").replace("), (", "),(") polyfill_lat_str = "array(dims=%s, dtype=%s)" % (unique_polyfill_lat_dims, self.polyfill_lat[0].dtype) polyfill_lon_str = "array(dims=%s, dtype=%s)" % (unique_polyfill_lon_dims, self.polyfill_lon[0].dtype) elevation_str = "array(dims=%s, dtype=%s)" % (unique_elevation_dims, self.elevation[0].dtype) # print print("MosaicSkymap:") print(" %-15s: %s" % ("polyfill_lat", polyfill_lat_str)) print(" %-15s: %s" % ("polyfill_lon", polyfill_lon_str)) print(" %-15s: %s" % ("elevation", elevation_str)) print(" %-15s: %s" % ("site_uid_list", self.site_uid_list))
A special print output for this class.
class ToolsManager (aurorax_obj)
-
Expand source code
class ToolsManager: """ The ToolsManager object is initialized within every PyAuroraX object. It acts as a way to access the submodules and carry over configuration information in the super class. """ def __init__(self, aurorax_obj): self.__aurorax_obj = aurorax_obj # initialize sub-modules self.__bounding_box = BoundingBoxManager(self.__aurorax_obj) self.__calibration = CalibrationManager() self.__ccd_contour = CCDContourManager() self.__grid_files = GridFilesManager(self.__aurorax_obj) self.__keogram = KeogramManager() self.__montage = MontageManager() self.__mosaic = MosaicManager(self.__aurorax_obj) self.__spectra = SpectraManager() # ------------------------------------------ # properties for submodule managers # ------------------------------------------ @property def bounding_box(self): """ Access to the `bounding_box` submodule from within a PyAuroraX object. """ return self.__bounding_box @property def calibration(self): """ Access to the `calibration` submodule from within a PyAuroraX object. """ return self.__calibration @property def ccd_contour(self): """ Access to the `ccd_contour` submodule from within a PyAuroraX object. """ return self.__ccd_contour @property def grid_files(self): """ Access to the `grid_files` submodule from within a PyAuroraX object. """ return self.__grid_files @property def keogram(self): """ Access to the `keogram` submodule from within a PyAuroraX object. """ return self.__keogram @property def montage(self): """ Access to the `montage` submodule from within a PyAuroraX object. """ return self.__montage @property def mosaic(self): """ Access to the `mosaic` submodule from within a PyAuroraX object. """ return self.__mosaic @property def spectra(self): """ Access to the `spectra` submodule from within a PyAuroraX object. """ return self.__spectra # ------------------------------------------ # functions available at this manager level # ------------------------------------------ def display(self, image: np.ndarray, cmap: Optional[str] = None, figsize: Optional[Tuple[int, int]] = None, aspect: Optional[Union[Literal["equal", "auto"], float]] = None, colorbar: bool = False, title: Optional[str] = None, returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Render a visualization of a single image. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: image (numpy.ndarray): The image to display, represented as a numpy array. cmap (str): The matplotlib colormap to use. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). figsize (tuple): The matplotlib figure size to use when displaying, tuple of two integers (ie. `figsize=(14, 4)`) aspect (str or float): The matplotlib imshow aspect ration to use. A common value for this is `auto`. All valid values can be found on the [matplotlib documentation](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html). colorbar (bool): Display a colorbar. Default is `False`. title (str): A title to display above the rendered image. Defaults to no title. returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed image, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: ValueError: issues encountered with supplied parameters. """ return func_display(image, cmap, figsize, aspect, colorbar, title, returnfig, savefig, savefig_filename, savefig_quality) def movie( self, input_filenames: List[str], output_filename: str, n_parallel: int = 1, fps: int = 25, progress_bar_disable: bool = False, ) -> None: """ Generate a movie file from a list of filenames. Note that the codec used is "mp4v". Args: input_filenames (List[str]): Filenames of frames to use for movie generation. No sorting is applied, so it is assumed the list is in the desired order. This parameter is required. output_filename (str): Filename for the created movie file. This parameter is required. n_parallel (int): Number of multiprocessing workers to use. Default is `1`, which does not use multiprocessing. fps (int): Frames per second (FPS) for the movie file. Default is `25`. progress_bar_disable (bool): Toggle the progress bars off. Default is `False`. Raises: IOError: I/O related issue while generating movie """ return func_movie(self.__aurorax_obj, input_filenames, output_filename, n_parallel, fps, progress_bar_disable) def scale_intensity( self, data: np.ndarray, min: Optional[float] = None, max: Optional[float] = None, top: Optional[float] = None, memory_saver: bool = True, ) -> np.ndarray: """ Scale all values of an array that lie in the range min<=x<=max in to the range 0<=x<=high. Args: data (numpy.ndarray): Data array, can be 2, 3, or 4-dimensional. Assumed to be an image, or array of images. Also assumed that the first 2 dimensions are the image's x and y coordinates, and the following dimensions are some combination of the number of images, and/or the colour channel. min (float): Minimum value of array to be considered max (float): Maximum value of array to be considered top (float): Maximum value of the scaled result. If not supplied, the max value of the data array's dtype is used. memory_saver (bool): Utilize less RAM when scaling a set of images. Defaults to `True`. If set to `False` then the scaling routine will be faster, but will utilize significantly more RAM. Returns: A new `numpy.ndarray` that is the same dimensions as the inputted data array, with the scaling applied. Raises: ValueError: issues encountered with supplied min, max, or top value(s) """ return func_scale_intensity(data, min, max, top, memory_saver) def set_theme(self, theme: str) -> None: """ A handy wrapper for setting the matplotlib global theme. Common choices are `light`, `dark`, or `default`. Args: theme (str): Theme name. Common choices are `light`, `dark`, or `default`. If default, then matplotlib theme settings will be fully reset to their defaults. Additional themes can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/style_sheets/style_sheets_reference.html) """ return func_set_theme(theme)
The ToolsManager object is initialized within every PyAuroraX object. It acts as a way to access the submodules and carry over configuration information in the super class.
Instance variables
prop bounding_box
-
Expand source code
@property def bounding_box(self): """ Access to the `bounding_box` submodule from within a PyAuroraX object. """ return self.__bounding_box
Access to the
pyaurorax.tools.bounding_box
submodule from within a PyAuroraX object. prop calibration
-
Expand source code
@property def calibration(self): """ Access to the `calibration` submodule from within a PyAuroraX object. """ return self.__calibration
Access to the
pyaurorax.tools.calibration
submodule from within a PyAuroraX object. prop ccd_contour
-
Expand source code
@property def ccd_contour(self): """ Access to the `ccd_contour` submodule from within a PyAuroraX object. """ return self.__ccd_contour
Access to the
pyaurorax.tools.ccd_contour
submodule from within a PyAuroraX object. prop grid_files
-
Expand source code
@property def grid_files(self): """ Access to the `grid_files` submodule from within a PyAuroraX object. """ return self.__grid_files
Access to the
pyaurorax.tools.grid_files
submodule from within a PyAuroraX object. prop keogram
-
Expand source code
@property def keogram(self): """ Access to the `keogram` submodule from within a PyAuroraX object. """ return self.__keogram
Access to the
pyaurorax.tools.keogram
submodule from within a PyAuroraX object. prop montage
-
Expand source code
@property def montage(self): """ Access to the `montage` submodule from within a PyAuroraX object. """ return self.__montage
Access to the
pyaurorax.tools.montage
submodule from within a PyAuroraX object. prop mosaic
-
Expand source code
@property def mosaic(self): """ Access to the `mosaic` submodule from within a PyAuroraX object. """ return self.__mosaic
Access to the
pyaurorax.tools.mosaic
submodule from within a PyAuroraX object. prop spectra
-
Expand source code
@property def spectra(self): """ Access to the `spectra` submodule from within a PyAuroraX object. """ return self.__spectra
Access to the
pyaurorax.tools.spectra
submodule from within a PyAuroraX object.
Methods
def display(self,
image: numpy.ndarray,
cmap: str | None = None,
figsize: Tuple[int, int] | None = None,
aspect: Literal['equal', 'auto'] | float | None = None,
colorbar: bool = False,
title: str | None = None,
returnfig: bool = False,
savefig: bool = False,
savefig_filename: str | None = None,
savefig_quality: int | None = None) ‑> Any-
Expand source code
def display(self, image: np.ndarray, cmap: Optional[str] = None, figsize: Optional[Tuple[int, int]] = None, aspect: Optional[Union[Literal["equal", "auto"], float]] = None, colorbar: bool = False, title: Optional[str] = None, returnfig: bool = False, savefig: bool = False, savefig_filename: Optional[str] = None, savefig_quality: Optional[int] = None) -> Any: """ Render a visualization of a single image. Either display it (default behaviour), save it to disk (using the `savefig` parameter), or return the matplotlib plot object for further usage (using the `returnfig` parameter). Args: image (numpy.ndarray): The image to display, represented as a numpy array. cmap (str): The matplotlib colormap to use. Commonly used colormaps are: - REGO: `gist_heat` - THEMIS ASI: `gray` - TREx Blue: `Blues_r` - TREx NIR: `gray` - TREx RGB: `None` A list of all available colormaps can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/color/colormap_reference.html). figsize (tuple): The matplotlib figure size to use when displaying, tuple of two integers (ie. `figsize=(14, 4)`) aspect (str or float): The matplotlib imshow aspect ration to use. A common value for this is `auto`. All valid values can be found on the [matplotlib documentation](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html). colorbar (bool): Display a colorbar. Default is `False`. title (str): A title to display above the rendered image. Defaults to no title. returnfig (bool): Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default. Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing `plt.close(fig)`. Note that this method cannot be used in combination with `savefig`. savefig (bool): Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if this parameter is set to True. Defaults to `False`. savefig_filename (str): Filename to save the image to. Must be specified if the savefig parameter is set to True. savefig_quality (int): Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%. Returns: The displayed image, by default. If `savefig` is set to True, nothing will be returned. If `returnfig` is set to True, the plotting variables `(fig, ax)` will be returned. Raises: ValueError: issues encountered with supplied parameters. """ return func_display(image, cmap, figsize, aspect, colorbar, title, returnfig, savefig, savefig_filename, savefig_quality)
Render a visualization of a single image.
Either display it (default behaviour), save it to disk (using the
savefig
parameter), or return the matplotlib plot object for further usage (using thereturnfig
parameter).Args
image
:numpy.ndarray
- The image to display, represented as a numpy array.
cmap
:str
-
The matplotlib colormap to use.
Commonly used colormaps are:
- REGO:
gist_heat
- THEMIS ASI:
gray
- TREx Blue:
Blues_r
- TREx NIR:
gray
- TREx RGB:
None
A list of all available colormaps can be found on the matplotlib documentation.
- REGO:
figsize
:tuple
- The matplotlib figure size to use when displaying, tuple of two integers (ie.
figsize=(14, 4)
) aspect
:str
orfloat
- The matplotlib imshow aspect ration to use. A common value for this is
auto
. All valid values can be found on the matplotlib documentation. colorbar
:bool
- Display a colorbar. Default is
False
. title
:str
- A title to display above the rendered image. Defaults to no title.
returnfig
:bool
-
Instead of displaying the image, return the matplotlib figure object. This allows for further plot manipulation, for example, adding labels or a title in a different location than the default.
Remember - if this parameter is supplied, be sure that you close your plot after finishing work with it. This can be achieved by doing
plt.close(fig)
.Note that this method cannot be used in combination with
savefig
. savefig
:bool
- Save the displayed image to disk instead of displaying it. The parameter savefig_filename is required if
this parameter is set to True. Defaults to
False
. savefig_filename
:str
- Filename to save the image to. Must be specified if the savefig parameter is set to True.
savefig_quality
:int
- Quality level of the saved image. This can be specified if the savefig_filename is a JPG image. If it is a PNG, quality is ignored. Default quality level for JPGs is matplotlib/Pillow's default of 75%.
Returns
The displayed image, by default. If
savefig
is set to True, nothing will be returned. Ifreturnfig
is set to True, the plotting variables(fig, ax)
will be returned.Raises
ValueError
- issues encountered with supplied parameters.
def movie(self,
input_filenames: List[str],
output_filename: str,
n_parallel: int = 1,
fps: int = 25,
progress_bar_disable: bool = False) ‑> None-
Expand source code
def movie( self, input_filenames: List[str], output_filename: str, n_parallel: int = 1, fps: int = 25, progress_bar_disable: bool = False, ) -> None: """ Generate a movie file from a list of filenames. Note that the codec used is "mp4v". Args: input_filenames (List[str]): Filenames of frames to use for movie generation. No sorting is applied, so it is assumed the list is in the desired order. This parameter is required. output_filename (str): Filename for the created movie file. This parameter is required. n_parallel (int): Number of multiprocessing workers to use. Default is `1`, which does not use multiprocessing. fps (int): Frames per second (FPS) for the movie file. Default is `25`. progress_bar_disable (bool): Toggle the progress bars off. Default is `False`. Raises: IOError: I/O related issue while generating movie """ return func_movie(self.__aurorax_obj, input_filenames, output_filename, n_parallel, fps, progress_bar_disable)
Generate a movie file from a list of filenames. Note that the codec used is "mp4v".
Args
input_filenames
:List[str]
- Filenames of frames to use for movie generation. No sorting is applied, so it is assumed the list is in the desired order. This parameter is required.
output_filename
:str
- Filename for the created movie file. This parameter is required.
n_parallel
:int
- Number of multiprocessing workers to use. Default is
1
, which does not use multiprocessing. fps
:int
- Frames per second (FPS) for the movie file. Default is
25
. progress_bar_disable
:bool
- Toggle the progress bars off. Default is
False
.
Raises
IOError
- I/O related issue while generating movie
def scale_intensity(self,
data: numpy.ndarray,
min: float | None = None,
max: float | None = None,
top: float | None = None,
memory_saver: bool = True) ‑> numpy.ndarray-
Expand source code
def scale_intensity( self, data: np.ndarray, min: Optional[float] = None, max: Optional[float] = None, top: Optional[float] = None, memory_saver: bool = True, ) -> np.ndarray: """ Scale all values of an array that lie in the range min<=x<=max in to the range 0<=x<=high. Args: data (numpy.ndarray): Data array, can be 2, 3, or 4-dimensional. Assumed to be an image, or array of images. Also assumed that the first 2 dimensions are the image's x and y coordinates, and the following dimensions are some combination of the number of images, and/or the colour channel. min (float): Minimum value of array to be considered max (float): Maximum value of array to be considered top (float): Maximum value of the scaled result. If not supplied, the max value of the data array's dtype is used. memory_saver (bool): Utilize less RAM when scaling a set of images. Defaults to `True`. If set to `False` then the scaling routine will be faster, but will utilize significantly more RAM. Returns: A new `numpy.ndarray` that is the same dimensions as the inputted data array, with the scaling applied. Raises: ValueError: issues encountered with supplied min, max, or top value(s) """ return func_scale_intensity(data, min, max, top, memory_saver)
Scale all values of an array that lie in the range min<=x<=max in to the range 0<=x<=high.
Args
data
:numpy.ndarray
- Data array, can be 2, 3, or 4-dimensional. Assumed to be an image, or array of images. Also assumed that the first 2 dimensions are the image's x and y coordinates, and the following dimensions are some combination of the number of images, and/or the colour channel.
min
:float
- Minimum value of array to be considered
max
:float
- Maximum value of array to be considered
top
:float
- Maximum value of the scaled result. If not supplied, the max value of the data array's dtype is used.
memory_saver
:bool
- Utilize less RAM when scaling a set of images. Defaults to
True
. If set toFalse
then the scaling routine will be faster, but will utilize significantly more RAM.
Returns
A new
numpy.ndarray
that is the same dimensions as the inputted data array, with the scaling applied.Raises
ValueError
- issues encountered with supplied min, max, or top value(s)
def set_theme(self, theme: str) ‑> None
-
Expand source code
def set_theme(self, theme: str) -> None: """ A handy wrapper for setting the matplotlib global theme. Common choices are `light`, `dark`, or `default`. Args: theme (str): Theme name. Common choices are `light`, `dark`, or `default`. If default, then matplotlib theme settings will be fully reset to their defaults. Additional themes can be found on the [matplotlib documentation](https://matplotlib.org/stable/gallery/style_sheets/style_sheets_reference.html) """ return func_set_theme(theme)
A handy wrapper for setting the matplotlib global theme. Common choices are
light
,dark
, ordefault
.Args
theme
:str
-
Theme name. Common choices are
light
,dark
, ordefault
. If default, then matplotlib theme settings will be fully reset to their defaults.Additional themes can be found on the matplotlib documentation