Source code for galaxychop.plot

# This file is part of
# the galaxy-chop project (https://github.com/vcristiani/galaxy-chop)
# Copyright (c) 2021, Valeria Cristiani
# License: MIT
# Full Text: https://github.com/vcristiani/galaxy-chop/blob/master/LICENSE.txt

# =============================================================================
# DOCS
# =============================================================================

"""Plot helper for the galaxy object."""

# =============================================================================
# IMPORTS
# =============================================================================

from collections import OrderedDict

import attr

import numpy as np

import pandas as pd

import seaborn as sns

from . import models, utils

# =============================================================================
# ACCESSOR
# =============================================================================


[docs]@attr.s(frozen=True, order=False) class GalaxyPlotter: """Make plots of DecisionMatrix.""" _P_KIND_FORBIDEN_METHODS = ("get_df_and_hue", "get_circ_df_and_hue") _galaxy = attr.ib() # INTERNAL ================================================================ def __call__(self, plot_kind="pairplot", **kwargs): """Make plots of the galaxy. Parameters ---------- kind : str The kind of plot to produce: - 'pairplot' : pairplot matrix of any coordinates (default) **kwargs Options to pass to subjacent plotting method. Returns ------- :class:`matplotlib.axes.Axes` or numpy.ndarray of them The ax used by the plot """ if ( plot_kind.startswith("_") or plot_kind in self._P_KIND_FORBIDEN_METHODS ): raise ValueError(f"invalid 'plot_kind' name '{plot_kind}'") method = getattr(self, plot_kind, None) if not callable(method): raise ValueError(f"invalid 'plot_kind' name '{plot_kind}'") return method(**kwargs) # COMMON PLOTS ============================================================
[docs] def get_df_and_hue(self, ptypes, attributes, labels, lmap): """ Dataframe and Hue constructor for plot implementations. Parameters ---------- ptypes : keys of ``ParticleSet class`` parameters. Particle type. attributes : keys of ``ParticleSet class`` parameters. Names of ``ParticleSet class`` parameters. labels : keys of ``ParticleSet class`` parameters. Variable to map plot aspects to different colors. lmap : dicts Name assignment to the label. Returns ------- df : pandas.DataFrame DataFrame of galaxy properties with labels added. hue : keys of ``ParticleSet class`` parameters. Labels of all galaxy particles. """ # if we use the components as laberls we need to extract the labels if isinstance(labels, models.Components): labels = labels.labels attributes = ["x", "y", "z"] if attributes is None else attributes hue = None # by default labels is None # labels: column used to map plot aspects to different colors (hue). # if is a str and it was not in the attributes I have to take it out # of the dataframe. if isinstance(labels, str): hue = labels attributes = np.unique(list(attributes) + [labels]) # put all attributes in a df df = self._galaxy.to_dataframe(ptypes=ptypes, attributes=attributes) # labels can be an np array and must be added as a column to the # dataframe and assign hue to the name of this new column. if hue is None and labels is not None: hue = "Labels" # Hue is not in ParticleSet, so it is useful df.insert(0, hue, labels) # I place it as the first column if hue and lmap is not None: lmap_func = ( (lambda l: lmap.get(l, l)) if isinstance(lmap, dict) else lmap ) df[hue] = df[hue].apply(lmap_func) return df, hue
[docs] def pairplot( self, ptypes=None, attributes=None, labels="ptype", lmap=None, **kwargs ): """ Draw a pairplot of the galaxy properties. By default, this function will create a grid of Axes such that each numeric variable in data will by shared across the y-axes across a single row and the x-axes across a single column. The diagonal plots drow a univariate distribution to show the marginal distribution of the data in each column. This function groups the values of all galaxy particles according to some ``ParticleSet class`` parameter. Parameters ---------- ptypes : keys of ``ParticleSet class`` parameters. Particle type. Default value = None attributes : keys of ``ParticleSet class`` parameters. Names of ``ParticleSet class`` parameters. Default value = None labels : keys of ``ParticleSet class`` parameters. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs : Additional keyword arguments are passed and are documented in ``seaborn.pairplot``. Returns ------- seaborn.axisgrid.PairGrid """ df, hue = self.get_df_and_hue( ptypes=ptypes, attributes=attributes, labels=labels, lmap=lmap, ) kwargs.setdefault("kind", "hist") kwargs.setdefault("diag_kind", "kde") ax = sns.pairplot(data=df, hue=hue, **kwargs) return ax
[docs] def scatter(self, x, y, ptypes=None, labels=None, lmap=None, **kwargs): """Draw a scatter plot of galaxy properties. Shows the relationship between x and y. This function groups the values of all galaxy particles according to some ``ParticleSet class`` parameter. Parameters ---------- x, y : keys of ``ParticleSet class`` parameters. Variables that specify positions on the x and y axes. Default value y = None. ptypes : keys of ``ParticleSet class`` parameters. Particle type. Default value = None labels : keys of ``ParticleSet class`` parameters. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs Additional keyword arguments are passed and are documented in ``seaborn.scatterplot``. Returns ------- matplotlib.axes.Axes """ attributes = [x, y] df, hue = self.get_df_and_hue( ptypes=ptypes, attributes=attributes, labels=labels, lmap=lmap, ) ax = sns.scatterplot(x=x, y=y, data=df, hue=hue, **kwargs) return ax
[docs] def hist(self, x, y=None, ptypes=None, labels=None, lmap=None, **kwargs): """Draw a histogram of galaxy properties. Plot univariate or bivariate histograms to show distributions of datasets. This function groups the values of all galaxy particles according to some ``ParticleSet class`` parameter. Parameters ---------- x, y : keys of ``ParticleSet class`` parameters. Variables that specify positions on the x and y axes. Default value y = None. ptypes : keys of ``ParticleSet class`` parameters. Particle type. Default value = None labels : keys of ``ParticleSet class`` parameters. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs Additional keyword arguments are passed and are documented in ``seaborn.histplot``. Returns ------- matplotlib.axes.Axes """ attributes = [x] if y is None else [x, y] df, hue = self.get_df_and_hue( ptypes=ptypes, attributes=attributes, labels=labels, lmap=lmap, ) ax = sns.histplot(x=x, y=y, data=df, hue=hue, **kwargs) return ax
[docs] def kde(self, x, y=None, ptypes=None, labels=None, lmap=None, **kwargs): """Draw a Kernel Density plot of galaxy properties. Plot univariate or bivariate distributions using kernel density estimation (KDE). This plot represents the galaxy properties using a continuous probability density curve in one or more dimensions. This function groups the values of all galaxy particles according to some ``ParticleSet class`` parameter. Parameters ---------- x, y : keys of ``ParticleSet class`` parameters. Variables that specify positions on the x and y axes. Default value y = None. ptypes : keys of ``ParticleSet class`` parameters. Particle type. Default value = None labels : keys of ``ParticleSet class`` parameters. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs Additional keyword arguments are passed and are documented in ``seaborn.kdeplot``. Returns ------- matplotlib.axes.Axes """ attributes = [x] if y is None else [x, y] df, hue = self.get_df_and_hue( ptypes=ptypes, attributes=attributes, labels=labels, lmap=lmap, ) ax = sns.kdeplot(x=x, y=y, data=df, hue=hue, **kwargs) return ax
# CICULARITY ==============================================================
[docs] def get_circ_df_and_hue(self, cbins, attributes, labels, lmap): """ Dataframe and Hue constructor for plot implementations. Parameters ---------- cbins : tuple It contains the two widths of bins necessary for the calculation of the circular angular momentum. Shape: (2,). Dafult value = (0.05, 0.005). attributes : keys of ``JCirc`` tuple. Keys of the normalized specific energy, the circularity parameter (J_z/J_circ) and/or the projected circularity parameter (J_p/J_circ) of the stellar particles. labels : keys of ``JCirc`` tuple. Variable to map plot aspects to different colors. lmap : dicts Name assignment to the label. Returns ------- df : pandas.DataFrame DataFrame of the normalized specific energy, the circularity parameter (J_z/J_circ) and/or the projected circularity parameter (J_p/J_circ) of the stellar particles with labels added. hue : keys of ``JCirc`` tuple. Labels of stellar particles. """ # if we use the components as laberls we need to extract the labels if isinstance(labels, models.Components): labels = labels.labels # first we extract the circularity parameters from the galaxy # as a dictionary circ = utils.jcirc(self._galaxy, *cbins) mask = circ.isfinite() circ_dict = circ.as_dict() # determine the correct number of attributes attributes = ( list(circ_dict.keys()) if attributes is None else attributes ) hue = None # labels: column used to map plot aspects to different colors (hue). # if is a str and it was not in the attributes but we can retrieve from # circ, we add as an attribute if isinstance(labels, str): hue = labels attributes = np.unique(list(attributes) + [labels]) columns = OrderedDict() for aname in attributes: columns[aname] = circ_dict[aname][mask] df = pd.DataFrame(columns) # here we create the dataframe # At this point if "hue" is still "None" we can assume: # is an array simply paste it into the dataframe. if hue is None and labels is not None: # if the labels are passed to me as an array, # I only delete the nans and inf. labels = np.asarray(labels) labels = labels[np.isfinite(labels)] hue = "Labels" # I place it as the first column df.insert(0, hue, labels) if hue and lmap is not None: lmap_func = ( (lambda l: lmap.get(l, l)) if isinstance(lmap, dict) else lmap ) df[hue] = df[hue].apply(lmap_func) return df, hue
[docs] def circ_pairplot( self, cbins=utils.DEFAULT_CBIN, attributes=None, labels=None, lmap=None, **kwargs, ): """ Draw a pairplot of circularity and normalized energy. By default, this function will create a grid of Axes such that each numeric variable in data will by shared across the y-axes across a single row and the x-axes across a single column. The diagonal plots drow a univariate distribution to show the marginal distribution of the data in each column. This function groups the values of stellar particles according to some keys of ``JCirc`` tuple. Parameters ---------- cbins : tuple It contains the two widths of bins necessary for the calculation of the circular angular momentum. Shape: (2,). Dafult value = (0.05, 0.005). attributes : keys of ``ParticleSet class`` parameters. Names of ``ParticleSet class`` parameters. Default value = None labels : keys of ``JCirc`` tuple. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs : Additional keyword arguments are passed and are documented in ``seaborn.pairplot``. Returns ------- seaborn.axisgrid.PairGrid """ df, hue = self.get_circ_df_and_hue( cbins=cbins, attributes=attributes, labels=labels, lmap=lmap ) kwargs.setdefault("kind", "hist") kwargs.setdefault("diag_kind", "kde") ax = sns.pairplot(data=df, hue=hue, **kwargs) return ax
[docs] def circ_scatter( self, x, y, cbins=utils.DEFAULT_CBIN, labels=None, lmap=None, **kwargs, ): """Draw a scatter plot of circularity and normalized energy. Shows the relationship between x and y. This function groups the values of stellar particles according to some keys of ``JCirc`` tuple. Parameters ---------- x, y : keys of ``JCirc`` tuple. Variables that specify positions on the x and y axes. Default value y = None. cbins : tuple It contains the two widths of bins necessary for the calculation of the circular angular momentum. Shape: (2,). Dafult value = (0.05, 0.005). labels : keys of ``JCirc`` tuple. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs Additional keyword arguments are passed and are documented in ``seaborn.scatterplot``. Returns ------- matplotlib.axes.Axes """ attributes = [x, y] df, hue = self.get_circ_df_and_hue( cbins=cbins, attributes=attributes, labels=labels, lmap=lmap, ) ax = sns.scatterplot(x=x, y=y, data=df, hue=hue, **kwargs) return ax
[docs] def circ_hist( self, x, y=None, cbins=utils.DEFAULT_CBIN, labels=None, lmap=None, **kwargs, ): """Draw a histogram of circularity and normalized energy. Plot univariate or bivariate histograms to show distributions of datasets. This function groups the values of stellar particles according to some keys of ``JCirc`` tuple. Parameters ---------- x, y : keys of ``JCirc`` tuple. Variables that specify positions on the x and y axes. Default value y = None. cbins : tuple It contains the two widths of bins necessary for the calculation of the circular angular momentum. Shape: (2,). Dafult value = (0.05, 0.005). labels : keys of ``JCirc`` tuple. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs Additional keyword arguments are passed and are documented in ``seaborn.histplot``. Returns ------- matplotlib.axes.Axes """ attributes = [x] if y is None else [x, y] df, hue = self.get_circ_df_and_hue( cbins=cbins, attributes=attributes, labels=labels, lmap=lmap, ) ax = sns.histplot(x=x, y=y, data=df, hue=hue, **kwargs) return ax
[docs] def circ_kde( self, x, y=None, cbins=utils.DEFAULT_CBIN, labels=None, lmap=None, **kwargs, ): """Draw a Kernel Density plot of circularity and normalized energy. Plot univariate or bivariate distributions using kernel density estimation (KDE). This plot represents normalized specific energy, the circularity parameter (J_z/J_circ) and/or the projected circularity parameter (J_p/J_circ) of the stellar particles using a continuous probability density curve in one or more dimensions. This function groups the values of stellar particles according to some keys of ``JCirc`` tuple. Parameters ---------- x, y : keys of ``JCirc`` tuple. Variables that specify positions on the x and y axes. Default value y = None. cbins : tuple It contains the two widths of bins necessary for the calculation of the circular angular momentum. Shape: (2,). Dafult value = (0.05, 0.005). labels : keys of ``JCirc`` tuple. Variable to map plot aspects to different colors. Default value = None lmap : dicts Name assignment to the label. Default value = None **kwargs Additional keyword arguments are passed and are documented in ``seaborn.kdeplot``. Returns ------- matplotlib.axes.Axes """ attributes = [x] if y is None else [x, y] df, hue = self.get_circ_df_and_hue( cbins=cbins, attributes=attributes, labels=labels, lmap=lmap, ) ax = sns.kdeplot(x=x, y=y, data=df, hue=hue, **kwargs) return ax