from distutils.command.config import config
import numpy as np
from matplotlib import axes
from matplotlib.collections import LineCollection
from matplotlib.colorbar import Colorbar
from matplotlib.figure import Figure
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.colors import LogNorm
from matplotlib.colors import to_rgba
from matplotlib.colors import to_hex
import matplotlib.pyplot as plt
import matplotlib as mpl
import scipy.stats as sp
from matplotlib.pyplot import colorbar
from scipy.interpolate import griddata
from scipy.stats import alpha
ii = np.iinfo(int) # Information on numpy's integer
ii_max = ii.max # The maximum int numerically possible
c: str = "ysqgsdkbn" # Chain used to fill the gaps in the lists during the saving of the Graphique
#: Defaults colors :
C1: str = '#6307ba' #: Violet / Purple
C2: str = '#16b5fa' #: Cyan
C3: str = '#2ad500' #: Vert clair / Light green
C4: str = '#145507' #: vert foncé / Dark green
C5: str = '#ff8e00' #: Orange
C6: str = '#cb0d17' #: Rouge / Red
C7: str = '#5694b2' #: Bleu pastel / Pastel blue
C8: str = '#569a57' #: Vert pastel / Pastel green
C9: str = '#b986b9' #: Lavande
C10: str = '#c6403c' #: Rouge pastel / Pastel red
C11: str = '#d39d5d' #: Beige
C12: str = '#25355d' #: Bleu / Blue
C13: str = '#fcc100' #: Jaune / Yellow
C14: str = '#7ab5fa' #: Bleu ciel / Light blue
C15: str = '#fc2700' #: Orange foncé / Dark orange
C16: str = '#0fc88f' #: Bleu-Vert / Blue-Green
C17: str = '#a8173b' #: Rouge cerise / Red
C18: str = '#1812c4' #: Bleu foncé / Dark blue
C19: str = "#000000" #: Noir / Black
C20: str = "#707070" #: Gris / Grey
Ctrensp: tuple = (0, 0, 0, 0) #: completely transparent color (to use for hiding curves for exemple)
l_colors: list[str] = [C1, C2, C4, C3, C5, C6, C7, C8, C9,
C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20]
[docs]
def linear_color_interpolation(val: np.float64 | float | list[np.float64 | float] | np.ndarray[np.float64 | float],
val_min: np.float64 = - np.inf, val_max: np.float64 = np.inf,
col_min: str | tuple = C1, col_max: str = C2,
) -> str | list[str] | np.ndarray[str]:
"""
Return a color/list of colors which is linearly interpolated between the two extremal colors col_min
and col_max
Parameters
----------
val: np.float64 | float | list[np.float64 | float] | np.ndarray[np.float64 | float],
the value to be interpolated
val_min: np.float64, default = min(val)
the minimal value
val_max: np.float64, default = max(val)
the maximal value
col_min: str | tuple, optional, default=C1=#6307ba (purple)
color associated with the minimal value (in hexadecimal or rgba)
col_max: str | tuple, optional, default=C2=#16b5fa (cyan)
color associated with the maximal value (in hexadecimal or rgba)
Returns
-------
str | list[str] | np.ndarray[str]
the interpolated color(s) in hex
"""
if isinstance(col_min, str):
col_min: tuple = to_rgba(col_min)
if isinstance(col_max, str):
col_max: tuple = to_rgba(col_max)
col_min: np.ndarray = np.array(col_min)
col_max: np.ndarray = np.array(col_max)
if val_min == - np.inf:
val_min = np.min(val)
if val_max == np.inf:
val_max = np.max(val)
if val_min == val_max:
raise UserWarning('Graphique.linear_color_interpolation: val_min == val_max, its impossible to build an interpolation wetween two differents colors')
if (isinstance(val, np.float64) or isinstance(val, float)
or isinstance(val, np.int64) or isinstance(val, int)):
return to_hex(tuple(col_min + (col_max - col_min) * (val - val_min) / (val_max - val_min)))
else:
res: list[str] = []
for v in val:
res.append(to_hex(tuple(np.minimum(np.double(1.),
np.maximum(np.double(0.), col_min + (col_max - col_min)
* (v - val_min) / (val_max - val_min))))))
if isinstance(val, np.ndarray):
return np.array(res)
elif isinstance(val, list):
return res
else:
raise UserWarning("The values to be interpolated has the wrong type :", type(val),
"the only accepted types are float, np.float64, list[np.float64| float], np.ndarray")
[docs]
def test_list_regular(x: list) -> list | None:
"""
If x is a list of lists, this function test if there size is equals.
If there are, then it returns a list of string of the same dimensions of x.
Then x could be turned into a ndarray and turned back after
Parameters
----------
x: list
the list to be tested
Returns
-------
the type list or None
"""
res: list = []
dim: int = -1 # size of the sub list (-1 for scalars or strings)
if len(x) == 0:
return []
elif isinstance(x[0], list | np.ndarray):
dim = len(x[0])
for X in x:
if isinstance(X, str | float | int) and dim > -1:
return None
elif isinstance(X, list | np.ndarray) and len(X) != dim:
return None
if isinstance(X, str):
res.append("str")
elif isinstance(X, np.float64):
res.append("double")
elif isinstance(X, float):
res.append("float")
elif isinstance(X, np.int64):
res.append("int64")
elif isinstance(X, int):
res.append("int")
elif isinstance(X, tuple):
res.append("tuple")
elif isinstance(X, np.ndarray):
res.append("array")
elif isinstance(X, list):
types: list | None = test_list_regular(X)
if types is None:
return None
else:
res.append(types)
elif isinstance(X, dict):
return None
elif isinstance(X, Graphique):
return None
else:
raise UserWarning("test_list_regular : the type ", type(X), "cannot be saved")
return res
[docs]
def get_regular_list(x: np.ndarray | list, types: np.ndarray) -> list:
"""
Recover the original list converted by test_list_regular (if the list is regular (the result is not None))
Parameters
----------
x: np.ndarray | list
The converted array
types: np.ndarray
The types of each list's element (result of 'test_list_regular')
Returns
-------
dict
the original list
"""
res: list = []
for (X, T) in zip(x, types):
if isinstance(X, list) or isinstance(X, np.ndarray) and not isinstance(T, str):
res.append(get_regular_list(X, T))
elif isinstance(X, np.ndarray) and len(X) == 0:
res.append([])
elif T == "str":
res.append(str(X))
elif T == "double":
res.append(np.double(X))
elif T == "float":
res.append(float(X))
elif T == "int":
res.append(int(X))
elif T == "int64":
res.append(np.int64(X))
elif T == "tuple":
res.append(tuple(X))
elif T == "array":
res.append(X)
else:
raise UserWarning("get_regular_list : the type ", T, "cannot be loaded")
return res
[docs]
def list_to_dict(x: list, separator: str = "-.-") -> dict:
"""
Parameters
----------
x: list
the list to be converted
separator: str, optinal, default="-.-"
The string to be added between dictionary's keys if there are recursives
Returns
-------
dict
the dictionary containing the list
"""
res: dict = dict()
types: list[list[str]] = []
for i in range(len(x)):
if isinstance(x[i], str):
res[str(i)] = x[i]
types.append([str(i), "str"])
elif isinstance(x[i], np.float64):
res[str(i)] = x[i]
types.append([str(i), "double"])
elif isinstance(x[i], float):
res[str(i)] = x[i]
types.append([str(i), "float"])
elif isinstance(x[i], np.int64):
res[str(i)] = x[i]
types.append([str(i), "int64"])
elif isinstance(x[i], int):
res[str(i)] = x[i]
types.append([str(i), "int"])
elif isinstance(x[i], tuple):
res[str(i)] = x[i]
types.append([str(i), tuple])
elif isinstance(x[i], np.ndarray):
res[str(i)] = x[i]
types.append([str(i), "array"])
elif isinstance(x[i], list):
loc_types: list | None = test_list_regular(x[i])
if loc_types is not None:
res[str(i)] = np.array(x[i])
types.append([str(i), "list_regular"])
res[str(i) + separator + "types"] = np.array(loc_types)
types.append([str(i) + separator + "types", "types"])
else:
loc_dic: dict = list_to_dict(x[i], separator=separator)
types.append([str(i), "list_irregular"])
res[str(i)] = str(i)
for lk in loc_dic.keys():
res[str(i) + separator + lk] = loc_dic[lk]
types.append([str(i) + separator + lk, "list_irregular_values"])
elif isinstance(x[i], dict):
loc_dic: dict = dict_to_ndarray_dict(x[i], separator=separator)
types.append([str(i), "dict"])
res[str(i)] = str(i)
for lk in loc_dic.keys():
res[str(i) + separator + lk] = loc_dic[lk]
types.append([str(i) + separator + lk, "dict_values"])
elif isinstance(x[i], Graphique):
loc_dic: dict = dict_to_ndarray_dict(x[i].to_dict(), separator=separator)
types.append([str(i), "Graphique"])
res[str(i)] = str(i)
for lk in loc_dic.keys():
res[str(i) + separator + lk] = loc_dic[lk]
types.append([str(i) + separator + lk, "Graphique_values"])
else:
raise UserWarning("list_to_dict : the type ", type(x[i]), "cannot be saved")
res["types"] = types
res["separator"] = separator
return res
[docs]
def dict_to_ndarray_dict(dic: dict, separator: str = "-.-") -> dict:
"""
Turn a dictionary containing list, ndarray, str, float, int or even others dic into a dic in the
right form to be saved by np.save_compressed
Parameters
----------
dic: dict
The dictionary to be transformed
separator: str, optional, default="-.-"
The string to be added between dictionary's keys if there are recursives
Returns
-------
dict
The new dictionary
"""
res: dict = dict()
types: list[[str, str]] = []
keys: list[str] = []
for k in dic.keys():
if "k" == "types":
raise UserWarning("""dict_to_ndarray_dict : the key "types" cannot be saved,
please replace it with another one""")
if isinstance(dic[k], str):
res[k] = dic[k]
types.append([k, "str"])
keys.append(k)
elif isinstance(dic[k], np.int64):
res[k] = dic[k]
types.append([k, "int64"])
keys.append(k)
elif isinstance(dic[k], int):
res[k] = dic[k]
types.append([k, "int"])
keys.append(k)
elif isinstance(dic[k], np.float64):
res[k] = dic[k]
types.append([k, "double"])
keys.append(k)
elif isinstance(dic[k], float):
res[k] = dic[k]
types.append([k, "float"])
keys.append(k)
elif isinstance(dic[k], tuple):
res[k] = dic[k]
types.append([k, "tuple"])
keys.append(k)
elif isinstance(dic[k], np.ndarray):
res[k] = dic[k]
types.append([k, "array"])
keys.append(k)
elif isinstance(dic[k], list):
loc_types: list | None = test_list_regular(dic[k])
if loc_types is not None:
res[k] = np.array(dic[k])
types.append([k, "list_regular"])
res[k + separator + "types"] = np.array(loc_types)
types.append([k + separator + "types", "types"])
else:
loc_dic: dict = list_to_dict(dic[k], separator=separator)
types.append([k, "list_irregular"])
res[k] = k
for lk in loc_dic.keys():
res[k + separator + lk] = loc_dic[lk]
types.append([k + separator + lk, "list_irregular_values"])
elif isinstance(dic[k], dict):
loc_dic: dict = dict_to_ndarray_dict(dic[k], separator=separator)
types.append([k, "dict"])
res[k] = k
for lk in loc_dic.keys():
res[k + separator + lk] = loc_dic[lk]
types.append([k + separator + lk, "dict_values"])
elif isinstance(dic[k], Graphique):
loc_dic: dict = dict_to_ndarray_dict(dic[k].to_dict(), separator=separator)
types.append([k, "Graphique"])
res[k] = k
for lk in loc_dic.keys():
res[k + separator + lk] = loc_dic[lk]
types.append([k + separator + lk, "Graphique_values"])
else:
raise UserWarning("dict_to_ndarray_dic : the type ", type(dic[k]), "cannot be saved")
res["types"] = types
res["separator"] = separator
return res
[docs]
def dict_to_list(dic: dict) -> list:
"""
Return the irregular list (A list with list of differents sizes or with dictionary(s))
transformed by the list_to_dict function
Parameters
----------
dic: dict
The dic to be converted
Returns
-------
list
The original list
"""
if "separator" not in dic.keys():
raise UserWarning("dic_to_list, the given dictionary doesn't contain the required separator key."
"Either this dict is not the result of list_to_dict either it has been modified")
separator: str = str(dic["separator"])
del dic["separator"]
types = dic["types"]
del dic["types"]
num_keys: list = []
num_keys_int: list = []
keys: list[str] = list(dic.keys())
keys.sort()
for k in keys:
if separator in k:
num_keys_int.append(int(k[:k.find(separator)]))
num_keys.append(np.double(k[:k.find(separator)])
+ np.double(num_keys_int.count(int(k[:k.find(separator)])) - 1) * 1e-6)
else:
num_keys_int.append(int(k))
num_keys.append(np.double(k)
+ np.double(num_keys_int.count(int(k)) - 1) * 1e-6)
keys: np.ndarray[str] = np.array(list(dic.keys()))
keys = keys[np.argsort(num_keys)]
res: list = []
i: int = 0
# while i < len(keys):
# k: str = keys[i]
# if k == "types" or k == "separator":
# i += 1
# else: # this is an original element of the list
while i < len(keys):
# k = str(ky)
# print("key : ", k)
k: str = keys[i]
type_i = types[np.argwhere(types[:, 0] == k)[0, 0]][1]
if type_i == "str":
res.append(str(dic[k]))
i += 1
elif type_i == "double":
res.append(np.double(dic[k]))
i += 1
elif type_i == "float":
res.append(float(dic[k]))
i += 1
elif type_i == "int64":
res.append(np.int64(dic[k]))
i += 1
elif type_i == "int":
res.append(int(dic[k]))
i += 1
elif type_i == "tuple":
res.append(tuple(dic[k]))
i += 1
elif type_i == "array":
res.append(np.array(dic[k]))
i += 1
elif type_i == "list_regular":
res.append(get_regular_list(dic[k], dic[k + separator + "types"]))
i += 2
elif type_i == "list_irregular":
loc_dic: dict = dict()
i += 1
while i < len(keys) and k + separator in keys[i]:
loc_dic[keys[i][len(k) + len(separator):]] = dic[keys[i]]
i += 1
res.append(dict_to_list(loc_dic))
elif type_i == "dict":
loc_dic: dict = dict()
i += 1
while i < len(keys) and k + separator in keys[i]:
loc_dic[keys[i][len(k) + len(separator):]] = dic[keys[i]]
i += 1
res.append(ndarray_dict_to_dict(loc_dic))
elif type_i == "Graphique":
loc_graph: Graphique = Graphique()
loc_dic: dict = dict()
i += 1
while i < len(keys) and k + separator in keys[i]:
loc_dic[keys[i][len(k) + len(separator):]] = dic[keys[i]]
i += 1
loc_graph.load_dict(ndarray_dict_to_dict(loc_dic))
res.append(loc_graph)
else:
raise UserWarning("dict_list : the type ", type_i, "cannot be loaded", k)
return res
[docs]
def ndarray_dict_to_dict(dic: dict) -> dict:
"""
Return the original dictionary get from the dict_to_ndarray_dict
Parameters
----------
dic, dict
the dictionary to be converted
Returns
-------
dict
the original dictionary
"""
if "separator" not in dic.keys():
raise UserWarning("dic_to_list, the given dictionary doesn't contain the required separator key."
"Either this dict is not the result of list_to_dict either it has been modified")
separator: str = str(dic["separator"])
if "types" not in dic.keys():
raise UserWarning("dic_to_list, the given dictionary doesn't contain the required _types key."
"Either this dict is not the result of list_to_dict either it has been modified",
dic.keys())
types: np.ndarray = dic["types"]
keys: list[str] = list(dic.keys())
keys.sort()
res: dict = dict()
i: int = 0
while i < len(keys):
k: str = keys[i]
if k == "types" or k == "separator":
i += 1
else: # this is an original element of the list
if np.any(types[:, 0] == k):
type_i = types[np.argwhere(types[:, 0] == k)[0, 0]][1]
if type_i == "str":
res[k] = str(dic[k])
i += 1
elif type_i == "double":
res[k] = np.double(dic[k])
i += 1
elif type_i == "float":
res[k] = float(dic[k])
i += 1
elif type_i == "int64":
res[k] = np.int64(dic[k])
i += 1
elif type_i == "int":
res[k] = int(dic[k])
i += 1
elif type_i == "tuple":
res[k] = tuple(dic[k])
i += 1
elif type_i == "array":
res[k] = np.array(dic[k])
i += 1
elif type_i == "list_regular":
res[k] = get_regular_list(dic[k], dic[k + separator + "types"])
i += 2
elif type_i == "list_irregular":
loc_dic: dict = dict()
i += 1
while i < len(keys) and k + separator in keys[i]:
loc_dic[keys[i][len(k) + len(separator):]] = dic[keys[i]]
i += 1
res[k] = dict_to_list(loc_dic)
elif type_i == "dict":
loc_dic: dict = dict()
i += 1
while k + separator in keys[i]:
loc_dic[keys[i][len(k) + len(separator):]] = dic[keys[i]]
i += 1
res[k] = ndarray_dict_to_dict(loc_dic)
elif type_i == "Graphique":
loc_graph: Graphique = Graphique()
loc_dic: dict = dict()
i += 1
while k + separator in keys[i]:
loc_dic[keys[i][len(k) + len(separator):]] = dic[keys[i]]
i += 1
loc_graph.load_dict(ndarray_dict_to_dict(loc_dic))
res[k] = loc_graph
else:
raise UserWarning("dict_list : the type ", type_i, "cannot be loaded")
else:
print("Warning : ", k, " is not in the list of types")
i += 1
return res
[docs]
def colored_line(x, y, c, ax, **lc_kwargs):
"""
This function is adapted from https://matplotlib.org/stable/gallery/lines_bars_and_markers/multicolored_line.html
Plot a line with a color specified along the line by a third value.
It does this by creating a collection of line segments. Each line segment is
made up of two straight lines each connecting the current (x, y) point to the
midpoints of the lines connecting the current point with its two neighbors.
This creates a smooth line with no gaps between the line segments.
Parameters
----------
x, y : array-like
The horizontal and vertical coordinates of the data points.
c : array-like
The color values, which should be the same size as x and y.
ax : Axes
Axis object on which to plot the colored line.
lc_kwargs
Any additional arguments to pass to matplotlib.collections.LineCollection
constructor. This should not include the array keyword argument because
that is set to the color argument. If provided, it will be overridden.
Returns
-------
matplotlib.collections.LineCollection
The generated line collection representing the colored line.
"""
# if "array" in lc_kwargs:
# warnings.warn('The provided "array" keyword argument will be overridden')
# Default the capstyle to butt so that the line segments smoothly line up
default_kwargs = {"capstyle": "butt"}
default_kwargs.update(lc_kwargs)
# Compute the midpoints of the line segments. Include the first and last points
# twice so we don't need any special syntax later to handle them.
x = np.asarray(x)
y = np.asarray(y)
x_midpts = np.hstack((x[0], 0.5 * (x[1:] + x[:-1]), x[-1]))
y_midpts = np.hstack((y[0], 0.5 * (y[1:] + y[:-1]), y[-1]))
# Determine the start, middle, and end coordinate pair of each line segment.
# Use the reshape to add an extra dimension so each pair of points is in its
# own list. Then concatenate them to create:
# [
# [(x1_start, y1_start), (x1_mid, y1_mid), (x1_end, y1_end)],
# [(x2_start, y2_start), (x2_mid, y2_mid), (x2_end, y2_end)],
# ...
# ]
coord_start = np.column_stack((x_midpts[:-1], y_midpts[:-1]))[:, np.newaxis, :]
coord_mid = np.column_stack((x, y))[:, np.newaxis, :]
coord_end = np.column_stack((x_midpts[1:], y_midpts[1:]))[:, np.newaxis, :]
segments = np.concatenate((coord_start, coord_mid, coord_end), axis=1)
lc = LineCollection(segments, color=c, **default_kwargs)
# lc.set_array(c) # set the colors of each segment
return ax.add_collection(lc)
# noinspection PyTypeChecker
[docs]
class Graphique:
"""
The purpose of this object is to make it easier to create and manipulate graphs
It contains all the variables required to plot a graph on an axis
It can be used to display the graph, save it as a .png file and save it using a
.npy format in order to avoid having to easily regenerate the graph in a reproducible way.
------------------------Handling procedures----------------------------
To initialise a Graphique :
- For a new Graphique: ```gr=Graphique()```
- To open a Graphique with name ```n``` in directory ```f``` :
(```n``` and ```f``` are two strings, by default ```f``` is the current working directory)
e.g. ```f="../Images/Graphics"``` and ```n="test_graphique"```.
(the ```.npz``` extension is not mandatory) :
- ```gr=Graphique(n)``` if ```n``` is in the current directory
- ```gr=Graphique(n, f)``` otherwise
To save a Graphique :
- Assign a name to the graphic, without using an extension :
```gr.filename = "new_name"```
The default name is graph_without_name. If you want to save several Graphiques in the same folder
it is therefore important to give them a name (not automatically)
- If necessary, assign a directory for saving:
```gr.directory=‘new_directory’``` By default, the location is the current working directory.
- To save the object :
```gr.save()```
- To save the figure :
- Assign an extension if necessary (by default the extension is svg).
Possible extensions are those available via the matplotlib library: ‘png’, ‘pdf’, ‘svg’, etc.
```gr.ext=".new_extension"```
- ```gr.save_figure()```
To show the Graphique :
- ```gr.show()```
To add a line (equivalent to plt.plot) :
- ```gr.line(x, y, **args)```
with x and y the list(s)/ndarray to plot
and ```**args``` are all the ather arguments of plt.plot()
Can be repeated as many times as required
To add a histogram :
- ```gr.histogram(values, weight=[], normalisation=True, statistic=‘sum’, bins=10, range=None, **args)``` :
where
- values is the array, the list of values to classify
- weights is a list giving a possible weight for each value
- normalisation indicates whether the histogram should be normalised
- The other arguments are the same as ```plt.hist()```
Can be repeated as many times as necessary
To add an image :
- ```gr.image(array,x_axis,y_axis,**args)```
where :
- ```array``` represents the image to be displayed
- ```axis_x``` and ```axis_y``` give the graduations of the image axes
- ```**args``` all the other possible arguments for displaying an image
To add contours :
- ```gr.contours(self, contours=np.array([[]]), x_axe=None, y_axe=None, **args)``` :
where
- ```**args``` gives the possible arguments for ```plt.contours()```
- To add level lines to an image complete ```**args```, leaving the other arguments by default
To add a polygon (coloured area delimited by a list of points) :
- ```gr.polygon(ind,alpha0=0.7, facecolor=‘C3’,**args)```
with ```ind``` an array/list of dimension (n,2) where n is the number of points.
```ind[:,0]``` corresponds to the abscissas of the points and
```ind[:1]``` corresponds to the to the ordinates.
Can be repeated as many times as necessary
To display several Graphique in one, use a Multigraph
"""
def __init__(self, filename: str = "", directory: str = "", set_phenigraph_style: bool = True):
if '.npz' in filename:
filename = filename[:-4]
self.filename: str = filename
if filename == "":
self.directory: str = "./"
self.filename: str = "graph_without_name"
self.ext: str = ".png"
self.title: str = ""
self.style: str = 'default' # global style:
# styles available: plt.style.available : 'default' 'Solarize_Light2'
# '_classic_test_patch' '_mpl-gallery' '_mpl-gallery-nogrid'
# 'bmh' 'classic' 'dark_background' 'fast' 'fivethirtyeight' 'ggplot'
# 'grayscale' 'seaborn' 'seaborn-bright' 'seaborn-colorblind' 'seaborn-dark' 'seaborn-dark-palette'
# 'seaborn-darkgrid' 'seaborn-deep' 'seaborn-muted' 'seaborn-notebook' 'seaborn-paper' 'seaborn-pastel'
# 'seaborn-poster' 'seaborn-talk' 'seaborn-ticks' 'seaborn-white' 'seaborn-whitegrid' 'tableau-colorblind10'
self.param_font: dict = {
"font.size": 13} # Contains additional parameters for global font management
self.ax: axes = None # x axis on the bottom, y axis on the left
self.ax_tl: axes = None # x axis on the top, y axis on the left
self.ax_br: axes = None # x axis on the bottom, y axis on the right
self.ax_tr: axes = None # x axis on the top, y axis on the right
self.axes: list[axes] = None
self.param_ax: dict = dict()
self.param_ax_tl: dict = dict()
self.param_ax_br: dict = dict()
self.param_ax_tr: dict = dict()
self.ticks_param_ax: list[dict] = [dict(), dict()] # x axis, y axis
self.ticks_param_ax_tl: list[dict] = [dict(), dict()] # x axis, y axis
self.ticks_param_ax_br: list[dict] = [dict(), dict()] # x axis, y axis
self.ticks_param_ax_tr: list[dict] = [dict(), dict()]# x axis, y axis
self.param_spines_ax: dict = [dict(), dict(), dict(), dict()] # bottom, left, top, right
self.param_spines_ax_tl: dict = [dict(), dict(), dict(), dict()]
self.param_spines_ax_br: dict = [dict(), dict(), dict(), dict()]
self.param_spines_ax_tr: dict = [dict(), dict(), dict(), dict()]
self.colorbar: list[Colorbar] = []
self.cmap: list = []
self.norms: list = []
self.param_colorbar: list[dict] = []
self.ticks_colorbar: list[np.ndarray | list] = []
# Contains additional parameters for the colorbars ex : label="legende"...
# The first one is automatically associated with the image
self.custum_colorbar_colors: list[list] = None
# To bild custums discrete colorbars defind by the colors in thoses list (one list for one colorbar)
self.custum_colorbar_values: list[list] = None
# The values associated with the colors of self.custum_colorbar_colors
self.index_colorbar_image: list[int] = [] # Index of the image's colorbar(s)
self.fig: Figure = None
self.param_fig: dict = dict() # Contains additional parameters for the Figure ex : facecolor="w"...
self.param_enrg_fig: dict = dict(bbox_inches="tight")
# Contains additional parameters to save the Figure ex : dpi=300...
# orders of axis in the lists : ["bl", "tl, "tr", "br"]
# liste of position of x-axis ticks
self.x_axe: list[np.ndarray[float | np.float64]] = [np.array([-np.inf]), np.array([-np.inf]),
np.array([-np.inf]), np.array([-np.inf])]
# List of x-ticks labels if not "empty"
self.labels_x_ticks: list[np.ndarray[str]] = [np.array(["empty"]), np.array(["empty"]),
np.array(["empty"]), np.array(["empty"])]
# liste of position of y-axis ticks
self.y_axe: list[np.ndarray[float | np.float64]] = [np.array([-np.inf]), np.array([-np.inf]),
np.array([-np.inf]), np.array([-np.inf])]
# List of y-ticks labels if not "empty"
self.labels_y_ticks: list[np.ndarray[str]] = [np.array(["empty"]), np.array(["empty"]),
np.array(["empty"]), np.array(["empty"])]
self.lines_x: list[
list[float | np.float64]] = [] # list containing lists of x coordinates to be displayed via plt.plot
self.lines_y: list[
list[float | np.float64]] = [] # list containing lists of y coordinates to be displayed via plt.plot
self.lines_t_x: list[
list[float | np.float64]] = [] # list containing lists of x coordinates to be displayed via plt.text
self.lines_t_y: list[
list[float | np.float64]] = [] # list containing lists of y coordinates to be displayed via plt.text
self.lines_t_s: list[
list[float | np.float64]] = [] # list containing lists of string to be displayed via plt.text
self.err_x: list[list[
float | np.float64]] = [] # list containing lists of errors associated with x coordinates
self.err_y: list[list[
float | np.float64]] = [] # list containing lists of errors associated with y coordinates
self.compt_color: int = -1 # Indicate the index of the last color used in line in the list_colors
# Additianal parameter's dictionarys
self.param_lines: list = [] # for lines
self.param_texts: list = [] # for texts
# Order of line plot (default the order of saving)
self.indexs_plot_lines: list = []
# histogrammes
self.bords_histogramme: list = [] # List of lists of coordinates of the borders of histograms' bars
# liste contenant les valeurs des hauteurs de barres des histogrammes
self.vals_histogramme: list = [] # List of lists of the values of each histograms' bars
self.param_histogrammes: list = [] # Additional parameters dictionary for plt.bar
self.param_legende: dict = dict() # parameters of plt.legende
# Table to plot via plt.pcolor, the limites are x_axe/y
self.array_image: np.ndarray = np.array([[]])
self.x_axe_image: np.ndarray = np.array([]) # list of x-coordinate for the image
self.y_axe_image: np.ndarray = np.array([]) # list of y-coordinate for the image
# Parameters of pcolor colorbar,legend...
self.param_image: dict = dict() # for pcolor
self.array_contours: np.ndarray = np.array([[]])
# table to plot via contour, the limites are x_axe/y switch of half a bin
self.clabels: np.ndarray = np.array([]) # Label to plot for each contours levels
self.clabels_mask: np.ndarray = np.array([]) # Mask or index list of labels to plot for contours
self.param_contours: dict = dict() # parameter of contours : alpha0,label...
self.param_labels_contours: dict = dict(fontsize=15, inline=True)
# Contains additional parameters for the labels of the contours
self.color_label_contours: list[str] = []
self.x_axe_contours: np.ndarray = np.array([]) # liste of x-coordinate for contours
self.y_axe_contours: np.ndarray = np.array([]) # liste of y-coordinate for contours
# lists of levels for contours to plot
self.levels: np.ndarray = np.array([])
# number of levels for contours to plot, ignore if levels != np.array([])
self.nb_contours: int = 10
self.tab_contours_is_image: bool = False # If True, the table used for contour is self.image
self.index_polygons: list = [] # Index of polygone polygons to plot
self.param_polygons: list = [] # Parameters for the polygons plotting
self.grid: bool = False # If True add a background grid via plt.grid()
if filename != "":
self.filename = filename
if directory != "":
self.directory = directory
elif "/" in directory:
i: int = directory.find("/")
while directory.find("/") > 0:
# Cherche la dernière occurrence de "/"
i = directory.find("/")
self.directory = filename[:i]
self.filename = filename[i:]
else:
self.directory = "./"
values_files: np.lib.npyio.NpzFile = np.load(directory + filename + ".npz")
values_to_load: dict = ndarray_dict_to_dict(dict(values_files))
values_files.close()
self.load_dict(values_to_load)
elif set_phenigraph_style:
self.set_style_phenigraph()
[docs]
def load_dict(self, values_to_load: dict) -> None:
"""
Load a Graphique contained in a dictionary
Parameters
----------
values_to_load: dict
The dictionary that contain all the necessery informations to build a Graphique.
Should be produced by another Graphique via Graphique.to_dict()
Returns
-------
None
See Also
--------
Graphique.to_dict()
"""
if "ext" in values_to_load.keys():
self.ext = values_to_load["ext"]
self.ax = None
self.ax_tl = None
self.ax_br = None
self.ax_tr = None
self.axes = None
self.param_ax = dict()
if 'style' in values_to_load.keys():
self.style = values_to_load["style"]
if "param_colorbar" in values_to_load.keys():
self.param_colorbar = values_to_load["param_colorbar"]
if "ticks_colorbar" in values_to_load.keys():
self.ticks_colorbar = values_to_load["ticks_colorbar"]
if "custum_colorbar_colors" in values_to_load.keys():
self.custum_colorbar_colors = values_to_load["custum_colorbar_colors"]
if "custum_colorbar_values" in values_to_load.keys():
self.custum_colorbar_values = values_to_load["custum_colorbar_values"]
if "index_colorbar_image" in values_to_load.keys():
self.index_colorbar_image = values_to_load["index_colorbar_image"]
if "param_labels_contours" in values_to_load.keys():
self.param_labels_contours = values_to_load["param_labels_contours"]
if "color_label_contours" in values_to_load.keys():
self.color_label_contours = values_to_load["color_label_contours"]
if "param_font" in values_to_load.keys():
self.param_font = values_to_load["param_font"]
if "param_ax" in values_to_load.keys():
self.param_ax = values_to_load["param_ax"]
if "param_ax_tl" in values_to_load.keys():
self.param_ax_tl = values_to_load["param_ax_tl"]
if "param_ax_br" in values_to_load.keys():
self.param_ax_br = values_to_load["param_ax_br"]
if "param_ax_tr" in values_to_load.keys():
self.param_ax_tr = values_to_load["param_ax_tr"]
if "ticks_param_ax" in values_to_load.keys():
self.ticks_param_ax = values_to_load["ticks_param_ax"]
if "ticks_param_ax_tl" in values_to_load.keys():
self.ticks_param_ax_tl = values_to_load["ticks_param_ax_tl"]
if "ticks_param_ax_br" in values_to_load.keys():
self.ticks_param_ax_br = values_to_load["ticks_param_ax_br"]
if "ticks_param_ax_tr" in values_to_load.keys():
self.ticks_param_ax_tr = values_to_load["ticks_param_ax_tr"]
if "param_spines_ax" in values_to_load.keys():
self.param_spines_ax = values_to_load["param_spines_ax"]
if "param_spines__ax_tl" in values_to_load.keys():
self.param_spines_ax_tl = values_to_load["param__spines_ax_tl"]
if "param_spines__ax_br" in values_to_load.keys():
self.param_spines_ax_br = values_to_load["param__spines_ax_br"]
if "param_spines_ax_tr" in values_to_load.keys():
self.param_spines_ax_tr = values_to_load["param_spines_ax_tr"]
# self.colorbar = None
if "param_fig" in values_to_load.keys():
self.param_fig = values_to_load["param_fig"]
if "param_enrg_fig" in values_to_load.keys():
self.param_enrg_fig = values_to_load["param_enrg_fig"]
if "x_axe" in values_to_load.keys():
if isinstance(values_to_load["x_axe"][0], int | float | np.float64 | np.int64):
self.x_axe = [np.array(values_to_load["x_axe"]), np.array([-np.inf]),
np.array([-np.inf]), np.array([-np.inf])]
else:
self.x_axe = values_to_load["x_axe"]
if "labels_x_ticks" in values_to_load.keys():
if len(values_to_load["labels_x_ticks"]) == 0:
self.labels_x_ticks = [np.array([]), np.array(["empty"]),
np.array(["empty"]), np.array(["empty"])]
elif isinstance(values_to_load["labels_x_ticks"][0], str):
self.labels_x_ticks = [np.array(values_to_load["labels_x_ticks"]), np.array(["empty"]),
np.array(["empty"]), np.array(["empty"])]
else:
self.labels_x_ticks = values_to_load["labels_x_ticks"]
if "y_axe" in values_to_load.keys():
if isinstance(values_to_load["y_axe"][0], int | float | np.float64 | np.int64):
self.y_axe = np.array([values_to_load["y_axe"], np.array([-np.inf]),
np.array([-np.inf]), np.array([-np.inf])])
else:
self.y_axe = values_to_load["y_axe"]
if "labels_y_ticks" in values_to_load.keys():
if len(values_to_load["labels_y_ticks"]) == 0:
self.labels_y_ticks = [np.array([]), np.array(["empty"]),
np.array(["empty"]), np.array(["empty"])]
elif isinstance(values_to_load["labels_y_ticks"][0], str):
self.labels_y_ticks = np.array([values_to_load["labels_y_ticks"], np.array(["empty"]),
np.array(["empty"]), np.array(["empty"])])
else:
self.labels_y_ticks = values_to_load["labels_y_ticks"]
if "lines_x" in values_to_load.keys():
self.lines_x = values_to_load["lines_x"]
if "lines_y" in values_to_load.keys():
self.lines_y = values_to_load["lines_y"]
if "indexs_plot_lines" in values_to_load.keys():
self.indexs_plot_lines = values_to_load["indexs_plot_lines"]
if "lines_t_x" in values_to_load.keys():
self.lines_t_x = values_to_load["lines_t_x"]
if "lines_t_y" in values_to_load.keys():
self.lines_t_y = values_to_load["lines_t_y"]
if "lines_t_s" in values_to_load.keys():
self.lines_t_s = values_to_load["lines_t_s"]
if "err_x" in values_to_load.keys():
self.err_x = values_to_load["err_x"]
if "err_y" in values_to_load.keys():
self.err_y = values_to_load["err_y"]
if "compt_color" in values_to_load.keys():
self.compt_color = values_to_load["compt_color"]
self.param_lines = []
if "param_lines" in values_to_load.keys():
self.param_lines = values_to_load["param_lines"]
if "param_texts" in values_to_load.keys():
self.param_texts = values_to_load["param_texts"]
if "bords_histogramme" in values_to_load.keys():
self.bords_histogramme = values_to_load["bords_histogramme"]
if "vals_histogramme" in values_to_load.keys():
self.vals_histogramme = values_to_load["vals_histogramme"]
if "param_histogrammes" in values_to_load.keys():
self.param_histogrammes = values_to_load["param_histogrammes"]
if "param_legende" in values_to_load.keys():
self.param_legende = values_to_load["param_legende"]
if "array_image" in values_to_load.keys():
self.array_image = values_to_load["array_image"]
self.param_image = values_to_load["param_image"]
self.x_axe_image = values_to_load["x_axe_image"]
self.y_axe_image = values_to_load["y_axe_image"]
if "contours" in values_to_load.keys():
self.array_contours = values_to_load["contours"]
self.x_axe_contours = values_to_load["x_axe_contours"]
self.y_axe_contours = values_to_load["y_axe_contours"]
if "param_contours" in values_to_load.keys():
self.param_contours = values_to_load["param_contours"]
if "levels" in values_to_load.keys():
self.levels = values_to_load["levels"]
if "clabels" in values_to_load.keys():
self.clabels = values_to_load["clabels"]
if "clabels_mask" in values_to_load.keys():
self.clabels_mask = values_to_load["clabels_mask"]
if "parameters" in values_to_load.keys():
self.title = values_to_load["parameters"][0]
self.nb_contours = int(values_to_load["parameters"][1])
self.tab_contours_is_image = bool(int(values_to_load["parameters"][2]))
self.grid = bool(int(values_to_load["parameters"][3]))
if "index_polygons" in values_to_load.keys():
self.index_polygons = values_to_load["index_polygons"]
self.param_polygons = values_to_load["param_polygons"]
[docs]
def to_dict(self) -> dict:
"""
Build a dictionary containing all the information of this Graphique
to save it with np.saved_compressed
Returns
-------
dict
See Also
--------
Graphique.to_dict()
"""
enrg: dict = dict() # Dictionary containing all the necessary information :
# Used like : np.savez_compressed(name_fichier,**enrg)
enrg["ext"] = self.ext
enrg["style"] = self.style
if len(self.param_colorbar) > 0:
enrg["param_colorbar"] = self.param_colorbar
if len(self.ticks_colorbar) > 0:
enrg["ticks_colorbar"] = self.ticks_colorbar
if self.custum_colorbar_colors is not None:
enrg["custum_colorbar_colors"] = self.custum_colorbar_colors
if self.custum_colorbar_values is not None:
enrg["custum_colorbar_values"] = self.custum_colorbar_values
if len(self.index_colorbar_image) > 0:
enrg["index_colorbar_image"] = self.index_colorbar_image
if len(self.param_labels_contours) > 0:
enrg["param_labels_contours"] = self.param_labels_contours
if len(self.param_font) > 0:
enrg["param_font"] = self.param_font
if len(self.param_ax) > 0:
enrg["param_ax"] = self.param_ax
if len(self.param_ax_tl) > 0:
enrg["param_ax_tl"] = self.param_ax_tl
if len(self.param_ax_br) > 0:
enrg["param_ax_br"] = self.param_ax_br
if len(self.param_ax_tr) > 0:
enrg["param_ax_tr"] = self.param_ax_tr
if len(self.ticks_param_ax[0]) > 0 or len(self.ticks_param_ax[1]) > 0:
enrg["ticks_param_ax"] = self.ticks_param_ax
if len(self.ticks_param_ax_tl[0]) > 0 or len(self.ticks_param_ax_tl[1]) > 0:
enrg["ticks_param_ax_tl"] = self.ticks_param_ax_tl
if len(self.ticks_param_ax_br[0]) > 0 or len(self.ticks_param_ax_br[1]) > 0:
enrg["ticks_param_ax_br"] = self.ticks_param_ax_br
if len(self.ticks_param_ax_tr[0]) > 0 or len(self.ticks_param_ax_tr[1]) > 0:
enrg["ticks_param_ax_tr"] = self.ticks_param_ax_tr
if np.any(np.array([len(d) > 0 for d in self.param_spines_ax])):
enrg["param_spines_ax"] = self.param_spines_ax
if np.any(np.array([len(d) > 0 for d in self.param_spines_ax_tl])):
enrg["param_spines_ax_tl"] = self.param_spines_ax_tl
if np.any(np.array([len(d) > 0 for d in self.param_spines_ax_br])):
enrg["param_spines_ax_br"] = self.param_spines_ax_br
if np.any(np.array([len(d) > 0 for d in self.param_spines_ax])):
enrg["param_spines_ax_tr"] = self.param_spines_ax_tr
if len(self.param_fig) > 0:
enrg["param_fig"] = self.param_fig
if len(self.param_enrg_fig) > 0:
enrg["param_enrg_fig"] = self.param_enrg_fig
if len(self.x_axe) == 0 or np.any([np.any(x_axe > -np.inf) or len(x_axe) == 0 for x_axe in self.x_axe]):
enrg["x_axe"] = self.x_axe
if len(self.labels_x_ticks) == 0 or np.any([np.any(labels_x_ticks != "empty")
for labels_x_ticks in self.labels_x_ticks]):
enrg["labels_x_ticks"] = self.labels_x_ticks
if len(self.y_axe) == 0 or np.any([np.any(y_axe > -np.inf) or len(y_axe) == 0 for y_axe in self.y_axe]):
enrg["y_axe"] = self.y_axe
if len(self.labels_y_ticks) == 0 or np.any([np.any(labels_y_ticks != "empty")
for labels_y_ticks in self.labels_y_ticks]):
enrg["labels_y_ticks"] = self.labels_y_ticks
if len(self.lines_x) > 0:
enrg["lines_x"] = self.lines_x
if len(self.lines_y) > 0:
enrg["lines_y"] = self.lines_y
if len(self.indexs_plot_lines) > 0:
enrg["indexs_plot_lines"] = self.indexs_plot_lines
if len(self.lines_t_x) > 0:
enrg["lines_t_x"] = self.lines_t_x
if len(self.lines_t_y) > 0:
enrg["lines_t_y"] = self.lines_t_y
if len(self.lines_t_s) > 0:
enrg["lines_t_s"] = self.lines_t_s
if len(self.err_x) > 0:
enrg["err_x"] = self.err_x
if len(self.err_y) > 0:
enrg["err_y"] = self.err_y
enrg["compt_color"] = self.compt_color
if len(self.param_lines) > 0:
enrg["param_lines"] = self.param_lines
if len(self.param_texts) > 0:
enrg["param_texts"] = self.param_texts
if len(self.bords_histogramme) > 0:
enrg["bords_histogramme"] = self.bords_histogramme
if len(self.vals_histogramme) > 0:
enrg["vals_histogramme"] = self.vals_histogramme
if len(self.param_histogrammes) > 0:
enrg["param_histogrammes"] = self.param_histogrammes
if len(self.param_legende) > 0:
enrg["param_legende"] = self.param_legende
if len(self.array_image) > 1:
enrg["array_image"] = self.array_image
enrg["x_axe_image"] = self.x_axe_image
enrg["y_axe_image"] = self.y_axe_image
enrg["param_image"] = self.param_image
if len(self.array_contours) > 1:
enrg["array_contours"] = self.array_contours
enrg["x_axe_contours"] = self.x_axe_contours
enrg["y_axe_contours"] = self.y_axe_contours
if len(self.color_label_contours) > 0:
enrg["color_label_contours"] = self.color_label_contours
if len(self.param_contours) > 0:
enrg["param_contours"] = self.param_contours
if len(self.levels) > 0:
enrg["levels"] = self.levels
if len(self.clabels) > 0:
enrg["clabels"] = self.clabels
if len(self.clabels_mask) > 0:
enrg["clabels_mask"] = self.clabels_mask
param = [self.title, str(self.nb_contours), str(
int(self.tab_contours_is_image)), str(int(self.grid))]
enrg["parameters"] = param
if len(self.index_polygons) > 0:
enrg["index_polygons"] = self.index_polygons
enrg["param_polygons"] = self.param_polygons
return enrg
[docs]
def save(self, filename: str = "graph_without_name", directory: str = None) -> None:
"""
Save the Graphique in self.directory (default the current working directory) in npz compressed
format.
Parameters
----------
filename: str, optinal, default="graph_without_name"
The name of the .npz file (default: "graph_without_name")
directory: str, optional, default="./"
Graphique's directory (default self.directory (default : the curent working directory))
Returns
-------
None
"""
if filename != "graph_without_name":
if ".npz" in filename:
self.filename = filename[:-4]
else:
self.filename = filename
if directory is not None:
self.directory = directory
enrg = dict_to_ndarray_dict(self.to_dict(), separator="-.-")
if ".npz" not in self.filename:
if self.directory[-1] == "/":
np.savez_compressed(self.directory +
self.filename + ".npz", **enrg)
else:
np.savez_compressed(self.directory + "/" +
self.filename + ".npz", **enrg)
else:
if self.directory[-1] == "/":
np.savez_compressed(self.directory +
self.filename, **enrg)
else:
np.savez_compressed(self.directory + "/" +
self.filename, **enrg)
[docs]
def customized_cmap(self, values: list[np.float64] | np.ndarray | tuple,
colors: list | np.ndarray | tuple | None = None,
ticks: list | np.ndarray[np.float64] | None = None,
ticks_labels: list | np.ndarray[str] | None = None,
**kwargs) -> None:
"""
Parameters
----------
values : list[np.float64] | np.ndarray | tuple
The values of the colormap's color intervals if len(values)==2, the interval is automatically
defined as a linear subdivision of the interval between values[0] and values[1] of size 255
colors : list | np.ndarray | tuple, optional
The associated colors, if None, a linear variation beteween C1 and C2 is bild
ticks : list | np.ndarray[np.float64], optional
Array of ticks for the colorbar If None, ticks are determined automatically from the input.
ticks_labels : list | np.ndarray[str], optional
Array of labels for the ticks.
kwargs
Additional arguments for the colorbar :
- location: str, {'right', 'top', 'bottom', 'left'}
Indicate where the colorbar should be plotted
- scale: str, {'linear', 'log', 'symlog'}
The scale of the colorbar
- ticks: list | array_like
- format: str
ticks' format
- label: str
The label to plot along the colorbar
- size: float, default=0.01
relative width of the colorbar
- fraction: float, default=1
relative hight of the colorbar
- space_between: float, default=0.01
relative space between colorsbars (and the plot)
Returns
-------
None
Examples
--------
>>> x = np.linspace(0, 10, 1000)
>>> alpha = np.linspace(1, 5, 10)
>>> colors = linear_color_interpolation(np.arange(len(alpha)), col_min=C1, col_max=C2)
>>> gr = Graphique()
>>> gr.logy(x, [x**a for a in alpha], color=colors)
>>> gr.customized_cmap(alpha, colors)
>>> gr.show()
"""
if len(values) < 2:
raise UserWarning("Graphique.custumized_cmap : the len of values need to be higer than 2")
if ticks_labels is not None:
kwargs["ticks_labels"] = ticks_labels
if isinstance(values, tuple) or len(values) == 2:
values = np.linspace(values[0], values[1], 255)
if colors is not None and (isinstance(colors, tuple) or len(colors) == 2):
colors = linear_color_interpolation(values, col_min=colors[0], col_max=colors[1])
elif colors is not None and (isinstance(colors, tuple) or len(colors) == 2):
colors = linear_color_interpolation(values, col_min=colors[0], col_max=colors[1])
if colors is not None and len(colors) != len(values):
raise UserWarning("Graphique.custumized_cmap : values and colors need to have the same size :"
"len(values)=", len(values), " len(colors)=", len(colors))
if colors is None:
colors = linear_color_interpolation(values, col_min=C1, col_max=C2)
if self.custum_colorbar_values is not None:
self.custum_colorbar_values.append(values)
else:
self.custum_colorbar_values = [values]
if self.custum_colorbar_colors is not None:
self.custum_colorbar_colors.append(colors)
else:
self.custum_colorbar_colors = [colors]
if ticks is None:
self.ticks_colorbar.append([])
elif len(ticks) == 0:
self.ticks_colorbar.append([-np.inf])
else:
self.ticks_colorbar.append(ticks)
self.param_colorbar.append(kwargs)
[docs]
def line(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list | np.ndarray[str] = "", share_colorbar: bool | int = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
hide: bool = False, cmap: str = "default", color_min: str | tuple = None, color_max: str | tuple = None,
axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to plt.plot
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, int optional, default=False
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions. If is an integer, the integer refers to the index of a customized cmap
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
cmap : str, optional, default='default'
The colormap style if needed, the default colorbar is a linear variation between color_min and color_max
If there are not provided, the color will be chosen automatically
color_min : str | tuple, optional
The color associated with the minimum value for a `default` cmap
color_max : str | tuple, optional
The color associated with the maximum value for a `default` cmap
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.line(x,[y1,y2], *args)``` is equivalent to
```plt.plot(x, y1, *args)
plt.plot(x, y2, *args)```
- if y1 and y2 have not the same size:
```self.line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.line((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```plt.plot(x, y1, marker=".", label="Curve1")
plt.plot(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.linspace(0, 10, 1000)
>>> alpha = np.linspace(1, 5, 10)
>>> colors = g.linear_color_interpolation(np.arange(len(alpha)), col_min=C1, col_max=C2)
>>> gr = g.Graphique()
>>> gr.line(x, [x*a for a in alpha], color=colors)
>>> gr.customized_cmap(alpha, colors)
>>> gr.show()
"""
if not isinstance(scale_z, str):
raise UserWarning("""Graphique.line : The scale of the z-axis need to be represanted by a string :
'linear", 'log' or 'symlog'""")
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
kwargs["axis_config"] = axis_config
if kwargs_colorbar is None:
kwargs_colorbar = dict()
if not isinstance(kwargs_colorbar, dict):
raise UserWarning("""Graphique.line : The extra arguments ir the colorbar need to be provided thru a
dictionary. Not a """, type(kwargs_colorbar))
if scale_z != "linear" and scale_z != "log" and scale_z != "symlog":
raise UserWarning("""Graphique.line : The scale of the z-axis can only be
"linear", "log" or "symlog". Not """, scale_z)
if isinstance(y, str):
marker = y
y = None
if isinstance(z, str):
marker = z
z = None
if y is None:
if isinstance(x, list) and isinstance(x[0], np.ndarray):
y = [np.copy(X) for X in x]
else:
y = np.copy(x)
x = np.arange(0, len(y))
# if the parameters are array, trying to find the corrects axis order if needed.
# if isinstance(x, np.ndarray) and isinstance(y, np.ndarray) and (z is None or isinstance(z, np.ndarray)):
# if len(x.shape) > 3:
# raise UserWarning("The x dimension cannot be higher than 3 : x.shape=", x.shape)
# if len(y.shape) > 3:
# raise UserWarning("The y dimension cannot be higher than 3 : x.shape=", y.shape)
# if z is not None and len(z.shape) > 3:
# raise UserWarning("The z dimension cannot be higher than 3 : x.shape=", z.shape)
#
# if x.shape[-1] != y.shape[-1]:
# if z is not None and ((len(x.shape) == len(z.shape) and x.shape != z.shape)
# or(len(y.shape) == len(z.shape) and y.shape != z.shape)):
# raise UserWarning("Graphique.line : the shape of z is not compatible with shape of x or y"
# " : x.shape=", x.shape, "y.shape=", y.shape, "z.shape=", z.shape)
# if len(x.shape) == 1 and not np.any(np.array(y.shape) == x.shape[0]):
# raise UserWarning("Graphique.line : x and y shape doesn't match : x.shape=", x.shape,
# "y.shape=", y.shape)
# elif len(x.shape) == 1:
# i = np.argwhere(np.array(y.shape) == x.shape[0])[:, 0]
# if len(i) > 1:
# raise UserWarning("Graphique.line : unable to determine the dimension along which plot the data")
# else:
# i = i[0]
# if z is not None and len(z.shape) == len(y.shape):
# np.moveaxis(z, i, -1)
# elif z is not None and len(z.shape) == 2 and len(y.shape) == 3:
# j = np.argwhere(np.array(z.shape) == x.shape[0])[:, 0]
# if len(j) > 1:
# raise UserWarning(
# "Graphique.line : unable to determine the dimension along which plot the data for z axis")
# else:
# j = j[0]
# np.moveaxis(z, j, -1)
# if isinstance(marker, np.ndarray) and marker.shape == y.shape:
# np.moveaxis(marker, i, -1)
# elif isinstance(marker, np.ndarray) and len(marker.shape) == 2 and len(y.shape) == 3:
# j = np.argwhere(np.array(marker.shape) == x.shape[0])[:, 0]
# if len(j) > 1:
# raise UserWarning(
# "Graphique.line : unable to determine the dimension along which plot the data for markers")
# else:
# j = j[0]
# np.moveaxis(marker, j, -1)
# for k in kwargs.keys():
# if isinstance(kwargs[k], np.ndarray) and kwargs[k].shape == y.shape:
# np.moveaxis(kwargs[k], i, -1)
# elif isinstance(kwargs[k], np.ndarray) and len(kwargs[k].shape) == 2 and len(y.shape) == 3:
# j = np.argwhere(np.array(kwargs[k].shape) == x.shape[0])[:, 0]
# if len(j) > 1:
# raise UserWarning(
# "Graphique.line : unable to determine the dimension along which plot the "
# "data for one of the argument : ", k, kwargs[k].shape)
# else:
# j = j[0]
# np.moveaxis(kwargs[k], j, -1)
# np.moveaxis(x, i, -1)
# np.moveaxis(y, i, -1)
# elif len(x.shape) == 2:
# i = np.argwhere((np.array(y.shape) != x.shape[0]) + (np.array(y.shape) != x.shape[1]))[:, 0]
# if len(i) > 1:
# raise UserWarning("Graphique.line : unable to determine the dimension along wich plot the data")
# else:
# i = i[0]
# if z is not None and z.shape == x.shape:
# np.moveaxis(z, i, 0)
#
# if isinstance(marker, np.ndarray) and marker.shape == y.shape:
# np.moveaxis(marker, i, 0)
# for k in kwargs.keys():
# if isinstance(kwargs[k], np.ndarray) and kwargs[k].shape == y.shape:
# np.moveaxis(kwargs[k], i, 0)
# np.moveaxis(x, i, 0)
# np.moveaxis(y, i, 0)
# else: # len(x.shape) == 3
# if not np.any(np.array(x.shape) == np.array(y.shape)):
# raise UserWarning("Graphique.line : the shape of x and y are not compatible : x.shape=",
# x.shape, "y.shape=", y.shape)
# i = np.argwhere(np.array(x.shape) == np.array(y.shape))[:, 0]
# if len(i) > 1:
# raise UserWarning("Graphique.line : impossible to determine the axis along wich plot the data "
# ": x.shape=", x.shape, "y.shape=", y.shape)
# else:
# i = i[0]
# np.moveaxis(x, i, -1)
# np.moveaxis(y, i, -1)
# for k in kwargs.keys():
# if isinstance(kwargs[k], np.ndarray) and kwargs[k].shape == y.shape:
# np.moveaxis(kwargs[k], i, -1)
# if len(y.shape) == 3:
# for i in range(len(y)):
# if isinstance(marker, np.ndarray) and marker.shape == y.shape:
# mrk = marker[i]
# else:
# mrk = marker
# kwargs_i = kwargs.copy()
# for k in kwargs_i.keys():
# if isinstance(kwargs_i[k], np.ndarray) and kwargs_i[k].shape == y.shape:
# kwargs_i[k] = kwargs_i[k][i]
# if len(x.shape) == 3 and (z is None or len(z.shape) < 3):
# self.line(x=x[i], y=y[i], z=z, marker=mrk, share_colorbar=share_colorbar, scale_z=scale_z,
# kwargs_colorbar=kwargs_colorbar, hide=hide, axis_config=axis_config, **kwargs_i)
if isinstance(x[0], list) | isinstance(x[0], np.ndarray):
if isinstance(x[0][0], list) | isinstance(x[0][0], np.ndarray):
raise UserWarning("Graphique.line the x-axis dimension cannot be superior than 2")
else:
dim_x: int = 2
else:
dim_x: int = 1
if isinstance(y[0], list) | isinstance(y[0], np.ndarray):
if isinstance(y[0][0], list) | isinstance(y[0][0], np.ndarray):
raise UserWarning("Graphique.line the y-axis dimension cannot be superior than 2")
else:
dim_y: int = 2
else:
dim_y: int = 1
if z is not None and isinstance(z[0], list) | isinstance(z[0], np.ndarray):
if isinstance(z[0][0], list) | isinstance(z[0][0], np.ndarray):
raise UserWarning("Graphique.line the z-axis dimension cannot be superior than 2")
else:
dim_z: int = 2
elif z is None:
dim_z: int = 0
else:
dim_z: int = 1
if (dim_x == 2 and dim_y == 2 and
np.any(np.array([len(X) != len(Y) for (X, Y) in zip(x, y)]))):
raise UserWarning("Graphique.line : the sizes of arrays of the abscissa "
"doesn't mach with the sizes of the array of ordinates : ",
[(len(X), len(Y)) for (X, Y) in zip(x, y)])
elif (dim_x == 2 and dim_y == 2 and dim_z == 2 and
np.any(np.array([len(Y) != len(Z) for (Y, Z) in zip(y, z)]))):
raise UserWarning("Graphique.line : the sizes of arrays of the z-axis "
"doesn't mach with the sizes of the array of ordinates : ",
[(len(Y), len(Z)) for (Y, Z) in zip(y, z)])
elif (dim_x == 2 and dim_y == 2 and dim_z == 1 and
(np.any(np.array([len(Y) != len(z) for Y in y]))) and len(y) != len(z)):
raise UserWarning("Graphique.line : the sizes of the z-axis "
"doesn't mach with the sizes of the array of ordinates : ",
[(len(Y), len(Z)) for (Y, Z) in zip(y, z)], (len(y), len(z)))
elif (dim_y == 2 and dim_x == 1 and
np.any(np.array([len(x) != len(Y) for Y in y]))):
raise UserWarning("Graphique.line : the sizes of the abscissa "
"doesn't mach with the sizes of the array of ordinates : ",
[(len(x), len(Y)) for Y in y])
elif (dim_y == 2 and dim_x == 1 and dim_z == 2 and
(np.any(np.array([len(x) != len(Z) for Z in z])) and len(y) != len(z))):
raise UserWarning("Graphique.line : the sizes of the array of z-axis "
"doesn't mach with the sizes of the abscissa : ",
[(len(x), len(Z)) for Z in z], " or the y-axis :", (len(y), len(z)))
elif (dim_y == 2 and dim_x == 1 and dim_z == 1 and
len(x) != len(z) and len(y) != len(z)):
raise UserWarning("Graphique.line : the sizes of thez-axis "
"doesn't mach with the sizes of the abscissa : ",
len(x), len(z), " or the y-axis :", len(y))
elif dim_y == 1 and dim_x == 1 and len(x) != len(y):
raise UserWarning("Graphique.line : the sizes of the abscissa "
"doesn't mach with the sizes of the ordinate : ",
len(x), len(y))
elif dim_y == 1 and dim_x == 1 and dim_z == 2:
raise UserWarning("Graphique.line : There is only one list of ordinate for several's lists"
"of z. This cannot be represented by a colorscale")
elif dim_y == 1 and dim_x == 1 and dim_z == 1 and len(x) != len(z):
raise UserWarning("Graphique.line : the sizes of the abscissa "
"doesn't mach with the sizes of the z-axis : ",
len(x), len(z))
if dim_z < 2 and isinstance(share_colorbar, bool) and share_colorbar:
if self.custum_colorbar_values is None:
raise UserWarning(
"Graphique.line : There is no previous colormap to use to plot the z axis, please set "
"the parameter share_colorbar to False")
share_colorbar = len(self.param_colorbar) - 1
print('Graphique.line : Warning, no colorbar is provide to plot the z axis, the ', share_colorbar,
"is used by default")
if dim_x == 2 and dim_y == 2 and dim_z == 2:
if scale_z == "linear" or scale_z == "symlog":
if isinstance(share_colorbar, bool):
z_min: np.float64 = np.min([np.min(Z) for Z in z])
z_max: np.float64 = np.max([np.max(Z) for Z in z])
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
else:
if isinstance(share_colorbar, bool):
if np.any(np.array([Z > 0 for Z in z])):
z_min: np.float64 = np.inf
z_max: np.float64 = -np.inf
for Z in z:
if np.any(Z > 0):
z_min = min(z_min, np.min(Z[Z>0]))
z_min = max(z_max, np.max(Z[Z>0]))
else:
raise UserWarning(
"Graphique.line : z-axis has no strictly positive values and the scale is log)")
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
if scale_z == "symlog" and np.any(np.array([Z > 0 for Z in z])):
if isinstance(share_colorbar, bool):
z_min_pos: np.float64 = np.inf
for Z in z:
if np.any(Z > 0):
z_min_pos = min(z_min_pos, np.min(Z[Z>0]))
else:
z_min_pos: np.float64 = self.custum_colorbar_values[np.argwhere(self.custum_colorbar_values > 0)[0, 0]]
else:
z_min_pos: np.float64 = max(0., z_min)
if scale_z == "symlog" and z is not None and np.any(np.array([Z < 0 for Z in z])):
if isinstance(share_colorbar, bool):
z_max_neg: np.float64 = -np.inf
for Z in z:
if np.any(Z < 0):
z_max_neg = max(z_max_neg, np.max(Z[Z < 0]))
else:
z_min_neg: np.float64 = self.custum_colorbar_values[
np.argwhere(self.custum_colorbar_values < 0)[-1, 0]]
else:
z_max_neg: np.float64 = min(0., z_max)
if isinstance(share_colorbar, bool) and (color_min is not None or color_max is not None):
share_colorbar = True
for (X, Y, Z, i) in zip(x, y, z, np.arange(len(x))):
if isinstance(share_colorbar, bool):
if scale_z == "linear" or scale_z == "symlog":
z_min: np.float64 = np.min(Z)
z_max: np.float64 = np.max(Z)
else:
if np.any(z > 0):
z_min: np.float64 = np.min(Z[Z > 0])
z_max: np.float64 = np.max(Z)
else:
z_min: np.float64 = np.double(0.)
z_max: np.float64 = np.double(0.)
if scale_z == "symlog" and (Z > 0).sum() > 0:
z_min_pos: np.float64 = np.min(Z[Z > 0])
else:
z_min_pos: np.float64 = 0.
if scale_z == "symlog" and (Z < 0).sum() > 0:
z_max_neg: np.float64 = np.max(Z[Z < 0])
else:
z_max_neg: np.float64 = 0
idx_s: np.ndarray[int] = np.arange(len(Z))
if scale_z == "log" and np.any(Z > 0):
idx_s = np.argwhere(Z > 0)[:, 0]
elif scale_z == "log":
idx_s = np.array([])
if len(idx_s) > 0:
self.lines_x.append(np.array(X[idx_s]))
self.lines_y.append(np.array(Y[idx_s]))
else:
self.lines_x.append(np.array([]))
self.lines_y.append(np.array([]))
self.err_x.append([])
self.err_y.append([])
args_auxi: dict = {}
for k in kwargs.keys():
if (isinstance(kwargs[k], list) | isinstance(kwargs[k], np.ndarray)) and len(kwargs[k]) == len(y):
args_auxi[k] = kwargs[k][i]
else:
args_auxi[k] = kwargs[k]
if marker != "" and not ("linestyle" in args_auxi):
args_auxi["linestyle"] = ""
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
elif marker != "":
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
if scale_z == "linear":
if isinstance(share_colorbar, bool) and share_colorbar:
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max = color_max
elif isinstance(share_colorbar, bool):
c_min: str = l_colors[(self.compt_color + 1 + 2 * i) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 2 + 2 * i) % len(l_colors)]
if isinstance(share_colorbar, bool):
if cmap == "default":
colors: np.ndarray[str] = linear_color_interpolation(Z, val_min=z_min, val_max=z_max,
col_min=c_min,
col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(cmap_auxi(np.minimum(
np.maximum((Z- z_min)/ (z_max - z_min),
0.), 1.)))])
args_auxi["color"] = colors
else:
args_auxi["color"] = linear_color_interpolation(Z, val_min=self.custum_colorbar_values[
share_colorbar].min(),
val_max=self.custum_colorbar_values[
share_colorbar].max(),
col_min=
self.custum_colorbar_colors[share_colorbar][0],
col_max=
self.custum_colorbar_colors[share_colorbar][-1])
if isinstance(share_colorbar, bool) and not share_colorbar:
if cmap == "default":
colors=linear_color_interpolation(np.linspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(np.linspace(0, 1, 255))])
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
elif scale_z == "log" and len(idx_s) > 0:
if isinstance(share_colorbar, bool) and share_colorbar:
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max = color_max
elif isinstance(share_colorbar, bool):
c_min: str = l_colors[(self.compt_color + 1 + 2 * i) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 2 + 2 * i) % len(l_colors)]
if isinstance(share_colorbar, bool):
if cmap == "default":
colors: np.ndarray[str] = linear_color_interpolation(np.log10(Z[idx_s]), val_min=np.log10(z_min),
val_max=np.log10(z_max),
col_min=c_min,
col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(np.minimum(
np.maximum((np.log10(Z[idx_s])
- np.log10(z_min))/ (np.log10(z_max) - np.log10(z_min)),
0.), 1.))])
args_auxi["color"] = colors
else:
args_auxi["color"] = linear_color_interpolation(np.log10(Z[idx_s]),
val_min=self.custum_colorbar_values[
share_colorbar].min(),
val_max=self.custum_colorbar_values[
share_colorbar].max(),
col_min=
self.custum_colorbar_colors[share_colorbar][0],
col_max=
self.custum_colorbar_colors[share_colorbar][-1])
if isinstance(share_colorbar, bool) and not share_colorbar:
if cmap == "default":
colors=linear_color_interpolation(np.linspace(np.log10(z_min), np.log10(z_min), 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(np.linspace(0, 1, 255))])
self.customized_cmap(values=np.linspace(np.log10(z_min), np.log10(z_max), 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
else:
if isinstance(share_colorbar, bool) and share_colorbar:
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min = color_min
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
if color_max is None:
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
else:
c_max = color_max
elif isinstance(share_colorbar, bool):
c_min: str = l_colors[(self.compt_color + 1 + 3 * i) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2 + 3 * i) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3 + 3 * i) % len(l_colors)]
else:
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_min: str = self.custum_colorbar_colors[share_colorbar][
np.argwhere(self.custum_colorbar_values > 0)[0, 0]]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
ma: np.ndarray[bool] = Z > 0.
args_auxi["color"] = np.full(len(X), c_med)
if z_min_pos > 0.:
args_auxi["color"][ma] = linear_color_interpolation(np.log10(Z[ma]),
val_min=np.log10(z_min_pos),
val_max=np.log10(z_max),
col_min=c_med, col_max=c_max)
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
args_auxi["color"][~ma] = linear_color_interpolation(np.log10(-Z[~ma]),
val_min=np.log10(-z_max_neg),
val_max=np.log10(-z_min),
col_min=c_med, col_max=c_min)
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
args_auxi["color"] = colors
if isinstance(share_colorbar, bool) and not share_colorbar:
self.customized_cmap(values=z_colors,
colors=colors, scale=scale_z, **kwargs_colorbar)
if "label" in kwargs and args_auxi["label"] == "":
del args_auxi["label"]
# Delete empty legend to prevent a warning message and the addition of an empty gray square
self.param_lines.append(args_auxi)
if isinstance(share_colorbar, bool) and share_colorbar:
if scale_z == "linear":
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
colors = linear_color_interpolation(np.linspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(np.linspace(0, 1, 255))])
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
elif scale_z == "log":
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
colors = linear_color_interpolation(np.geomspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi((np.geomspace(z_min, z_max, 255) - z_min) / (z_max - z_min))])
self.customized_cmap(values=np.geomspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
else:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
if z_min_pos > 0.:
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
self.customized_cmap(values=z_colors, colors=colors, scale=scale_z, **kwargs_colorbar)
self.compt_color += 3
elif isinstance(share_colorbar, bool) and scale_z == "linear" or scale_z == "log":
self.compt_color += 2 * len(x)
elif isinstance(share_colorbar, bool):
self.compt_color += 3 * len(x)
elif dim_x == 2 and dim_y == 2 and dim_z < 2:
if z is not None:
if z is not None and scale_z == "linear" or scale_z == "symlog":
if isinstance(share_colorbar, bool):
z_min: np.float64 = np.min(z)
z_max: np.float64 = np.max(z)
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max: str = color_max
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
elif z is not None:
if isinstance(share_colorbar, bool):
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
if np.any(z > 0):
z_min: np.float64 = np.min(z[z > 0])
z_max: np.float64 = np.max(z)
else:
raise UserWarning(
"Graphique.line : z-axis has no strictly positive values and the scale is log)")
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar][
self.custum_colorbar_values[share_colorbar] > 0])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_med: str = self.custum_colorbar_colors[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] > 0)[0, 0]]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
else:
z_min: np.float64 = np.double(0.)
z_max: np.float64 = np.double(0.)
if z is not None and scale_z == "symlog" and (
(z > 0).sum() > 0 or not isinstance(share_colorbar, bool)):
if isinstance(share_colorbar, bool):
z_min_pos: np.float64 = np.min(z[z > 0])
else:
z_min_pos: np.float64 = self.custum_colorbar_values[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] > 0)[0, 0]]
else:
z_min_pos: np.float64 = 0.
if z is not None and scale_z == "symlog" and (z < 0).sum() > 0:
if isinstance(share_colorbar, bool):
z_max_neg: np.float64 = np.max(z[z < 0])
else:
z_min_neg: np.float64 = self.custum_colorbar_values[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] < 0)[-1, 0]]
else:
z_max_neg: np.float64 = 0.
idx_s: np.ndarray[int] = np.arange(len(x[0]))
if scale_z == "log" and np.any(z > 0):
idx_s = np.argwhere(z > 0)[:, 0]
elif scale_z == "log":
idx_s = np.array([])
colors: np.ndarray[str] = []
if scale_z == "linear" and z is not None:
if cmap == "default":
colors = linear_color_interpolation(z, val_min=z_min, val_max=z_max,
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(np.minimum(np.maximum((z-z_min) / (z_max - z_min), 0), 1))])
elif scale_z == "log" and z is not None and np.any(z > 0):
if cmap == "default":
colors = linear_color_interpolation(np.log10(z[idx_s]), val_min=np.log10(z_min),
val_max=np.log10(z_max), col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors_pos: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(
np.minimum(np.maximum((np.log10(z[z > 0]) - np.log10(z_min))
/ (np.log10(z_max) - np.log10(z_min)), 0),
1))])
colors = np.full(len(z), cmap_auxi(0))
colors[z > 0] = colors_pos
elif z is not None:
colors = np.full(len(z), c_med)
ma = z > 0
if z_min_pos > 0.:
colors[ma] = linear_color_interpolation(np.log10(colors[ma]),
val_min=np.log10(z_min_pos),
val_max=np.log10(z_max),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
colors[~ma] = linear_color_interpolation(np.log10(-z[~ma]),
val_min=np.log10(-z_max_neg),
val_max=np.log10(-z_min),
col_min=c_med, col_max=c_min)
for (X, Y, i) in zip(x, y, np.arange(len(x))):
if not (z is not None and len(z) == len(y) and i not in idx_s):
if z is not None and len(z) == len(Y):
self.lines_x.append(np.array(X[idx_s]))
self.lines_y.append(np.array(Y[idx_s]))
else:
self.lines_x.append(np.array(X))
self.lines_y.append(np.array(Y))
self.err_x.append([])
self.err_y.append([])
args_auxi: dict = {}
for k in kwargs.keys():
if (isinstance(kwargs[k], list) | isinstance(kwargs[k], np.ndarray)) and len(kwargs[k]) == len(
y):
args_auxi[k] = kwargs[k][i]
else:
args_auxi[k] = kwargs[k]
if marker != "" and not ("linestyle" in args_auxi):
args_auxi["linestyle"] = ""
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
elif marker != "":
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
if z is None:
if "color" not in kwargs and len(y) <= 4:
args_auxi["color"] = l_colors[(self.compt_color + 1 + i) % len(l_colors)]
elif "color" not in kwargs:
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max: str = color_max
args_auxi["color"] = linear_color_interpolation(i, val_min=0, val_max=len(y) - 1,
col_min=c_min,
col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
args_auxi["color"] = np.ndarray[str] = cmap_auxi(i / (len(y) - 1))
elif len(z) == len(y):
args_auxi["color"] = colors[i]
else:
args_auxi["color"] = colors
if "label" in kwargs and args_auxi["label"] == "":
del args_auxi["label"]
# Delete empty legend to prevent a warning message and the addition of an empty gray square
self.param_lines.append(args_auxi)
if z is None and len(y) <= 4 and "color" not in kwargs:
self.compt_color += len(y)
elif z is None:
if "color" not in kwargs and len(y) <= 4:
self.compt_color += len(y)
elif "color" not in kwargs:
if color_min is None:
self.compt_color += 1
if color_max is None:
self.compt_color += 1
elif (isinstance(share_colorbar, bool) and (isinstance(share_colorbar, bool) and not share_colorbar)
and scale_z == "linear"):
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
colors = linear_color_interpolation(np.linspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.linspace(0., 1., 255))
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
elif isinstance(share_colorbar, bool) and (
isinstance(share_colorbar, bool) and not share_colorbar) and scale_z == "log":
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
args_auxi["color"] = linear_color_interpolation(np.geomspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.minimum(np.maximum((np.geomspace(z_min, z_max, 255) - z_min) / (z_max - z_min), 0.)))
self.customized_cmap(values=np.geomspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
elif isinstance(share_colorbar, bool) and (isinstance(share_colorbar, bool) and not share_colorbar):
if z_min_pos > 0.:
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
self.customized_cmap(values=z_colors, colors=colors, scale=scale_z, **kwargs_colorbar)
self.compt_color += 3
elif dim_y == 2 and dim_z == 2:
if scale_z == "linear" or scale_z == "symlog":
if isinstance(share_colorbar, bool):
z_min: np.float64 = np.min(z)
z_max: np.float64 = np.max(z)
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
else:
if isinstance(share_colorbar, bool):
if np.any(z > 0):
z_min: np.float64 = np.min(z[z > 0])
z_max: np.float64 = np.max(z)
else:
raise UserWarning(
"Graphique.line : z-axis has no strictly positive values and the scale is log)")
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
if scale_z == "symlog" and (z > 0).sum() > 0:
if isinstance(share_colorbar, bool):
z_min_pos: np.float64 = np.min(z[z > 0])
else:
z_min_pos: np.float64 = self.custum_colorbar_values[
np.argwhere(self.custum_colorbar_values > 0)[0, 0]]
else:
z_min_pos: np.float64 = 0.
if scale_z == "symlog" and z is not None and (z < 0).sum() > 0:
if isinstance(share_colorbar, bool):
z_max_neg: np.float64 = np.max(z[z < 0])
else:
z_min_neg: np.float64 = self.custum_colorbar_values[
np.argwhere(self.custum_colorbar_values < 0)[-1, 0]]
else:
z_max_neg: np.float64 = 0.
for (Y, Z, i) in zip(y, z, np.arange(len(y))):
if not share_colorbar:
if scale_z == "linear" or scale_z == "symlog":
z_min: np.float64 = np.min(Z)
z_max: np.float64 = np.max(Z)
else:
if np.any(z > 0):
z_min: np.float64 = np.min(Z[Z > 0])
z_max: np.float64 = np.max(Z)
else:
z_min: np.float64 = np.double(0.)
z_max: np.float64 = np.double(0.)
if scale_z == "symlog" and (Z > 0).sum() > 0:
z_min_pos: np.float64 = np.min(Z[Z > 0])
else:
z_min_pos: np.float64 = 0.
if scale_z == "symlog" and (Z < 0).sum() > 0:
z_max_neg: np.float64 = np.max(Z[Z < 0])
else:
z_max_neg: np.float64 = 0
if scale_z == "log":
idx_s = np.argwhere(Z > 0)[:, 0]
idx_s: np.ndarray[int] = np.arange(len(Z))
if scale_z == "log" and np.any(Z > 0):
idx_s = np.argwhere(Z > 0)[:, 0]
elif scale_z == "log":
idx_s = np.array([])
if len(idx_s) > 0:
self.lines_x.append(np.array(x[idx_s]))
self.lines_y.append(np.array(Y[idx_s]))
else:
self.lines_x.append(np.array([]))
self.lines_y.append(np.array([]))
self.err_x.append([])
self.err_y.append([])
args_auxi: dict = {}
for k in kwargs.keys():
if (isinstance(kwargs[k], list) | isinstance(kwargs[k], np.ndarray)) and len(kwargs[k]) == len(y):
args_auxi[k] = kwargs[k][i]
else:
args_auxi[k] = kwargs[k]
if marker != "" and not ("linestyle" in args_auxi):
args_auxi["linestyle"] = ""
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
elif marker != "":
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
if scale_z == "linear":
if share_colorbar:
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max: str = color_max
colors: np.ndarray = linear_color_interpolation(Z, val_min=z_min, val_max=z_max,
col_min=c_min,
col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(
np.minimum(np.maximum((Z - z_min) / (z_max - z_min), 0.), 1.))
else:
c_min: str = l_colors[(self.compt_color + 1 + 2 * i) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 2 + 2 * i) % len(l_colors)]
colors: np.ndarray = linear_color_interpolation(Z, val_min=z_min, val_max=z_max,
col_min=c_min,
col_max=c_max)
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=linear_color_interpolation(np.linspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max),
scale=scale_z, **kwargs_colorbar)
args_auxi["color"] = colors
elif scale_z == "log" and len(idx_s) > 0:
if share_colorbar:
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max: str = color_max
colors: np.ndarray = linear_color_interpolation(np.log10(np.maximum(Z, np.min(Z[idx_s]), 0.)),
val_min=np.log10(z_min),
val_max=np.log10(z_max),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.minimum(np.maximum((np.log10(np.maximum(Z, np.min(Z[idx_s]))) - np.log10(z_min)) / (np.log10(z_max) - np.log10(z_min)), 0.), 1.))
else:
c_min: str = l_colors[(self.compt_color + 1 + 2 * i) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 2 + 2 * i) % len(l_colors)]
colors: np.ndarray = linear_color_interpolation(np.log10(np.maximum(Z, np.min(Z[idx_s]), 0.)),
val_min=np.log10(z_min),
val_max=np.log10(z_max),
col_min=c_min, col_max=c_max)
self.customized_cmap(values=np.geomspace(z_min, z_max, 255),
colors=linear_color_interpolation(np.linspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max),
scale=scale_z, **kwargs_colorbar)
args_auxi["color"] = colors
else:
if share_colorbar:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
else:
c_min: str = l_colors[(self.compt_color + 1 + 3 * i) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2 + 3 * i) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3 + 3 * i) % len(l_colors)]
ma: np.ndarray[bool] = Z > 0.
args_auxi["color"] = np.full(len(x), c_med)
if z_min_pos > 0.:
args_auxi["color"][ma] = linear_color_interpolation(np.log10(Z[ma]),
val_min=np.log10(z_min_pos),
val_max=np.log10(z_max),
col_min=c_med, col_max=c_max)
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
args_auxi["color"][~ma] = linear_color_interpolation(np.log10(-Z[~ma]),
val_min=np.log10(-z_max_neg),
val_max=np.log10(-z_min),
col_min=c_med, col_max=c_min)
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
if not share_colorbar:
self.customized_cmap(values=z_colors,
colors=colors, scale=scale_z,
**kwargs_colorbar)
if "label" in kwargs and args_auxi["label"] == "":
del args_auxi["label"]
# Delete empty legend to prevent a warning message and the addition of an empty gray square
self.param_lines.append(args_auxi)
if isinstance(share_colorbar, bool) and share_colorbar:
if scale_z == "linear":
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
colors: np.ndarray = linear_color_interpolation(np.linespace(0, 1, 255),
val_min=0, val_max=1,
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.linespace(0, 1, 255))
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
elif scale_z == "log":
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
colors: np.ndarray = linear_color_interpolation(np.geomspace(z_min, z_max, 255),
val_min=np.log10(z_min),
val_max=np.log10(z_max),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi((np.geomspace(z_min, z_max, 255) - z_min) / (z_max - z_min))
self.customized_cmap(values=np.geomspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
else:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
if z_min_pos > 0.:
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
self.customized_cmap(values=z_colors, colors=colors, scale=scale_z, **kwargs_colorbar)
self.compt_color += 3
elif scale_z == "linear" or scale_z == "log":
self.compt_color += 2 * len(x)
else:
self.compt_color += 3 * len(x)
elif dim_y == 2 and dim_z < 2:
# if z is None and "color" not in kwargs:
# kwargs["color"] = l_colors[self.compt_color + 1 % len(l_colors)]
# self.compt_color += 1
if z is not None:
if z is not None and scale_z == "linear" or scale_z == "log":
if isinstance(share_colorbar, bool):
z_min: np.float64 = np.min(z)
z_max: np.float64 = np.max(z)
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max: str = color_max
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
elif z is not None:
if isinstance(share_colorbar, bool):
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
if np.any(z > 0):
z_min: np.float64 = np.min(z[z > 0])
z_max: np.float64 = np.max(z)
else:
raise UserWarning(
"Graphique.line : z-axis has no strictly positive values and the scale is log)")
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar][
self.custum_colorbar_values[share_colorbar] > 0])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_med: str = self.custum_colorbar_colors[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] > 0)[0, 0]]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
else:
z_min: np.float64 = np.double(0.)
z_max: np.float64 = np.double(0.)
if z is not None and scale_z == "symlog" and (
(z > 0).sum() > 0 or not isinstance(share_colorbar, bool)):
if isinstance(share_colorbar, bool):
z_min_pos: np.float64 = np.min(z[z > 0])
else:
z_min_pos: np.float64 = self.custum_colorbar_values[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] > 0)[0, 0]]
else:
z_min_pos: np.float64 = 0.
if z is not None and scale_z == "symlog" and (z < 0).sum() > 0:
if isinstance(share_colorbar, bool):
z_max_neg: np.float64 = np.max(z[z < 0])
else:
z_min_neg: np.float64 = self.custum_colorbar_values[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] < 0)[-1, 0]]
else:
z_max_neg: np.float64 = 0.
colors: np.ndarray[str] = []
if scale_z == "linear" and z is not None:
if cmap == "default":
colors = linear_color_interpolation(z, val_min=z_min, val_max=z_max,
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(
np.minimum(np.maximum((z - z_min) / (z_max - z_min), 0.), 1.))
elif scale_z == "log" and z is not None and np.any(z > 0):
if cmap == "default":
colors = linear_color_interpolation(np.log10(np.maximum(z, z[z > 0].min())), val_min=np.log10(z_min),
val_max=np.log10(z_max), col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(
np.minimum(np.maximum((np.log10(np.maximum(z, z[z > 0].min())) -
np.log10(z_min)) / (np.log10(z_max) - np.log10(z_min)), 0.), 1.))
else:
if z is not None:
colors = np.full(len(z), c_med)
ma = z > 0
if z_min_pos > 0.:
colors[ma] = linear_color_interpolation(np.log10(colors[ma]),
val_min=np.log10(z_min_pos),
val_max=np.log10(z_max),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
colors[~ma] = linear_color_interpolation(np.log10(-z[~ma]),
val_min=np.log10(-z_max_neg),
val_max=np.log10(-z_min),
col_min=c_med, col_max=c_min)
idx_s: np.ndarray[int] = np.arange(len(x))
if z is not None and scale_z == "log" and np.any(z > 0):
idx_s = np.argwhere(z > 0)[:, 0]
elif z is not None and scale_z == "log":
idx_s = np.array([])
for (Y, i) in zip(y, np.arange(len(y))):
if not (z is not None and len(z) == len(y) and i not in idx_s):
if z is not None and len(z) == len(Y):
self.lines_x.append(np.array(x)[idx_s])
self.lines_y.append(np.array(Y)[idx_s])
else:
self.lines_x.append(np.array(x))
self.lines_y.append(np.array(Y))
self.err_x.append([])
self.err_y.append([])
args_auxi: dict = {}
for k in kwargs.keys():
if (isinstance(kwargs[k], list) | isinstance(kwargs[k], np.ndarray)) and len(kwargs[k]) == len(
y):
args_auxi[k] = kwargs[k][i]
else:
args_auxi[k] = kwargs[k]
if marker != "" and not ("linestyle" in args_auxi):
args_auxi["linestyle"] = ""
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
elif marker != "":
if ((isinstance(marker, list) | isinstance(marker, np.ndarray))
and len(marker) == len(y)):
args_auxi["marker"] = marker[i]
else:
args_auxi["marker"] = marker
if z is None:
if "color" not in kwargs and len(y) <= 4:
args_auxi["color"] = l_colors[(self.compt_color + 1 + i) % len(l_colors)]
elif "color" not in kwargs:
if cmap == "default":
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
else:
c_max: str = color_max
args_auxi["color"] = linear_color_interpolation(i, val_min=0, val_max=len(y) - 1,
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
args_auxi["color"] = cmap_auxi(i / (len(y) - 1))
elif len(z) == len(y):
args_auxi["color"] = colors[i]
else:
args_auxi["color"] = colors
if "label" in kwargs and args_auxi["label"] == "":
del args_auxi["label"]
# Delete empty legend to prevent a warning message and the addition of an empty gray square
self.param_lines.append(args_auxi)
if z is None and len(y) <= 4 and "color" not in kwargs:
self.compt_color += len(y)
elif z is None and "color" not in kwargs:
if color_max is None and "cmap" == "default":
self.compt_color += 1
if color_min is None and "cmap" == "default":
self.compt_color += 1
elif z is not None and scale_z == "linear" and isinstance(share_colorbar, bool) and not share_colorbar:
if cmap == "default":
if color_max is None:
self.compt_color += 1
if color_min is None:
self.compt_color += 1
colors = linear_color_interpolation(np.linspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.linespace(0, 1, 255))
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
elif z is not None and scale_z == "log" and isinstance(share_colorbar, bool) and not share_colorbar:
if cmap == "default":
if color_max is None:
self.compt_color += 1
if color_min is None:
self.compt_color += 1
colors = linear_color_interpolation(np.geomspace(z_min, z_max, 255),
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi((np.geomspace(z_min, z_max, 255) - z_min) / (z_max - z_min))
self.customized_cmap(values=np.geomspace(z_min, z_max, 255),
colors=colors,
scale=scale_z, **kwargs_colorbar)
self.compt_color += 2
elif z is not None and isinstance(share_colorbar, bool) and not share_colorbar:
if z_min_pos > 0.:
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
self.customized_cmap(values=z_colors, colors=colors, scale=scale_z, **kwargs_colorbar)
self.compt_color += 3
else:
idx_s: np.ndarray[int] = np.arange(len(x))
if scale_z == "log" and np.any(z > 0):
idx_s = np.argwhere(z > 0)[:, 0]
elif scale_z == "log":
idx_s = np.array([])
self.lines_x.append(np.array(x)[idx_s])
self.lines_y.append(np.array(y)[idx_s])
self.err_x.append([])
self.err_y.append([])
if marker != "" and not ("linestyle" in kwargs):
kwargs["linestyle"] = ""
kwargs["marker"] = marker
elif marker != "":
kwargs["marker"] = marker
if z is None and "color" not in kwargs:
kwargs["color"] = l_colors[self.compt_color + 1 % len(l_colors)]
self.compt_color += 1
elif z is not None:
if z is not None and scale_z == "linear" or scale_z == "log":
if isinstance(share_colorbar, bool):
z_min: np.float64 = np.min(z)
z_max: np.float64 = np.max(z)
if color_min is None:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
else:
c_min: str = color_min
if color_max is None:
c_max: str = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
else:
c_max: str = color_max
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
elif z is not None:
if isinstance(share_colorbar, bool):
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
if np.any(z > 0):
z_min: np.float64 = np.min(z[z > 0])
z_max: np.float64 = np.max(z)
else:
raise UserWarning(
"Graphique.line : z-axis has no strictly positive values and the scale is log)")
else:
z_min: np.float64 = np.min(self.custum_colorbar_values[share_colorbar][
self.custum_colorbar_values[share_colorbar] > 0])
z_max: np.float64 = np.max(self.custum_colorbar_values[share_colorbar])
c_min: str = self.custum_colorbar_colors[share_colorbar][0]
c_med: str = self.custum_colorbar_colors[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] > 0)[0, 0]]
c_max: str = self.custum_colorbar_colors[share_colorbar][-1]
else:
z_min: np.float64 = np.double(0.)
z_max: np.float64 = np.double(0.)
if z is not None and scale_z == "symlog" and (
(z > 0).sum() > 0 or not isinstance(share_colorbar, bool)):
if isinstance(share_colorbar, bool):
z_min_pos: np.float64 = np.min(z[z > 0])
else:
z_min_pos: np.float64 = self.custum_colorbar_values[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] > 0)[0, 0]]
else:
z_min_pos: np.float64 = 0.
if z is not None and scale_z == "symlog" and (z < 0).sum() > 0:
if isinstance(share_colorbar, bool):
z_max_neg: np.float64 = np.max(z[z < 0])
else:
z_min_neg: np.float64 = self.custum_colorbar_values[share_colorbar][
np.argwhere(self.custum_colorbar_values[share_colorbar] < 0)[-1, 0]]
else:
z_max_neg: np.float64 = 0.
idx_s: np.ndarray[int] = np.arange(len(z))
if scale_z == "log" and np.any(z > 0):
idx_s = np.argwhere(z > 0)[:, 0]
elif scale_z == "log":
idx_s = np.array([])
colors: np.ndarray[str] = []
colors_cmap: np.ndarray[str] = []
if scale_z == "linear" and z is not None:
if cmap == "default":
colors = linear_color_interpolation(z, val_min=z_min, val_max=z_max,
col_min=c_min, col_max=c_max)
colors_cmap = linear_color_interpolation(np.linspace(z_min, z_max, 255), val_min=z_min,
val_max=z_max,
col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.maximum(np.minimum((z - z_min) / (z_max - z_min), 1), 0))
colors_cmap = cmap_auxi(np.linspace(0., 1., 255))
elif scale_z == "log" and z is not None and np.any(z > 0):
if "cmap" == "default":
colors = linear_color_interpolation(np.log10(np.maximum(z, z[idx_s].min())), val_min=np.log10(z_min),
val_max=np.log10(z_max), col_min=c_min, col_max=c_max)
colors_cmap = linear_color_interpolation(np.log10(np.geomspace(z_min, z_max, 255)),
val_min=np.log10(z_min),
val_max=np.log10(z_max), col_min=c_min, col_max=c_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.line : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = cmap_auxi(np.maximum(np.minimum((np.log10(np.maximum(z, z[idx_s].min())) - np.log10(z_min)) / (np.log10(z_max) - np.log10(z_min)), 1), 0))
colors_cmap = cmap_auxi((np.geomspace(z_min, z_max, 255) - z_min) / (z_max - z_min))
elif z is not None:
colors = np.full(len(z), c_med)
ma = z > 0
if z_min_pos > 0.:
colors[ma] = linear_color_interpolation(np.log10(colors[ma]),
val_min=np.log10(z_min_pos),
val_max=np.log10(z_max),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
colors[~ma] = linear_color_interpolation(np.log10(-z[~ma]),
val_min=np.log10(-z_max_neg),
val_max=np.log10(-z_min),
col_min=c_med, col_max=c_min)
kwargs["color"] = colors
if scale_z == "linear" and isinstance(share_colorbar, bool) and not share_colorbar:
self.customized_cmap(values=np.linspace(z_min, z_max, 255),
colors=colors_cmap,
scale=scale_z, **kwargs_colorbar)
elif scale_z == "log" and np.any(z > 0.) and isinstance(share_colorbar, bool) and not share_colorbar:
self.customized_cmap(values=np.geomspace(z_min, z_max, 255),
colors=colors_cmap,
scale=scale_z, **kwargs_colorbar)
elif isinstance(share_colorbar, bool) and not share_colorbar:
c_min: str = l_colors[(self.compt_color + 1) % len(l_colors)]
c_med: str = l_colors[(self.compt_color + 2) % len(l_colors)]
c_max: str = l_colors[(self.compt_color + 3) % len(l_colors)]
ma: np.ndarray[bool] = z > 0.
z_min: np.float64 = np.min(z)
z_max: np.float64 = np.max(z)
if np.any(z > 0):
z_min_pos: np.float64 = np.min(z[z > 0])
else:
z_min_pos: np.float64 = 0.
if np.any(z < 0):
z_max_neg: np.float64 = np.max(z[z < 0])
else:
z_max_neg: np.float64 = 0.
if z_min_pos > 0.:
z_colors1 = np.geomspace(z_min_pos, z_max, 255 // 2)
colors1 = linear_color_interpolation(np.linspace(np.log10(z_min_pos), np.log10(z_max),
255 // 2),
col_min=c_med, col_max=c_max)
else:
z_colors1 = np.array([])
colors1 = np.array([])
if z_max_neg < 0.:
z_colors2 = -np.geomspace(-z_min, -z_max_neg, 255 // 2)
colors2 = linear_color_interpolation(np.linspace(np.log10(-z_min), np.log10(-z_max_neg),
255 // 2),
col_min=c_med, col_max=c_min)
else:
z_colors2 = np.array([])
colors2 = np.array([])
z_colors: np.ndarray[np.float64] = np.append(z_colors2, z_colors1)
colors: np.ndarray[np.float64] = np.append(colors2, colors1)
self.customized_cmap(values=z_colors, colors=colors, scale=scale_z,
**kwargs_colorbar)
self.compt_color += 4
if "label" in kwargs and kwargs["label"] == "":
del kwargs["label"]
self.param_lines.append(kwargs)
if hide and len(self.indexs_plot_lines) == 0:
if dim_y == 1:
self.indexs_plot_lines = list(np.arange(len(self.lines_x) - 1))
elif dim_y > 1:
self.indexs_plot_lines = list(np.arange(len(self.lines_x) - len(y)))
elif not hide and len(self.indexs_plot_lines) != 0:
if dim_y == 1:
self.indexs_plot_lines.append(len(self.lines_x) - 1)
elif dim_y > 1:
self.indexs_plot_lines.extend(list(np.arange(len(self.lines_x) - len(y), len(self.lines_x))))
[docs]
def set_indexs_plot_lines(self, indexs=list | np.ndarray | str) -> None:
"""
Set the order in which the lines are plotted. If the index size is smaller than the lists of x/y lines
then some of them will not be plotted.
Parameters
----------
indexs : list | np.ndarray | str
List lines' indexs to plot. The plotting order is the order of index.
If index=="default", then all the lines will be plotted in the order in which they were saved
Returns
-------
None
"""
if isinstance(indexs, str) and indexs != "default":
raise UserWarning("Graphique.set_order_plot_lines : The only string available as parameter is 'default',"
" not ", indexs)
elif not isinstance(indexs, list | np.ndarray | str):
raise UserWarning("Graphique.set_order_plot_lines : The only type available as parameter are "
"list, array or str not", type(indexs))
elif (isinstance(indexs, list | np.ndarray) and (len(indexs) > len(self.lines_x)
or np.max(indexs) >= len(self.lines_x))):
raise UserWarning("Graphique.set_order_plot_lines : there is at least one index in the index list",
np.max(indexs), "that is higher than the maximum possible index ", len(self.lines_x) - 1)
self.indexs_plot_lines = list(indexs)
[docs]
def text(self, x: list | np.ndarray, y: list | np.ndarray,
s: list | np.ndarray, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to ```plt.text```
Parameters
----------
x: list | np.ndarray
Abscissa(s)
y: list | np.ndarray
Ordinate(s)
s: list | np.ndarray
Texts to plot
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
Additional argument to ```plot()``` function like linestyle, color....
To rotate the text one can use the 'rotation' parameter with the angle in degrees or
the "vertical" "horizontal" keyword.
Returns
-------
None
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
if isinstance(s, str) and isinstance(x, list | np.ndarray):
s: np.ndarray = np.array([s for X in x])
if (isinstance(x, list | np.ndarray) and isinstance(y, list | np.ndarray)
and (len(np.shape(np.array(x))) == 1 and len(np.shape(np.array(y))) == 1
and len(np.array(x)) == len(np.array(y)))):
args_auxi: list[dict] = [{"axis_config": axis_config} for X in x]
for k in kwargs.keys():
if isinstance(kwargs[k], list | np.ndarray) and len(kwargs[k]) == len(x):
for i in range(len(x)):
args_auxi[i][k] = kwargs[k][i]
else:
for i in range(len(x)):
args_auxi[i][k] = kwargs[k]
if "color" not in kwargs:
for i in range(len(x)):
args_auxi[i]["color"] = l_colors[(len(self.lines_x) + i - 1) % len(l_colors)]
for (X, Y, S, argsS) in zip(x, y, s, args_auxi):
self.lines_t_x.append(X)
self.lines_t_y.append(Y)
self.lines_t_s.append(S)
self.param_texts.append(argsS)
elif (isinstance(x, list | np.ndarray) and isinstance(y, list | np.ndarray)
and len(y) != len(x)):
raise ValueError("Graphique.text : the ordinate list should have the same size than "
"the abscissa list len(x): "
+ str(len(x)) + " y : " + str(np.shape(np.array(y))))
elif (isinstance(x, list | np.ndarray) and isinstance(y, list | np.ndarray)
and len(y) != len(s)):
raise ValueError("Graphique.text : the ordinate list should have the same size than "
"the text list len(s): "
+ str(len(s)) + " y : " + str(np.shape(np.array(y))))
else:
self.lines_t_x.append(x)
self.lines_t_y.append(y)
self.lines_t_s.append(s)
if "color" not in kwargs:
# args["color"] = 'C' + str(len(self.lines_x) % 10)
kwargs["color"] = l_colors[(len(self.lines_x) - 1) % len(l_colors)]
self.param_texts.append(kwargs)
[docs]
def point(self, xp: float | np.double, yp: float | np.double, marker: str = "o", hide: bool = False,
axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to Graphique.line([xp],[yp],**args)
Parameters
----------
xp: float | np.double
Abscissa
yp: float | np.double
Ordinate
marker: str, optional, default="o"
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
Additional argument to plot() function like linestyle, color....
Returns
-------
None
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line([xp], [yp], marker=marker, hide=hide, axis_config=axis_config,
**kwargs)
[docs]
def errorbar(
self, x: list | np.ndarray, y: list | np.ndarray, err_y: list | np.ndarray,
err_x: np.ndarray | list | None = None, marker: str = "", scale: str = "",
hide: bool = False, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to plt.errorbar
Parameters
----------
x : list | array_like
Abscissa
y : list | array_like
Ordinate
err_y : list | array_like
Error associated with y
err_x : list | array_like
Error associated with x
marker : list[str] | array_like[str], str, optional, default=""
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
scale : str, optional, default="linear"
The scales of (x, y) axis :
- default : "" (linear scale for both x and y)
- polar : polar projection : X=r and Y=theta
- loglog, logx, logy : Logarithmic scale for both, x or y axis
- symloglog, symlogx, symlogy : Logarithmic scale for both, x or y axis with positive and négative values
hide: bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
Additional argument to plot() function like linestyle, color....
Returns
-------
None
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
if isinstance(err_y, str):
raise TypeError("Graphique.errorbar : no error on the y axis are provided")
if isinstance(err_x, str) and marker == "":
marker = err_x
err_x = None
if (isinstance(err_y, list | np.ndarray)
and ((isinstance(err_y[0], list | np.ndarray)
and ((isinstance(x, list | np.ndarray)
and len(err_y[0]) != len(x[0]))
or (not isinstance(x, list | np.ndarray) and len(err_y[0]) != len(x))))
or (not isinstance(err_y[0], list | np.ndarray) and len(err_y) != len(x)))):
raise ValueError(
"Graphique.errorbar the size of errors array should be equal to the size of"
"abscissa array : x :" +
str(len(x)) + " y : " + str(len(y)) + " err y : " + str(len(err_y)))
if isinstance(err_y, float | np.float64 | np.float32):
if isinstance(y, list) and isinstance(y[0], np.ndarray | list):
err_y = [np.full(len(Y), err_y) for Y in y]
elif isinstance(y, list):
err_y = np.full(len(y), err_y)
else:
err_y = np.full(y.shape, err_y)
if (len(err_y) != len(y) and len(err_y) != 2) or (len(err_y) == 2 and
len(err_y[0]) != len(y) and len(err_y[0]) != len(y[0])):
raise ValueError(
"Graphique.errorbar the size of ordinate's errors array should be equal to the size of "
"ordinate array : len(x)=" +
str(len(x)) + " len(y)= " + str(len(y)) + " shape(err y)" + str(np.array(err_y).shape))
elif (isinstance(y[0], list | np.ndarray) and isinstance(err_y[0], list | np.ndarray)
and np.any([(len(Y) != len(errY) and len(errY) != 2)
or (len(errY) == 2 and len(Y) != len(errY[0]))
for (Y, errY) in zip(y, err_y)])):
raise ValueError(
"Graphique.errorbar the size of ordinate's errors array should be equal to the size of "
"ordinate array")
elif (isinstance(y[0], list | np.ndarray)
and ((not isinstance(err_y[0], list | np.ndarray)) or len(err_y[0]) != 2)
and np.any([(len(y) != len(err_y) and len(err_y) != 2)
or (len(err_y) == 2 and len(Y) != len(err_y[0])) for Y in y])):
raise ValueError(
"Graphique.errorbar the size of ordinate's errors array should be equal to the size of "
"ordinate array")
if (err_x is not None and isinstance(err_x, list | np.ndarray)
and (not isinstance(err_x[0], list | np.ndarray)
and (len(err_x) != len(x) or (len(err_x) == 2 and len(err_x[0]) != len(x))))):
raise ValueError(
"Graphique.errorbar the size of abscissa's errors array should be equal to the size of "
"abscissa array : len(x)=" +
str(len(x)) + " len(y)=" + str(len(y)) + " shape(err y)=" + str(np.array(err_y).shape))
elif err_x is not None and (isinstance(y[0], list | np.ndarray) and isinstance(err_x, list | np.ndarray)
and isinstance(err_x[0], list | np.ndarray)
and np.any([(len(X) != len(errX) and len(errX) != 2)
or (len(errX) == 2 and len(errX[0]) != len(X))
for (X, errX) in zip(x, err_x)])):
raise ValueError(
"Graphique.errorbar the size of abscissa's errors array should be equal to the size of"
"ordinate array")
elif err_x is not None and (isinstance(err_x, list | np.ndarray)
and isinstance(x[0], list | np.ndarray)
and np.any([(len(X) != len(err_x) and len(err_x) != 2)
or (len(err_x) == 2 and len(err_x[0]) != len(X))
for X in x])):
raise ValueError(
"Graphique.errorbar the size of abscissa's errors array should be equal to the size of"
"ordinate array")
if scale == "":
self.line(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "polaire":
self.polar(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "loglog":
self.loglog(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "logx":
self.logx(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "logy":
self.logy(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "symloglog":
self.symloglog(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "symlogx":
self.symlogx(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "symlogy":
self.symlogy(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
else:
raise (ValueError("The scale " + scale + """ is not available. Please use : "", "polar",
"loglog", "logx", "logy", "symloglog", "symlogx", "symlogy" """))
if isinstance(y[0], list | np.ndarray):
for i in range(len(y) - 1, -1, -1):
if isinstance(err_y[0], list | np.ndarray):
self.err_y[-1 - i] = err_y[-1 - i]
else:
self.err_y[-1 - i] = err_y
if (err_x is not None and isinstance(err_x, list | np.ndarray)
and isinstance(err_x[0], list | np.ndarray)):
self.err_x[-1 - i] = err_x[-1 - i]
elif err_x is not None:
self.err_x[-1 - i] = err_x
else:
self.err_x[-1 - i] = []
else:
self.err_y[-1] = err_y
if err_x is not None:
self.err_x[-1] = err_x
else:
self.err_x[-1] = []
[docs]
def errorplot(
self, x: list | np.ndarray, y: list | np.ndarray, err_y: list | np.ndarray,
marker: str = "", scale: str = "", hide: bool = False, axis_config: str = "bl",
alpha_error: np.float64 = np.double(0.5), color_errors: str | np.float64 = None, **kwargs) -> None:
"""
Equivalent to plt.errorbar but the error is not represented by errorbars but by a
uniform-colored polygon
Parameters
----------
x : list | array_like
Abscissa
y : list | array_like
Ordinate
err_y : list | array_like
Error associated with y
marker : list[str] | array_like[str], str, optional, default=""
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
scale : str, optional, default="linear"
The scales of (x, y) axis :
- default : "" (linear scale for both x and y)
- polar : polar projection : X=r and Y=theta
- loglog, logx, logy : Logarithmic scale for both, x or y axis
- symloglog, symlogx, symlogy : Logarithmic scale for both, x or y axis with positive and négative values
hide: bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
alpha_error : float, optional, default=0.5
The trensparency parameter of the shaded area that represant errors
color_errors : str, optional
Color of the shaded area that represant error, default is the markers colors
kwargs
Additional argument to plot() function like linestyle, color....
Returns
-------
None
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
if type(err_y) is str:
raise TypeError("Graphique.errorbar : no error on the y axis are provided")
if isinstance(err_y, list | np.ndarray) and (
(isinstance(err_y[0], list | np.ndarray) and len(err_y[0]) != len(x))
or (not isinstance(err_y[0], list | np.ndarray) and len(err_y) != len(x))):
raise ValueError(
"Graphique.errorbar the size of errors array should be equal to the size of"
"abscissa array : x :" +
str(len(x)) + " y : " + str(len(y)) + " err y : " + str(len(err_y)))
if isinstance(err_y, float | np.float64 | np.float32):
if isinstance(y, list) and isinstance(y[0], np.ndarray):
err_y = [np.full(len(Y), err_y) for Y in y]
elif isinstance(y, list):
err_y = np.full(len(y), err_y)
else:
err_y = np.full(y.shape, err_y)
compt_color: int = self.compt_color
if scale == "":
self.line(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "polaire":
self.polar(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "loglog":
self.loglog(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "logx":
self.logx(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "logy":
self.logy(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "symloglog":
self.symloglog(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "symlogx":
self.symlogx(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
elif scale == "symlogy":
self.symlogy(x, y, marker=marker, hide=hide, axis_config=axis_config, **kwargs)
else:
raise (ValueError("The scale " + scale + """ is not available. Please use : "", "polar",
"loglog", "logx", "logy", "symloglog", "symlogx", "symlogy" """))
if (isinstance(y[0], list | np.ndarray) and isinstance(err_y, list | np.ndarray)
and isinstance(err_y[0], list | np.ndarray)):
for (Y, errY, i) in zip(y, err_y, np.arange(len(y))):
erry: list = list(Y + errY)
erry2: list = list(Y - errY)
erry2.reverse()
erry.extend(erry2)
xa: list = list(x)
x2: list = xa.copy()
x2.reverse()
xa.extend(x2)
ind: np.ndarray = np.array([xa, erry]).T
if color_errors is not None and isinstance(color_errors, str):
self.polygon(ind, facecolor=color_errors, alpha=alpha_error)
elif color_errors is not None:
self.polygon(ind, facecolor=color_errors[i], alpha=alpha_error)
elif len(y) < 4:
self.polygon(ind, facecolor=l_colors[compt_color + i + 1], alpha=alpha_error)
else:
self.polygon(ind, facecolor=linear_color_interpolation(i, val_min=0, val_max=len(y) - 1,
col_min=l_colors[compt_color + 1],
col_max=l_colors[compt_color + 2]),
alpha=alpha_error)
elif isinstance(y[0], list | np.ndarray):
for (Y, i) in zip(y, np.arange(len(y))):
erry: list = list(Y + err_y)
erry2: list = list(Y - err_y)
erry2.reverse()
erry.extend(erry2)
x: list = list(x)
x2: list = x.copy()
x2.reverse()
x.extend(x2)
ind: np.ndarray = np.array([x, erry]).T
if color_errors is not None and isinstance(color_errors, str):
self.polygon(ind, facecolor=color_errors, alpha=alpha_error)
elif color_errors is not None:
self.polygon(ind, facecolor=color_errors[i], alpha=alpha_error)
elif len(y) < 4:
self.polygon(ind, facecolor=l_colors[compt_color + i + 1], alpha=alpha_error)
else:
self.polygon(ind, facecolor=linear_color_interpolation(i, val_min=0, val_max=len(y) - 1,
col_min=l_colors[compt_color + 1],
col_max=l_colors[compt_color + 2]),
alpha=alpha_error)
else:
erry: list = list(y + err_y)
erry2: list = list(y - err_y)
erry2.reverse()
erry.extend(erry2)
x: list = list(x)
x2: list = x.copy()
x2.reverse()
x.extend(x2)
ind: np.ndarray = np.array([x, erry]).T
if color_errors is not None:
if not isinstance(color_errors, str):
raise UserWarning("The errors colors should be a string")
self.polygon(ind, facecolor=color_errors, alpha=alpha_error)
else:
self.polygon(ind, facecolor=l_colors[compt_color + 1], alpha=alpha_error)
[docs]
def polar(self, r: list | np.ndarray, theta: list | np.ndarray,
z: np.ndarray | list | None = None, marker: str = "",
share_colorbar: bool = False, scale_z: str = "linear", hide: bool = False,
kwargs_colorbar: dict | None = None, axis_config: str = "bl",
**kwargs: dict) -> None:
"""
Equivalent to self.line in polar projection
Parameters
----------
r : list | array_like
Radius
theta : list | array_like
Angle(s)
z : list | array_like, optional
z-axis (represented by a colorscale)
marker: : list[str] | array_like, str, optional, default=""
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
share_colorbar : bool, optional, default=True
If True(default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z: str, optional, {"linear", "log", "symlog"}, default="linear"
The scale of the z-axis (linear (default), log, symplog)
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar: dict
Extra arguments for the colorbar (if z is not None)
kwargs
Additional argument to plot() function like linestyle, color...
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
Returns
-------
None
Notes
-------
The order of first and second arguments is opposit to the matplotlib one :
The first argument is the radius, then the angle
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
if isinstance(theta[0], list | np.ndarray) and not isinstance(r[0], list | np.ndarray):
r = [r for t in theta]
# dim_r: int = 0
# dim_theta: int = 0
# dim_z: int = 0
# if isinstance(theta, str):
# marker = theta
# theta = None
# if isinstance(z, str):
# marker = z
# z = None
# if theta is None:
# theta = np.copy(r)
# r = np.arange(0, len(theta))
# if isinstance(r[0], list) | isinstance(r[0], np.ndarray):
# if isinstance(r[0][0], list) | isinstance(r[0][0], np.ndarray):
# raise UserWarning("Graphique.line the x-axis dimension cannot be superior than 2")
# else:
# dim_r: int = 2
# else:
# dim_r: int = 1
# if isinstance(theta[0], list) | isinstance(theta[0], np.ndarray):
# if isinstance(theta[0][0], list) | isinstance(theta[0][0], np.ndarray):
# raise UserWarning("Graphique.line the y-axis dimension cannot be superior than 2")
# else:
# dim_theta: int = 2
# else:
# dim_theta: int = 1
# if z is not None and isinstance(z[0], list) | isinstance(z[0], np.ndarray):
# if isinstance(z[0][0], list) | isinstance(z[0][0], np.ndarray):
# raise UserWarning("Graphique.line the z-axis dimension cannot be superior than 2")
# else:
# dim_z: int = 2
# elif z is None:
# dim_z: int = 0
# else:
# dim_z: int = 1
#
# if (z is None or dim_z == 1) and dim_r == 1 and dim_theta == 2:
# for thet in theta:
# self.line(thet, r, z=z, marker=marker, share_colorbar=share_colorbar,
# scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
# if (z is not None and dim_z == 2) and dim_r == 1 and dim_theta == 2:
# for (thet, zz) in zip(theta, z):
# self.line(thet, r, z=zz, marker=marker, share_colorbar=share_colorbar,
# scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
# else:
self.line(theta, r, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
self.config_ax(projection="polar")
[docs]
def loglog(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", hide: bool = False, kwargs_colorbar: dict | None = None,
axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to self.line with a logarithmique scale for both x and y-axis:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-----
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.line(x,[y1,y2], *args)``` is equivalent to
```plt.plot(x, y1, *args)
plt.plot(x, y2, *args)```
- if y1 and y2 have not the same size:
```self.line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.line((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"]```
is equivalent to
```plt.plot(x, y1, marker=".", label="Curve1")
plt.plot(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.linspace(0, 10, 1000)
>>> alpha = np.linspace(1, 5, 10)
>>> colors = g.linear_color_interpolation(np.arange(len(alpha)), col_min=C1, col_max=C2)
>>> gr = g.Graphique()
>>> gr.loglog(x, [x*a for a in alpha], color=colors)
>>> gr.customized_cmap(alpha, colors)
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
self.config_ax(xscale="log", yscale="log", axis=axis_config)
[docs]
def symloglog(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", hide: bool = False,
kwargs_colorbar: dict | None = None, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to self.line with a logarithmique scale for both x and y-axis
Both the negative and positive parts of y are represanted:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.symloglog(x,[y1,y2], *args)``` is equivalent to
```ax=plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(xscale="symlog", yscale="symlog")```
- if y1 and y2 have not the same size:
```self.line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.symploglog((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```ax=plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(xscale="symlog", yscale="symlog")```
Examples
--------
>>> x = np.linspace(-10, 10, 1000)
>>> gr = g.Graphique()
>>> gr.symloglog(x, np.tan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
self.config_ax(xscale="symlog", yscale="symlog", axis=axis_config)
[docs]
def logx(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", hide: bool = False,
kwargs_colorbar: dict | None = None, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to self.line with a logarithmique scale for x-axis:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.line(x,[y1,y2], *args)``` is equivalent to
```plt.plot(x, y1, *args)
plt.plot(x, y2, *args)```
- if y1 and y2 have not the same size:
```self.line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.line((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```plt.plot(x, y1, marker=".", label="Curve1")
plt.plot(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.logspace(-10, 10, 1000)
>>> gr = Graphique()
>>> gr.logx(x, np.arctan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
self.config_ax(xscale="log", axis=axis_config)
[docs]
def symlogx(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", hide: bool = False,
kwargs_colorbar: dict | None = None, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to self.line with a logarithmique scale for both x-axis (both negative and positive
part are represanted):
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.line(x,[y1,y2], *args)``` is equivalent to
```plt.plot(x, y1, *args)
plt.plot(x, y2, *args)```
- if y1 and y2 have not the same size:
```self.line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.line((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```plt.plot(x, y1, marker=".", label="Curve1")
plt.plot(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.append(-np.logspace(10, -10, 1000), np.logspace(-10, 10, 1000))
>>> gr = Graphique()
>>> gr.symlogx(x, np.arctan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
self.config_ax(xscale="symlog", axis=axis_config)
[docs]
def logy(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", hide: bool = False,
kwargs_colorbar: dict | None = None, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to ```self.line``` with a logarithmique scale for y-axis:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.line(x,[y1,y2], *args)``` is equivalent to
```plt.plot(x, y1, *args)
plt.plot(x, y2, *args)```
- if y1 and y2 have not the same size:
```self.line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.line((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```plt.plot(x, y1, marker=".", label="Curve1")
plt.plot(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.logspace(-10, 10, 1000)
>>> gr = Graphique()
>>> gr.logy(x, np.arctan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
self.config_ax(yscale="log", axis=axis_config)
[docs]
def symlogy(self, x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", hide: bool = False,
kwargs_colorbar: dict | None = None, axis_config: str = "bl", **kwargs) -> None:
"""
Equivalent to ```self.line``` with a logarithmique scale for y-axis (both positive and negative
part are represanted):
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
None
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.symlogy(x,[y1,y2], *args)``` is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(yscale="symplog")```
- if y1 and y2 have not the same size:
```self.symlogy([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```self.symplogy((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```ax=plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(yscale="symlog")```
Examples
--------
>>> x = np.linspace(0,np.pi,1000)
>>> gr = g.Graphique()
>>> gr.symlogy(x, np.tan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
self.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, **kwargs)
self.config_ax(yscale="symlog", axis=axis_config)
[docs]
def histogram(
self, values: np.ndarray, weights: np.ndarray | None = None,
normalization: bool = True, statistic: str = 'sum', bins: int = 10, stat_args: dict = None,
**kwargs) -> None:
"""
Plot the histogram of values
Parameters
----------
values : array_like
The values to histogramed
weights : array_like, optional
The weights to be applied to values
normalization : bool, optional, default=True
If the histogram is normalized or not
statistic : str, optional, default="sum"
The statistic to compute.
The following statistics are available
- 'mean': compute the mean of values for points within each bin. Empty bins will be represented by NaN.
- 'std': compute the standard deviation within each bin. This is implicitly calculated with ddof=0.
- 'median': compute the median of values for points within each bin. Empty bins will be represented by NaN.
- 'count': compute the count of points within each bin. This is identical to an unweighted histogram. values array is not
referenced.
- 'sum': compute the sum of values for points within each bin. This is identical to a weighted histogram.
- 'min': compute the minimum of values for points within each bin. Empty bins will be represented by NaN.
- 'max': compute the maximum of values for point within each bin. Empty bins will be represented by NaN.
bins : int, optional, default=10
Number of bins in the histogram
stat_args, dict, optional
Additionals argument for `sp.binned_statistic`
kwargs
Additionals argument for plt.bars
Returns
-------
None
See also
--------
scipy.stats.binned_statistic
"""
if weights is None:
weights = np.ones(len(values))
if stat_args is None:
stat_args = dict()
vals, bds, indices = sp.binned_statistic(
values, weights, statistic, bins, **stat_args)
if normalization:
vals /= len(values)
vals /= bds[1:] - bds[:-1]
if "color" not in kwargs:
kwargs["color"] = l_colors[(self.compt_color + 1) % len(l_colors)]
self.compt_color += 1
self.bords_histogramme.append(bds)
self.vals_histogramme.append(vals)
self.param_histogrammes.append(kwargs)
[docs]
def image(self, array_image: np.ndarray,
x_axe: list | np.ndarray | None = None, y_axe: list | np.ndarray | None = None,
colorscale: str = "linear",
cmap: str = "default", colorbar_ticks: list | np.ndarray | None = None,
colorbar_label: str = "", kwargs_colorbar: dict | None = None,
colorbar_index: int = ii_max, color_min: str | tuple = None, color_max: str | tuple = None,
vmin: np.float64 = -np.inf, vmax: np.float64 = np.inf, axis_config: str = "bl",
**kwargs) -> None:
"""
Plot the array image through plt.pcolor or plt.imshow for 3 color images
Parameters
----------
array_image : np.ndarray
The matrix (2D, or 3D for colored images (the color is on the third axis)) to be plotted
x_axe : list | np.ndarray, optional, default=np.arange(0,array_image.shape[0])
The x-axes coordinate (for the array), only for 2d array_image
y_axe : list | np.ndarray, optional, default=np.arange(0,array_image.shape[1])
The y-axes coordinate (for the array), only for 2d array_image
colorscale : str, optional, default="linear", {"linear", "log", "symlog"}
The scale for the colorbar
cmap : str, optional, default="default"
The colormap, default a linear color interpolation between two colors CX
colorbar_ticks : list | array_like, optional
The colorbar's ticks
colorbar_label : str, optional, default=""
The colorbar's label
kwargs_colorbar : dict, optional
Additional arguments for the colorbar :
- location: str, {'right', 'top', 'bottom', 'left'}
Indicate where the colorbar should be plotted
- scale: str, {'linear', 'log', 'symlog'}
The scale of the colorbar
- ticks: list | array_like
- format: str
ticks' format
- label: str
The label to plot along the colorbar
- size: float, default=0.01
relative width of the colorbar
- fraction: float, default=1
relative hight of the colorbar
- space_between: float, default=0.01
relative space between colorsbars (and the plot)
colorbar_index : int, optional
The index of a previouly defined colorbar, to use insted of building a new one, all the others colorbar are
ignored if provided
vmin : np.float64, optional, default : the minimum of array_image
The minimum value for the colorbar
vmax : np.float64, optional, default : the maximum of array_image
The maximum value for the colorbar
color_min : str | tuple, optional
The color associated with the minimum value for a `default` cmap
color_max : str | tuple, optional
The color associated with the maximum value for a `default` cmap
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
Additionals arguments for pcolor
Returns
-------
None
See Also
--------
matplotlib.pyplot.pcolor
Use to plot 2d array images
matplotlib.pyplot.imshow
Use to plot 3-colors images
Graphique.contours
To draw levels lines onto the image
"""
if x_axe is None:
x_axe = np.arange(0, array_image.shape[1])
if y_axe is None:
y_axe = np.arange(0, array_image.shape[0])
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
kwargs["axis_config"] = axis_config
if vmin == -np.inf:
vmin: np.float64 = np.nanmin(array_image)
else:
array_image[array_image < vmin] = vmin
if vmax == np.inf:
vmax: np.float64 = np.nanmax(array_image)
else:
array_image[array_image > vmax] = vmax
if kwargs_colorbar is None:
kwargs_colorbar = {}
if colorscale == "linear":
color_values: np.ndarray[np.float64] = np.linspace(vmin, vmax, 255)
elif colorscale == "log":
if vmin <= 0. and np.any(array_image > 0.):
vmin: np.float64 = np.nanmin(array_image[array_image > 0.])
elif not np.any(array_image > 0.):
raise UserWarning("Graphique.image : There is no positive values to plot with the log scale")
color_values: np.ndarray[np.float64] = np.geomspace(vmin, vmax, 255)
elif colorscale == "symlog":
if vmin > 0:
color_values: np.ndarray[np.float64] = np.geomspace(vmin, vmax, 255)
elif vmax < 0:
color_values: np.ndarray[np.float64] = np.geomspace(-vmin, -vmax, 255)
else:
vneg_sup: np.float64 = np.nanmax(array_image[array_image < 0.])
vpos_inf: np.float64 = np.nanmin(array_image[array_image > 0.])
color_values: np.ndarray[np.float64] = np.append(np.geomspace(-vmin, -vneg_sup,
int(abs(np.log10(vmin / vneg_sup)
/ (np.log10(vmin / vneg_sup)
+ np.log10(vmax / vpos_inf)))
* 255)),
np.geomspace(vpos_inf, vmax,
int(abs(np.log10(vmax / vpos_inf)
/ (np.log10(vmin / vneg_sup)
+ np.log10(vmax / vpos_inf)))
* 255)))
else:
color_values: np.ndarray[np.float64] = colorscale
if len(array_image.shape) == 3:
if array_image.shape[2] > 4:
raise UserWarning("Graphique.image : The array_image have not the right shape to plot a color image")
array_image = np.interp(array_image, color_values, np.linspace(0, 1, len(color_values)))
if cmap != "default":
print("Warning Graphique.image : for colored images, the colorbars parameters are ignored")
if "location" not in kwargs_colorbar.keys():
kwargs_colorbar["location"] = 'right'
if "size" not in kwargs_colorbar.keys():
kwargs_colorbar["size"] = 0.02
# colors_r: np.ndarray[str] = linear_color_interpolation(np.arange(len(color_values)),
# col_min=to_hex((0, 0, 0)),
# col_max=to_hex((1, 0, 0)))
#
# self.customized_cmap(color_values, colors_r, ticks=colorbar_ticks, label=colorbar_label,
# **kwargs_colorbar)
# self.index_colorbar_image.append(len(self.custum_colorbar_colors) - 1)
#
# colors_v: np.ndarray[str] = linear_color_interpolation(np.arange(len(color_values)),
# col_min=to_hex((0, 0, 0)),
# col_max=to_hex((0, 1, 0)))
# self.customized_cmap(color_values, colors_v, ticks="", label="", share_axis=True,
# space_between=0.005, **kwargs_colorbar)
# self.index_colorbar_image.append(len(self.custum_colorbar_colors) - 1)
#
# colors_b: np.ndarray[str] = linear_color_interpolation(np.arange(len(color_values)),
# col_min=to_hex((0, 0, 0)),
# col_max=to_hex((0, 0, 1)))
# self.customized_cmap(color_values, colors_b, ticks="", label="", share_axis=True,
# space_between=0.005, **kwargs_colorbar)
# self.index_colorbar_image.append(len(self.custum_colorbar_colors) - 1)
elif colorbar_index == ii_max:
if cmap == "default":
if color_min is None:
color_min = l_colors[(self.compt_color + 1) % len(l_colors)]
if color_max is None:
color_max = l_colors[(self.compt_color + 2) % len(l_colors)]
self.compt_color += 1
colors: np.ndarray[str] = linear_color_interpolation(np.arange(len(color_values)),
col_min= color_min,
col_max= color_max)
elif cmap not in list(plt.colormaps):
raise UserWarning("Graphique.image : the colorbar ", cmap,
"isn't awalible. Please use ", list(plt.colormaps))
else:
cmap_auxi = plt.get_cmap(cmap)
colors: np.ndarray[str] = np.array([to_hex(col) for col in
cmap_auxi(np.linspace(0, 1, len(color_values)))])
if kwargs_colorbar is None:
kwargs_colorbar = dict()
self.customized_cmap(color_values, colors, ticks=colorbar_ticks, label=colorbar_label, **kwargs_colorbar)
self.index_colorbar_image.append(len(self.custum_colorbar_colors) - 1)
if colorscale == "log":
self.config_colorbar(-1, ticks_label=np.array(["{:.2e}".format(t) for t in colorbar_ticks]))
if np.any(array_image < vmin) and np.any(array_image > vmax):
self.config_colorbar(extend="both")
elif np.any(array_image < vmin):
self.config_colorbar(extend="min")
elif np.any(array_image > vmax):
self.config_colorbar(extend="max")
else:
self.index_colorbar_image.append(int(colorbar_index))
self.array_image = array_image
self.x_axe_image = np.array(x_axe)
self.y_axe_image = np.array(y_axe)
self.param_image = kwargs
[docs]
def contours(
self, levels: int | np.ndarray | list | None = None, array_contours: np.ndarray | None = None,
x_axe: list | np.ndarray | None = None,
y_axe: list | np.ndarray | None = None, labels: list | np.ndarray | None = None,
labels_mask: np.ndarray | None = None, axis_config: str = "bl", **kwargs):
"""
Plot the level lines associated to self.array_image or array_contours
Parameters
----------
levels : int | array_like | list, optional
Number (or list of) levels to plot
array_contours : array_like, optional, default=self.arry_image
If not None, the reference array to determine the level
x_axe : array_like | list, optional
the x-axes coordinate (for the array if array_contour is not None)
y_axe : array_like | list, optional
the y-axes coordinate (for the array if array_contour is not None)
labels : array_like | list, optional
the labels of each level line
labels_mask : array_like | list, optional
the mask of levels line to show the labels
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
additional arguments
Returns
-------
None
See Also
--------
matplotlib.pyplot.contour
Used to plot the levels lines
Graphique.image
To plot an image, this image can be used as a reference for the levels lines
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
kwargs["axis_config"] = axis_config
idx_levels: np.ndarray | None = None
if isinstance(levels, list):
levels = np.array(levels)
if isinstance(levels, np.ndarray):
idx_levels = np.argsort(levels)
levels = levels[idx_levels]
if "color" in kwargs.keys():
if isinstance(kwargs["color"], np.ndarray | list):
kwargs["colors"] = np.copy(kwargs["color"])
else:
kwargs["colors"] = kwargs["color"]
del kwargs["color"]
if "colors" in kwargs.keys() and (type(kwargs["colors"]) is list
or type(kwargs["colors"]) is np.ndarray):
if idx_levels is None:
self.color_label_contours = kwargs["colors"]
else:
self.color_label_contours = kwargs["colors"][idx_levels]
del kwargs["colors"]
if levels is not None:
kwargs['levels'] = levels
if labels is not None:
if len(labels) != len(levels):
raise UserWarning("Graphique.contours : the labels size should be equal to the levels size: levels",
len(levels), "labels :", len(labels))
self.clabels = labels[idx_levels]
if labels_mask is not None:
if len(labels_mask) != len(levels):
raise UserWarning("Graphique.contours : the labels_mask size should be equal "
"to the levels/labels size: levels",
len(levels), "labels_mask :", len(labels_mask))
self.clabels_mask = labels_mask[idx_levels]
if array_contours is None:
self.tab_contours_is_image = True
if type(kwargs['levels']) is int:
self.nb_contours = kwargs['levels']
del kwargs['levels']
else:
self.nb_contours = len(kwargs['levels'])
self.levels = kwargs['levels']
del kwargs['levels']
liste_intersect: list[str] = ['alpha0', 'vmin', 'vmax', 'norm']
# if "colors" not in kwargs:
# liste_intersect.append("cmap")
for p in liste_intersect:
if p in self.param_image:
self.param_contours[p] = self.param_image[p]
self.param_contours.update(kwargs)
else:
self.array_contours = array_contours
self.tab_contours_is_image = False
self.x_axe_contours = x_axe
self.y_axe_contours = y_axe
self.param_contours = kwargs
[docs]
def polygon(self, ind, alpha: float | np.double = 0.7, facecolor: str = 'C3', plot_borders: bool = True,
axis_config: str = "bl", **kwargs) -> None:
"""
Plot a uniformly colored polygon
Parameters
----------
ind
2-dimensional array/list of the coordinate of the polygon characteristics points
ind[:, 0] point's abscissas
ind[:, 1] point's ordinate
alpha
transparency (between 0 and 1, default 0.7)
facecolor
Polygon's color
plot_borders
If True (default) plot a line at the polygon's border
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
Extras arguments for matplotlib.patches.PathPatch
Returns
-------
None
See Also
--------
matplotlib.patches.PathPatch
Use to draw the polygon
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
kwargs["axis_config"] = axis_config
self.index_polygons.append(ind)
kwargs["alpha"] = alpha
kwargs['facecolor'] = facecolor
if plot_borders and "edgecolor" not in kwargs.keys():
kwargs['edgecolor'] = facecolor
self.param_polygons.append(kwargs)
[docs]
def config_ax(self, axis: str = "bl", **kwargs) -> None:
"""
Additionals configurations for ax
Parameters
----------
axis : str, optional, {"bl", "tl", "br", "tr", "all"}, default="bl"
The positions of x-y axis to config:
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
- "all" will configurate aull axis
kwargs
Keywords available (see matplotlib documentation):
- ```sharex```, ```sharey``` Axes, optional
The x- or y-axis isshared with the x- or y-axis in the input Axes.
Note that it is not possible to unshare axes.
- ```frameonbool``` : default=True
Whether the Axes frame is visible.
- ```box_aspect``` : float, optional
Set a fixed aspect for the Axes box,
i.e. the ratio of height to width. See set_box_aspect for details.
- ```forward_navigation_events``` : bool or "auto", default: "auto"
Control whether pan/zoom events are passed through to Axes below this one. "auto" is True for axes with an
invisible patch and False otherwise.
- Other optional keyword arguments:
-- adjustable {'box', 'datalim'}
-- agg_filter : a filter function, which takes a (m, n, 3) float array and a dpi value, and returns
a (m, n, 3) array and two offsets from the bottom left corner of the image
-- alpha : scalar or None
-- anchor : (float, float) or {'C', 'SW', 'S', 'SE', 'E', 'NE', ...}
-- animated : bool
-- aspect : {'auto', 'equal'} or float
-- autoscale_on : bool
-- autoscalex_on
-- autoscaley_on
-- axes_locator : Callable[[Axes, Renderer], Bbox]
-- axisbelow : bool or 'line'
-- box_aspect : float or None
-- clip_on : bool
-- facecolor or fc : color
-- figure : Figure
-- forward_navigation_events : bool or "auto"
-- frame_on : bool
-- gid : str
-- in_layout : bool
-- label : object
-- mouseover : bool
-- navigate : bool
-- navigate_mode
-- picker : None or bool or float
-- position : [left, bottom, width, height]
-- rasterization_zorder : float or None
-- rasterized : bool
-- sketch_params : (scale: float, length: float, randomness: float)
-- snap : bool or None
-- subplotspec
-- title : str
-- url : str
-- visible : bool
-- xbound : (lower: float, upper: float)
-- xlabel : str
-- xlim : (left: float, right: float)
-- xmargin : float greater than -0.5
-- xscale
-- xticklabels
-- xticks
-- ybound : (lower: float, upper: float)
-- ylabel : str
-- ylim : (bottom: float, top: float)
-- ymargin : float greater than -0.5
-- yscale
-- yticklabels
-- yticks
-- zorder : float
Returns
-------
None
See Also
--------
matplotlib.axes.set
The function used with kwargs
"""
if 'xticks' in kwargs:
if axis == "bl" or axis == "all":
self.x_axe[0] = np.array(kwargs['xticks'])
if axis == "tl" or axis == "all":
self.x_axe[1] = np.array(kwargs['xticks'])
if axis == "tr" or axis == "all":
self.x_axe[2] = np.array(kwargs['xticks'])
if axis == "br" or axis == "all":
self.x_axe[3] = np.array(kwargs['xticks'])
del kwargs['xticks']
if 'yticks' in kwargs:
if axis == "bl" or axis == "all":
self.y_axe[0] = np.array(kwargs['yticks'])
if axis == "tl" or axis == "all":
self.y_axe[1] = np.array(kwargs['yticks'])
if axis == "tr" or axis == "all":
self.y_axe[2] = np.array(kwargs['yticks'])
if axis == "br" or axis == "all":
self.y_axe[3] = np.array(kwargs['yticks'])
del kwargs['yticks']
if 'xticklabels' in kwargs:
if axis == "bl" or axis == "all":
self.labels_x_ticks[0] = np.array(kwargs['xticklabels'])
if axis == "tl" or axis == "all":
self.labels_x_ticks[1] = np.array(kwargs['xticklabels'])
if axis == "tr" or axis == "all":
self.labels_x_ticks[2] = np.array(kwargs['xticklabels'])
if axis == "br" or axis == "all":
self.labels_x_ticks[3] = np.array(kwargs['xticklabels'])
del kwargs['xticklabels']
if "yticklabels" in kwargs:
if axis == "bl" or axis == "all":
self.labels_y_ticks[0] = np.array(kwargs['yticklabels'])
if axis == "tl" or axis == "all":
self.labels_y_ticks[1] = np.array(kwargs['yticklabels'])
if axis == "tr" or axis == "all":
self.labels_y_ticks[2] = np.array(kwargs['yticklabels'])
if axis == "br" or axis == "all":
self.labels_y_ticks[3] = np.array(kwargs['yticklabels'])
del kwargs['yticklabels']
if "Figure" in kwargs:
self.fig = kwargs["Figure"]
del kwargs["Figure"]
if "title" in kwargs:
self.title = kwargs["title"]
del kwargs["title"]
if (axis == "bl") | (axis == "all"):
self.param_ax.update(kwargs)
if (axis == "tl") | (axis == "all"):
self.param_ax_tl.update(kwargs)
if (axis == "tr") | (axis == "all"):
self.param_ax_tr.update(kwargs)
if (axis == "br") | (axis == "all"):
self.param_ax_br.update(kwargs)
[docs]
def config_ticks(self, axis: str = "bl", direction: str = "both",**kwargs) -> None:
"""
Additionals configurations for ax
Parameters
----------
axis : str, optional, {"bl", "tl", "br", "tr", "all"}, default="bl"
The positions of x-y axis to config:
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
- "all" will configurate aull axis
direction : str, optional, {"x", "y", "both"}, default="both":
The axis direction where ticks are configurated
kwargs
Keywords available (see matplotlib documentation):
- ```sharex```, ```sharey``` Axes, optional
The x- or y-axis isshared with the x- or y-axis in the input Axes.
Note that it is not possible to unshare axes.
- ```frameonbool``` : default=True
Whether the Axes frame is visible.
- ```box_aspect``` : float, optional
Set a fixed aspect for the Axes box,
i.e. the ratio of height to width. See set_box_aspect for details.
- ```forward_navigation_events``` : bool or "auto", default: "auto"
Control whether pan/zoom events are passed through to Axes below this one. "auto" is True for axes with an
invisible patch and False otherwise.
- Other optional keyword arguments:
-- adjustable {'box', 'datalim'}
-- agg_filter : a filter function, which takes a (m, n, 3) float array and a dpi value, and returns
a (m, n, 3) array and two offsets from the bottom left corner of the image
-- alpha : scalar or None
-- anchor : (float, float) or {'C', 'SW', 'S', 'SE', 'E', 'NE', ...}
-- animated : bool
-- aspect : {'auto', 'equal'} or float
-- autoscale_on : bool
-- autoscalex_on
-- autoscaley_on
-- axes_locator : Callable[[Axes, Renderer], Bbox]
-- axisbelow : bool or 'line'
-- box_aspect : float or None
-- clip_on : bool
-- facecolor or fc : color
-- figure : Figure
-- forward_navigation_events : bool or "auto"
-- frame_on : bool
-- gid : str
-- in_layout : bool
-- label : object
-- mouseover : bool
-- navigate : bool
-- navigate_mode
-- picker : None or bool or float
-- position : [left, bottom, width, height]
-- rasterization_zorder : float or None
-- rasterized : bool
-- sketch_params : (scale: float, length: float, randomness: float)
-- snap : bool or None
-- subplotspec
-- title : str
-- url : str
-- visible : bool
-- xbound : (lower: float, upper: float)
-- xlabel : str
-- xlim : (left: float, right: float)
-- xmargin : float greater than -0.5
-- xscale
-- xticklabels
-- xticks
-- ybound : (lower: float, upper: float)
-- ylabel : str
-- ylim : (bottom: float, top: float)
-- ymargin : float greater than -0.5
-- yscale
-- yticklabels
-- yticks
-- zorder : float
Returns
-------
None
See Also
--------
matplotlib.axes.set
The function used with kwargs
"""
if (axis == "bl") | (axis == "all"):
if direction == "x" or direction == "both":
self.ticks_param_ax[0].update(kwargs)
if direction == "y" or direction == "both":
self.ticks_param_ax[1].update(kwargs)
if (axis == "tl") | (axis == "all"):
if direction == "x" or direction == "both":
self.ticks_param_ax_tl[0].update(kwargs)
if direction == "y" or direction == "both":
self.ticks_param_ax_tl[1].update(kwargs)
if (axis == "tr") | (axis == "all"):
if direction == "x" or direction == "both":
self.ticks_param_ax_tr[0].update(kwargs)
if direction == "y" or direction == "both":
self.ticks_param_ax_tr[1].update(kwargs)
if (axis == "br") | (axis == "all"):
if direction == "x" or direction == "both":
self.ticks_param_ax_br[0].update(kwargs)
if direction == "y" or direction == "both":
self.ticks_param_ax_br[1].update(kwargs)
[docs]
def config_spines(self, spine: str | list[str] | np.ndarray[str]= "all", axis: str = "bl", **kwargs) -> None:
"""
Additionals configurations for ax
Parameters
----------
spine : str, optional, {"top", "bottom", "left", "right", "all"}:
The spine to be configurated
axis : str, optional, {"bl", "tl", "br", "tr", "all"}, default="bl"
The positions of x-y axis to config:
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
- "all" will configurate aull axis
kwargs
Keywords available (see matplotlib documentation):
- ```sharex```, ```sharey``` Axes, optional
The x- or y-axis isshared with the x- or y-axis in the input Axes.
Note that it is not possible to unshare axes.
- ```frameonbool``` : default=True
Whether the Axes frame is visible.
- ```box_aspect``` : float, optional
Set a fixed aspect for the Axes box,
i.e. the ratio of height to width. See set_box_aspect for details.
- ```forward_navigation_events``` : bool or "auto", default: "auto"
Control whether pan/zoom events are passed through to Axes below this one. "auto" is True for axes with an
invisible patch and False otherwise.
- Other optional keyword arguments:
-- adjustable {'box', 'datalim'}
-- agg_filter : a filter function, which takes a (m, n, 3) float array and a dpi value, and returns
a (m, n, 3) array and two offsets from the bottom left corner of the image
-- alpha : scalar or None
-- anchor : (float, float) or {'C', 'SW', 'S', 'SE', 'E', 'NE', ...}
-- animated : bool
-- aspect : {'auto', 'equal'} or float
-- autoscale_on : bool
-- autoscalex_on
-- autoscaley_on
-- axes_locator : Callable[[Axes, Renderer], Bbox]
-- axisbelow : bool or 'line'
-- box_aspect : float or None
-- clip_on : bool
-- facecolor or fc : color
-- figure : Figure
-- forward_navigation_events : bool or "auto"
-- frame_on : bool
-- gid : str
-- in_layout : bool
-- label : object
-- mouseover : bool
-- navigate : bool
-- navigate_mode
-- picker : None or bool or float
-- position : [left, bottom, width, height]
-- rasterization_zorder : float or None
-- rasterized : bool
-- sketch_params : (scale: float, length: float, randomness: float)
-- snap : bool or None
-- subplotspec
-- title : str
-- url : str
-- visible : bool
-- xbound : (lower: float, upper: float)
-- xlabel : str
-- xlim : (left: float, right: float)
-- xmargin : float greater than -0.5
-- xscale
-- xticklabels
-- xticks
-- ybound : (lower: float, upper: float)
-- ylabel : str
-- ylim : (bottom: float, top: float)
-- ymargin : float greater than -0.5
-- yscale
-- yticklabels
-- yticks
-- zorder : float
Returns
-------
None
See Also
--------
matplotlib.axes.set
The function used with kwargs
"""
if (axis == "bl") | (axis == "all"):
if (isinstance(spine, str) and (spine == "bottom" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("bottom" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "bottom")[0, 0]]
self.param_spines_ax[0].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "left" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("left" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "left")[0, 0]]
self.param_spines_ax[1].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "top" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("top" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "top")[0, 0]]
self.param_spines_ax[2].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "right" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("right" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "right")[0, 0]]
self.param_spines_ax[3].update(kwargs_loc)
if (axis == "tl") | (axis == "all"):
if (isinstance(spine, str) and (spine == "bottom" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("bottom" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "bottom")[0, 0]]
self.param_spines_ax_tl[0].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "left" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("left" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "left")[0, 0]]
self.param_spines_ax_tl[1].update(kwargs)
if (isinstance(spine, str) and (spine == "top" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("top" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "top")[0, 0]]
self.param_spines_ax_tl[2].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "right" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("right" in spine or "all" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "right")[0, 0]]
self.param_spines_ax_tl[3].update(kwargs_loc)
if (axis == "tr") | (axis == "all"):
if (isinstance(spine, str) and (spine == "bottom" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("bottom" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "bottom")[0, 0]]
self.param_spines_ax_tr[0].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "left" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("left" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "left")[0, 0]]
self.param_spines_ax_tr[1].update(kwargs)
if (isinstance(spine, str) and (spine == "top" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("top" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "top")[0, 0]]
self.param_spines_ax_tr[2].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "right" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("right" in spine or "all" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "right")[0, 0]]
self.param_spines_ax_tr[3].update(kwargs_loc)
if (axis == "br") | (axis == "all"):
if (isinstance(spine, str) and (spine == "bottom" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("bottom" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "bottom")[0, 0]]
self.param_spines_ax_br[0].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "left" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("left" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "left")[0, 0]]
self.param_spines_ax_br[1].update(kwargs)
if (isinstance(spine, str) and (spine == "top" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("top" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "top")[0, 0]]
self.param_spines_ax_br[2].update(kwargs_loc)
if (isinstance(spine, str) and (spine == "right" or spine == "all")
or (isinstance(spine, list | np.ndarray) and ("right" in spine or "all" in spine))):
kwargs_loc: dict = kwargs.copy()
if isinstance(spine, list | np.ndarray):
for k in kwargs_loc.keys():
if isinstance(kwargs_loc[k], list | np.ndarray) and len(kwargs_loc[k]) == len(spine):
kwargs_loc[k] = kwargs_loc[k][np.argwhere(np.array(spine) == "right")[0, 0]]
self.param_spines_ax_br[3].update(kwargs_loc)
[docs]
def config_legende(self, **kwargs) -> None:
"""
To set additionals parameters for the legend plotting
Parameters
----------
kwargs
additionals parameters for the legend
(see https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html)
- locstr default: rcParams["legend.loc"] (default: 'best') The location of the legend.
The strings 'upper left', 'upper right', 'lower left', 'lower right' place the legend at
the corresponding corner of the axes.
The strings 'upper center', 'lower center', 'center left', 'center right' place the
legend at the center of the corresponding edge of the axes.
The string 'center' places the legend at the center of the axes.
The string 'best' places the legend at the location, among the nine locations defined so far, with the
minimum overlap with other drawn artists. This option can be quite slow for plots with large amounts
of data; your plotting speed may benefit from providing a specific location.
The location can also be a 2-tuple giving the coordinates of the lower-left corner of the legend in
axes coordinates (in which case bbox_to_anchor will be ignored).
For back-compatibility, 'center right' (but no other location) can also be spelled 'right', and each
"string" location can also be given as a numeric value:
- bbox_to_anchorBboxBase, 2-tuple, or 4-tuple of floats
Box that is used to position the legend in conjunction with loc.
Defaults to axes.bbox (if called as a method to Axes.legend) or figure.bbox (if Figure.legend).
This argument allows arbitrary placement of the legend.
Bbox coordinates are interpreted in the coordinate system given by bbox_transform, with the default
transform Axes or Figure coordinates, depending on which legend is called.
If a 4-tuple or BboxBase is given, then it specifies the bbox (x, y, width, height) that the legend is
placed in. To put the legend in the best location in the bottom right quadrant of the Axes (or figure):
- loc='best', bbox_to_anchor=(0.5, 0., 0.5, 0.5)
A 2-tuple (x, y) places the corner of the legend specified by loc at x, y. For example,
to put the legend's upper right-hand corner in the center of the Axes (or figure)
the following keywords can be used: loc='upper right', bbox_to_anchor=(0.5, 0.5)
- ncolsint, default: 1
The number of columns that the legend has.
For backward compatibility, the spelling ncol is also supported but it is discouraged.
If both are given, ncols takes precedence.
- fontsize : int or {'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'}
The font size of the legend. If the value is numeric the size will be the absolute font size in points.
String values are relative to the current default font size. This argument is only used if prop
is not specified.
- labelcolor : str or list, default: rcParams["legend.labelcolor"] (default: 'None')
The color of the text in the legend. Either a valid color string (for example, 'red'),
or a list of color strings. The labelcolor can also be made to match the color of the line or marker using
'linecolor', 'markerfacecolor' (or 'mfc'), or 'markeredgecolor' (or 'mec').
Labelcolor can be set globally using rcParams["legend.labelcolor"] (default: 'None').
If None, use rcParams["text.color"] (default: 'black').
- numpointsint, default: rcParams["legend.numpoints"] (default: 1)
The number of marker points in the legend when creating a legend entry for a Line2D (line).
- scatterpointsint, default: rcParams["legend.scatterpoints"] (default: 1)
The number of marker points in the legend when creating a legend entry for a PathCollection (scatter plot).
- scatteryoffsets : iterable of floats, default: [0.375, 0.5, 0.3125]
The vertical offset (relative to the font size) for the markers created for a scatter plot legend entry.
0.0 is at the base the legend text, and 1.0 is at the top. To draw all markers at the same height,
set to [0.5].
- markerscalefloat, default: rcParams["legend.markerscale"] (default: 1.0)
The relative size of legend markers compared to the originally drawn ones.
- markerfirstbool, default: True If True, legend marker is placed to the left of the legend label.
If False, legend marker is placed to the right of the legend label.
- reversebool, default: False If True, the legend labels are displayed in reverse order from the input.
If False, the legend labels are displayed in the same order as the input.
Added in version 3.7.
- frameonbool, default: rcParams["legend.frameon"] (default: True)
Whether the legend should be drawn on a patch (frame).
- fancyboxbool, default: rcParams["legend.fancybox"] (default: True)
Whether round edges should be enabled around the FancyBboxPatch which makes up the legend's background.
- shadowNone, bool or dict, default: rcParams["legend.shadow"] (default: False)
Whether to draw a shadow behind the legend. The shadow can be configured using Patch keywords.
Customization via rcParams["legend.shadow"] (default: False) is currently not supported.
- framealpha float, default: rcParams["legend.framealpha"] (default: 0.8)
The alpha transparency of the legend's background. If shadow is activated and framealpha is None,
the default value is ignored.
- facecolor "inherit" or color, default: rcParams["legend.facecolor"] (default: 'inherit')
The legend's background color. If "inherit", use rcParams["axes.facecolor"] (default: 'white').
- edgecolor "inherit" or color, default: rcParams["legend.edgecolor"] (default: '0.8')
The legend's background patch edge color. If "inherit", use rcParams["axes.edgecolor"] (default: 'black').
- mode : {"expand", None}
If mode is set to "expand" the legend will be horizontally expanded to fill the Axes area
(or bbox_to_anchor if defines the legend's size).
- bbox_transformNone or Transform The transform for the bounding box (bbox_to_anchor).
For a value of None (default) the Axes' transAxes transform will be used.
- titlestr or None : The legend's title. Default is no title (None).
- title_fontproperties : None or FontProperties or dict
The font properties of the legend's title. If None (default), the title_fontsize argument will be used
if present; if title_fontsize is also None, the current rcParams["legend.title_fontsize"]
(default: None) will be used.
- title_fontsize int or {'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'},
default: rcParams["legend.title_fontsize"] (default: None)
The font size of the legend's title. Note: This cannot be combined with title_fontproperties.
If you want to set the fontsize alongside other font properties, use the size parameter
in title_fontproperties.
- alignment{'center', 'left', 'right'}, default: 'center'
The alignment of the legend title and the box of entries. The entries are aligned as a single block,
so that markers always lined up.
- borderpad float, default: rcParams["legend.borderpad"] (default: 0.4)
The fractional whitespace inside the legend border, in font-size units.
- labelspacing float, default: rcParams["legend.labelspacing"] (default: 0.5)
The vertical space between the legend entries, in font-size units.
- handlelength float, default: rcParams["legend.handlelength"] (default: 2.0)
The length of the legend handles, in font-size units.
- handleheight float, default: rcParams["legend.handleheight"] (default: 0.7)
The height of the legend handles, in font-size units.
- handletextpad float, default: rcParams["legend.handletextpad"] (default: 0.8)
The pad between the legend handle and text, in font-size units.
- borderaxespad float, default: rcParams["legend.borderaxespad"] (default: 0.5)
The pad between the Axes and legend border, in font-size units.
- columnspacing float, default: rcParams["legend.columnspacing"] (default: 2.0)
The spacing between columns, in font-size units.
- draggablebool, default: False
Whether the legend can be dragged with the mouse.
Returns
-------
None
See Also
--------
matplotlib.pyplot.legend
"""
self.param_legende.update(kwargs)
[docs]
def config_labels_contours(self, **kwargs) -> None:
"""
Additionals configurations for the contours labels
Parameters
----------
kwargs
- fontsize str or float, default: rcParams["font.size"] (default: 10.0)
Size in points or relative size e.g., 'smaller', 'x-large'.
See plt.Text.set_size for accepted string values.
- colorscolor or colors or None, default: None
The label colors:
If None, the color of each label matches the color of the corresponding contour.
If one string color, e.g., colors = 'r' or colors = 'red', all labels will be plotted in this color.
If a tuple of colors (string, float, RGB, etc), different labels will be plotted in different
colors in the order specified.
- inline: bool, default: True
If True the underlying contour is removed where the label is placed.
- inline_spacing: float, default: 5
Space in pixels to leave on each side of label when placing inline.
This spacing will be exact for labels at locations where the contour is straight, less so for labels on
curved contours.
- fmt: str, optional
How the levels are formatted: it is interpreted as a %-style format string.
The default is to use a standard ScalarFormatter.
- manual: bool or iterable, default: False
If True, contour labels will be placed manually using mouse clicks. Click the first button near a
contour to add a label, click the second button (or potentially both mouse buttons at once) to finish
adding labels. The third button can be used to remove the last label added, but only if labels are not
inline. Alternatively, the keyboard can be used to select label locations (enter to end label
placement, delete or backspace act like the third mouse button, and any other key will select a label
location).
manual can also be an iterable object of (x, y) tuples. Contour labels will be created as if mouse is
clicked at each (x, y) position.
- rightside_up: bool, default: True
If True, label rotations will always be plus or minus 90 degrees from level.
- use_clabel: text :bool, default: False
If True, use Text.set_transform_rotates_text to ensure that label rotation is updated whenever the Axes
aspect changes.
- zorder: float or None, default: (2 + contour.get_zorder())
zorder of the contour labels.
Returns
-------
None
See Also
--------
matplotlib.axes.Axes.clabel
"""
self.param_labels_contours.update(kwargs)
[docs]
def config_fig(self, **kwargs) -> None:
"""
Additionnals parameters to configure the Figure
Parameters
----------
kwargs
- figsize2 : tuple of floats, default: rcParams["figure.figsize"] (default: [6.4, 4.8])
Figure dimension (width, height) in inches.
- dpi float, default: rcParams["figure.dpi"] (default: 100.0)
Dots per inch.
- facecolor default: rcParams["figure.facecolor"] (default: 'white')
The figure patch facecolor.
- edgecolor default: rcParams["figure.edgecolor"] (default: 'white')
The figure patch edge color.
- linewidthfloat
The linewidth of the frame (i.e. the edge linewidth of the figure patch).
- frameonbool, default: rcParams["figure.frameon"] (default: True)
If False, suppress drawing the figure background patch.
- layout {'constrained', 'compressed', 'tight', 'none', LayoutEngine, None}, default: None
The layout mechanism for positioning of plot elements to avoid overlapping Axes decorations
(labels, ticks, etc). Note that layout managers can have significant performance penalties.
'constrained': The constrained layout solver adjusts Axes sizes to avoid overlapping Axes decorations.
Can handle complex plot layouts and colorbars, and is thus recommended.
See Constrained layout guide for examples.
'compressed': uses the same algorithm as 'constrained', but removes extra space between
fixed-aspect-ratio Axes. Best for simple grids of Axes.
'tight': Use the tight layout mechanism. This is a relatively simple algorithm that adjusts the subplot
parameters so that decorations do not overlap.
See Tight layout guide for examples.
'none': Do not use a layout engine.
A LayoutEngine instance. Builtin layout classes are ConstrainedLayoutEngine and TightLayoutEngine,
more easily accessible by 'constrained' and 'tight'. Passing an instance allows third parties to
provide their own layout engine.
If not given, fall back to using the parameters tight_layout and constrained_layout, including their config
defaults rcParams["figure.autolayout"] (default: False) and rcParams["figure.constrained_layout.use"]
(default: False).
- alpha scalar or None
- animated bool
- clip_on bool
- constrained_layout unknown
- constrained_layout_pads unknown
- dpi float
- edgecolor color
- facecolor color
- figheight float
- figwidth float
- frameon bool
- gid str
- in_layout bool
- layout_engine {'constrained', 'compressed', 'tight', 'none', LayoutEngine, None}
- linewidth number
- mouseover bool
- picker None or bool or float or callable
- rasterized bool
- size_inches (float, float) or float
- sketch_params (scale: float, length: float, randomness: float)
- snap bool or None
- tight_layout
- url str
- visible bool
- zorder float
Returns
-------
None
See Also
--------
matplotlib.pyplot.Figure
"""
self.param_fig.update(kwargs)
[docs]
def config_enrg_fig(self, **kwargs) -> None:
"""
Additionals parameters for the Figure saving
Parameters
----------
kwargs
- figsize 2-tuple of floats, default: rcParams["figure.figsize"] (default: [6.4, 4.8])
Figure dimension (width, height) in inches.
- dpi float, default: rcParams["figure.dpi"] (default: 100.0)
Dots per inch.
- facecolor default: rcParams["figure.facecolor"] (default: 'white')
The figure patch facecolor.
- edgecolor default: rcParams["figure.edgecolor"] (default: 'white')
The figure patch edge color.
- linewidth float
The linewidth of the frame (i.e. the edge linewidth of the figure patch).
- frameon bool, default: rcParams["figure.frameon"] (default: True)
If False, suppress drawing the figure background patch.
- layout {'onstrained', 'compressed', 'tight', 'none', LayoutEngine, None}, default: None
The layout mechanism for positioning of plot elements to avoid overlapping Axes decorations
(labels, ticks, etc). Note that layout managers can have significant performance penalties.
'constrained': The constrained layout solver adjusts Axes sizes to avoid overlapping Axes
decorations. Can handle complex plot layouts and colorbars, and is thus recommended.
See Constrained layout guide for examples.
'compressed': uses the same algorithm as 'constrained', but removes extra space between
fixed-aspect-ratio Axes. Best for simple grids of Axes.
'tight': Use the tight layout mechanism. This is a relatively simple algorithm that adjusts the
subplot parameters so that decorations do not overlap.
See Tight layout guide for examples.
'none': Do not use a layout engine.
A LayoutEngine instance. Builtin layout classes are ConstrainedLayoutEngine and TightLayoutEngine,
more easily accessible by 'constrained' and 'tight'. Passing an instance allows third parties to
provide their own layout engine.
If not given, fall back to using the parameters tight_layout and constrained_layout, including their
config defaults rcParams["figure.autolayout"] (default: False) and
rcParams["figure.constrained_layout.use"] (default: False).
- alpha scalar or None
- animated bool
- clip_on bool
- constrained_layout unknown
- constrained_layout_pads unknown
- dpi float
- edgecolor color
- facecolor color
- figheight float
- figwidth float
- frameon bool
- gid str
- in_layout bool
- label object
- layout_engine {'constrained', 'compressed', 'tight', 'none', LayoutEngine, None}
- linewidth number
- mouseover bool
- picker None or bool or float
- rasterized bool
- size_inches (float, float) or float
- sketch_params (scale: float, length: float, randomness: float)
- snap bool or None
- tight_layout unknown
- transform Transform
- url str
- visible bool
- zorder float
Returns
-------
None
See Also
--------
matplotlib.figure.Figure.savefig
"""
self.param_enrg_fig.update(kwargs)
[docs]
def config_font(self, **kwargs) -> None:
"""
Global font parameter
Parameters
----------
kwargs
'family' : 'fantasy','monospace','sans-serif','serif','cursive'
'styles' : 'normal', 'italic', 'oblique'
'size' : numerical value
'variants' : 'normal', 'small-caps'
'weight' : 'light', 'normal', 'medium', 'semibold', 'bold', 'heavy', 'black'
Returns
-------
"""
k: list[str] = kwargs.keys()
vals: list = kwargs.values()
kwargs: dict = {}
for K, L in zip(k, vals):
if "font." not in K:
kwargs['font.' + K] = L
else:
kwargs[K] = L
self.param_font.update(kwargs)
[docs]
def config_colorbar(self, index_colorbar: int = ii_max, ticks: list | np.ndarray | None = None,
**kwargs) -> None:
"""
Colorbar additianal parameter
Parameters
----------
index_colorbar : int, optional
The index of the colorbar (default the parameters are added for all colorbars)
ticks : list[float] | array_like
The colorbar's ticks. If None, ticks are determined automatically from the input.
kwargs
the parameter dictionary
Returns
-------
None
"""
if index_colorbar == ii_max:
for d in self.param_colorbar:
d.update(kwargs)
if ticks is not None and len(ticks) > 0:
self.ticks_colorbar = [ticks for t in self.ticks_colorbar]
elif ticks is not None:
self.ticks_colorbar = [[-np.inf] for t in self.ticks_colorbar]
else:
if ticks is not None and len(ticks) > 0:
self.ticks_colorbar[index_colorbar] = ticks
elif ticks is not None:
self.ticks_colorbar[index_colorbar] = [-np.inf]
self.param_colorbar[index_colorbar].update(kwargs)
[docs]
def config_line(self, index_line: int = ii_max, hide: bool = False, **kwargs) -> None:
"""
Colorbar additianal parameter
Parameters
----------
index_line : int, optional
The index of the line (default the parameters are added for all liness)
hide : bool, optional, default: False
To hide the line(s)
kwargs
the parameter dictionary
Returns
-------
None
"""
if index_line == ii_max:
if hide:
self.indexs_plot_lines = []
else:
new_indexs_to_plot: list = list(set(list(np.arange(len(self.lines_x)))) - set(self.indexs_plot_lines))
new_indexs_to_plot.sort()
self.indexs_plot_lines.extend(new_indexs_to_plot)
for d in self.param_lines:
d.update(kwargs)
elif isinstance(index_line, int | np.int64) and index_line >= len(self.param_lines):
raise UserWarning("Graphique.config_line : the maximum index awalible for lines is ", len(self.param_lines) - 1, index_line, "is to high")
elif isinstance(index_line, list | np.ndarray):
if isinstance(index_line[0], bool):
if len(index_line) != len(self.param_lines):
raise UserWarning("Graphique.config_line : the size of the mask array should be equal to the sze of Graphique.param_lines")
for i in range(len(index_line)):
if index_line[i]:
self.param_lines[i].update(kwargs)
if hide and i in self.indexs_plot_lines:
self.indexs_plot_lines.remove(i)
elif not hide and i not in self.indexs_plot_lines:
self.indexs_plot_lines.append(i)
else:
if np.any(np.array(index_line) >= len(self.param_lines)):
raise UserWarning("Graphique.config_line : there is at least one index higher"
" than the maximum index")
for i in index_line:
if i < len(self.param_lines):
raise UserWarning("The index ", index_line, "is not compatibe with a line liste of size ",
len(self.param_lines))
if i < 0:
i = len(self.param_lines) + i
self.param_lines[i].update(kwargs)
if hide and i in self.indexs_plot_lines:
self.indexs_plot_lines.remove(i)
elif not hide and i not in self.indexs_plot_lines:
self.indexs_plot_lines.append(i)
else:
if index_line <= - len(self.param_lines):
raise UserWarning("The index ", index_line, "is not compatibe with a line liste of size ",
len(self.param_lines))
if index_line < 0:
index_line = len(self.param_lines) + index_line
if hide and index_line in self.param_lines:
self.indexs_plot_lines.remove(index_line)
elif not hide and index_line not in self.indexs_plot_lines:
self.indexs_plot_lines.append(index_line)
self.param_lines[index_line].update(kwargs)
[docs]
def set_style_phenigraph(self) -> None:
"""
This method add a trensparent grey background for the axis self.ax and a trensparent background for the rest of
the Figure.
The top and right border (spine) of the axis are remouved
The linewidth of the left and below border (where the defaults x and -y axis are) are set to 2
The ticks size and width are increase too
Returns
-------
"""
self.config_ax(facecolor=(180 / 255, 180 / 255, 200 / 255, 0.1))
self.config_spines(spine=["top", "right"], visible=False) # Remouving the top and right limit of the plot
self.config_spines(spine=["bottom", "left"],
lw=2) # Setting the lineweight of the remaing borders of the figure to 2
self.config_ticks(width=2, length=6) # Setting the ticks width and length
self.config_fig(facecolor=Ctrensp) # Setting a trensparent background for the rest of the figure
[docs]
def set_style_matplotlib(self) -> None:
"""
This method reset the default matplotlib style
Returns
-------
"""
if 'facecolor' in self.param_ax:
del self.param_ax['facecolor']
if 'facecolor' in self.param_fig:
del self.param_fig['facecolor']
self.param_spines_ax = [{}, {}, {}, {}]
self.ticks_param_ax = {}
[docs]
def dark_background(self) -> None:
"""
Put a dark background on the figure
Returns
-------
None
"""
self.style = 'dark_background'
for d in self.param_lines:
if "color" in d.keys() and (isinstance(d["color"], str) and d["color"] == "k"):
d["color"] = "w"
for d in self.param_contours:
if "color" in d.keys() and (isinstance(d["color"], str) and d["color"] == "k"):
d["color"] = "w"
for d in self.param_polygons:
if "facecolor" in d.keys() and (isinstance(d["color"], str) and d["color"] == "k"):
d["facecolor"] = "w"
[docs]
def default_style(self) -> None:
"""
Use default style
Returns
-------
None
"""
self.style = 'default'
# for d in self.param_lines:
# if "color" in d.keys() and (isinstance(d["color"], str) and d["color"] == "w"):
# d["color"] = "k"
# if "colors" in self.param_contours.keys():
# for i in range(len(self.param_contours["colors"])):
# if (isinstance(self.param_contours["colors"][i], str)
# and self.param_contours["colors"][i] == "w"):
# self.param_contours["colors"] = "k"
# for d in self.param_polygons:
# if "facecolor" in d.keys() and d["facecolor"] == "w":
# d["facecolor"] = "k"
[docs]
def plot_colorbar(self) -> None:
"""
Plot the custom colorbar(s) if it(they) exists
Returns
-------
None
"""
if self.custum_colorbar_colors is not None:
# share_axis: np.array[int] = np.full(len(self.custum_colorbar_colors), -1)
right: list[int] = []
sr: np.float64 = 0.
top: list[int] = []
st: np.float64 = 0.
left: list[int] = []
sl: np.float64 = 0.
bottom: list[int] = []
sb: np.float64 = 0.
size_colorbar: np.float64 = 0.02
size_legend: np.float64 = 10 * size_colorbar
size_space: np.float64 = 0.
for i in range(len(self.custum_colorbar_colors)):
if "hide" not in self.param_colorbar[i] or not self.param_colorbar[i]["hide"]:
if "location" not in self.param_colorbar[i] or self.param_colorbar[i]["location"] == "right":
right.append(i)
if len(right) == 1:
self.param_colorbar[i]["share_axis"] = True
if "size" in self.param_colorbar[i].keys():
sr += self.param_colorbar[i]["size"]
else:
sr += size_colorbar
if ("share_axis" not in self.param_colorbar[i].keys()
or not self.param_colorbar[i]["share_axis"]):
if "size_legend" in self.param_colorbar[i].keys():
sr += self.param_colorbar[i]["size_legend"]
elif "size" in self.param_colorbar[i].keys():
sr += self.param_colorbar[i]["size"] * size_legend / size_colorbar
else:
sr += size_legend
if "space_between" in self.param_colorbar[i].keys():
sr += self.param_colorbar[i]["space_between"]
else:
sr += size_space
elif self.param_colorbar[i]["location"] == "top":
top.append(i)
if len(top) == 1:
self.param_colorbar[i]["share_axis"] = True
if "size" in self.param_colorbar[i].keys():
st += self.param_colorbar[i]["size"]
else:
st += size_colorbar
if ("share_axis" not in self.param_colorbar[i].keys()
or not self.param_colorbar[i]["share_axis"]):
if "size_legend" in self.param_colorbar[i].keys():
st += self.param_colorbar[i]["size_legend"]
elif "size" in self.param_colorbar[i].keys():
st += self.param_colorbar[i]["size"] * size_legend / size_colorbar
else:
st += size_legend
if "space_between" in self.param_colorbar[i].keys():
st += self.param_colorbar[i]["space_between"]
else:
st += size_space
elif self.param_colorbar[i]["location"] == "left":
left.append(i)
if len(left) == 1:
self.param_colorbar[i]["share_axis"] = True
if "size" in self.param_colorbar[i].keys():
sl += self.param_colorbar[i]["size"]
else:
sl += size_colorbar
if ("share_axis" not in self.param_colorbar[i].keys()
or not self.param_colorbar[i]["share_axis"]):
if "size_legend" in self.param_colorbar[i].keys():
sl += self.param_colorbar[i]["size_legend"]
elif "size" in self.param_colorbar[i].keys():
sl += self.param_colorbar[i]["size"] * size_legend / size_colorbar
else:
sl += size_legend
if "space_between" in self.param_colorbar[i].keys():
sl += self.param_colorbar[i]["space_between"]
else:
sl += size_space
elif self.param_colorbar[i]["location"] == "bottom":
bottom.append(i)
if len(bottom) == 1:
self.param_colorbar[i]["share_axis"] = True
if "size" in self.param_colorbar[i].keys():
sb += self.param_colorbar[i]["size"]
else:
sb += size_colorbar
if ("share_axis" not in self.param_colorbar[i].keys()
or not self.param_colorbar[i]["share_axis"]):
if "size_legend" in self.param_colorbar[i].keys():
sb += self.param_colorbar[i]["size_legend"]
elif "size" in self.param_colorbar[i].keys():
sb += self.param_colorbar[i]["size"] * size_legend / size_colorbar
else:
sb += size_legend
if "space_between" in self.param_colorbar[i].keys():
sb += self.param_colorbar[i]["space_between"]
else:
sb += size_space
else:
raise UserWarning("Graphique.plot_colorbar : the location ", self.param_colorbar[i]["location"],
"isn't awalible. Please use right, top, left, bottom")
pos_r: np.float64 = 1.
pos_t: np.float64 = 1.
pos_l: np.float64 = 0.
pos_b: np.float64 = 0.
for (i, ii) in zip(right, np.arange(len(right))):
params: dict = self.param_colorbar[i].copy()
if "hide" not in params or not params["hide"]:
cmap = mpl.colors.ListedColormap(self.custum_colorbar_colors[i])
norm = mpl.colors.BoundaryNorm(self.custum_colorbar_values[i], cmap.N)
if "hide" in params:
del params["hide"]
fmt: str = ""
if "format" in params.keys():
fmt = params["format"]
del params["format"]
ticks_labels = None
if "ticks" in params.keys():
self.ticks_colorbar[i] = params["ticks"]
del params["ticks"]
if "ticks_labels" in params.keys():
ticks_labels = params["ticks_labels"]
del params["ticks_labels"]
elif fmt != "" and len(self.ticks_colorbar[i]) != 0 and self.ticks_colorbar[i][0] > - np.inf:
ticks_labels = [fmt.format(x) for x in self.ticks_colorbar[i]]
scale: str = "linear"
if "scale" in params.keys():
scale = params["scale"]
del params["scale"]
share_axis: bool = False
if "share_axis" in params.keys():
share_axis = params["share_axis"]
del params["share_axis"]
if "location" in params.keys():
del params["location"]
fraction: np.float64 = 1
if "fraction" in params.keys():
fraction = params["fraction"]
del params["fraction"]
size_cb: np.float64 = size_colorbar
if "size" in params.keys():
size_cb = params["size"]
del params["size"]
size: np.float64 = size_cb
if not share_axis and "size_legend" in params.keys():
size += params["size_legend"]
del params["size_legend"]
elif not share_axis:
size += size_legend
if "space_between" in params.keys():
size += params["space_between"]
del params["space_between"]
elif not share_axis:
size += size_space
cax = self.ax.inset_axes([pos_r - size, 0.5 - fraction / 2.,
size_cb, fraction])
# cax = self.fig.add_axes([pos_r - size, 0.5 - fraction / 2.,
# size_cb, fraction])
self.axes.append(cax)
pos_r -= size
# cax.set_xticks([])
# cax.set_yticks([])
# cax.set_axis_off()
# if share_axis:
# cax.sharey = self.colorbar[-1].ax
self.colorbar.append(self.fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
cax=cax, **params))
self.cmap.append(cmap)
self.norms.append(norm)
if len(self.ticks_colorbar[i]) == 0 and scale != "linear":
self.colorbar[-1].ax.set_yscale(scale)
elif (ticks_labels is not None and len(self.ticks_colorbar[i]) > 0
and self.ticks_colorbar[i][0] > - np.inf):
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i], labels=ticks_labels)
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] > - np.inf:
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i])
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] == - np.inf:
self.colorbar[-1].set_ticks(ticks=[])
for (i, ii) in zip(top, np.arange(len(right))):
params: dict = self.param_colorbar[i].copy()
if "hide" not in params or not params["hide"]:
cmap = mpl.colors.ListedColormap(self.custum_colorbar_colors[i])
norm = mpl.colors.BoundaryNorm(self.custum_colorbar_values[i], cmap.N)
if "hide" in params:
del params["hide"]
fmt: str = ""
if "format" in params.keys():
fmt = params["format"]
del params["format"]
ticks_labels = None
if "ticks" in params.keys():
self.ticks_colorbar[i] = params["ticks"]
del params["ticks"]
if "ticks_labels" in params.keys():
ticks_labels = params["ticks_labels"]
del params["ticks_labels"]
elif fmt != "" and len(self.ticks_colorbar[i]) != 0 and self.ticks_colorbar[i][0] > - np.inf:
ticks_labels = [fmt.format(x) for x in self.ticks_colorbar[i]]
scale: str = "linear"
if "scale" in params.keys():
scale = params["scale"]
del params["scale"]
share_axis: bool = False
if "share_axis" in params.keys():
share_axis = params["share_axis"]
del params["share_axis"]
if "location" in params.keys():
del params["location"]
fraction: np.float64 = 1.
if "fraction" in params.keys():
fraction = params["fraction"]
del params["fraction"]
size_cb: np.float64 = size_colorbar
if "size" in params.keys():
size_cb = params["size"]
del params["size"]
size: np.float64 = size_cb
if not share_axis and "size_legend" in params.keys():
size += params["size_legend"]
del params["size_legend"]
elif not share_axis:
size += size_legend
if "space_between" in params.keys():
size += params["space_between"]
del params["space_between"]
elif not share_axis:
size += size_space
cax = self.ax.inset_axes([0.5 - fraction / 2., pos_t - size,
fraction, size_cb])
# cax = self.fig.add_axes([0.5 - fraction / 2., pos_t - size,
# fraction, size_cb])
self.axes.append(cax)
pos_t -= size
# cax.set_xticks([])
# cax.set_yticks([])
# cax.set_axis_off()
# if share_axis:
# cax.sharey = self.colorbar[-1].ax
self.colorbar.append(self.fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
cax=cax, **params))
self.cmap.append(cmap)
self.norms.append(norm)
if len(self.ticks_colorbar[i]) == 0 and scale != "linear":
self.colorbar[-1].ax.set_yscale(scale)
elif (ticks_labels is not None and len(self.ticks_colorbar[i]) > 0
and self.ticks_colorbar[i][0] > - np.inf):
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i], labels=ticks_labels)
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] > - np.inf:
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i])
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] == - np.inf:
self.colorbar[-1].set_ticks(ticks=[])
for (i, ii) in zip(left, np.arange(len(right))):
cmap = mpl.colors.ListedColormap(self.custum_colorbar_colors[i])
norm = mpl.colors.BoundaryNorm(self.custum_colorbar_values[i], cmap.N)
params: dict = self.param_colorbar[i].copy()
fmt: str = ""
if "format" in params.keys():
fmt = params["format"]
del params["format"]
ticks_labels = None
if "ticks" in params.keys():
self.ticks_colorbar[i] = params["ticks"]
del params["ticks"]
if "ticks_labels" in params.keys():
ticks_labels = params["ticks_labels"]
del params["ticks_labels"]
elif fmt != "" and len(self.ticks_colorbar[i]) != 0 and self.ticks_colorbar[i][
0] > - np.inf:
ticks_labels = [fmt.format(x) for x in self.ticks_colorbar[i]]
scale: str = "linear"
if "scale" in params.keys():
scale = params["scale"]
del params["scale"]
share_axis: bool = False
if "share_axis" in params.keys():
share_axis = params["share_axis"]
del params["share_axis"]
if "location" in params.keys():
del params["location"]
fraction: np.float64 = 1
if "fraction" in params.keys():
fraction = params["fraction"]
del params["fraction"]
size_cb: np.float64 = size_colorbar
if "size" in params.keys():
size_cb = params["size"]
del params["size"]
size: np.float64 = size_cb
if not share_axis and "size_legend" in params.keys():
size += params["size_legend"]
del params["size_legend"]
elif not share_axis:
size += size_legend
if "space_between" in params.keys():
size += params["space_between"]
del params["space_between"]
elif not share_axis:
size += size_space
cax = self.ax.inset_axes([pos_l, 0.5 - fraction / 2., size_cb, fraction])
# cax = self.fig.add_axes([pos_l, 0.5 - fraction / 2., size_cb, fraction])
self.axes.append(cax)
pos_l += size
# cax.set_xticks([])
# cax.set_yticks([])
# cax.set_axis_off()
# if share_axis:
# cax.sharey = self.colorbar[-1].ax
self.colorbar.append(self.fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
cax=cax, **params))
self.cmap.append(cmap)
self.norms.append(norm)
if len(self.ticks_colorbar[i]) == 0 and scale != "linear":
self.colorbar[-1].ax.set_yscale(scale)
elif (ticks_labels is not None and len(self.ticks_colorbar[i]) > 0
and self.ticks_colorbar[i][0] > - np.inf):
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i], labels=ticks_labels)
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] > - np.inf:
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i])
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] == - np.inf:
self.colorbar[-1].set_ticks(ticks=[])
for (i, ii) in zip(bottom, np.arange(len(right))):
if "hide" not in params or not params["hide"]:
if "hide" in params:
del params["hide"]
cmap = mpl.colors.ListedColormap(self.custum_colorbar_colors[i])
norm = mpl.colors.BoundaryNorm(self.custum_colorbar_values[i], cmap.N)
params: dict = self.param_colorbar[i].copy()
fmt: str = ""
if "format" in params.keys():
fmt = params["format"]
del params["format"]
ticks_labels = None
if "ticks" in params.keys():
self.ticks_colorbar[i] = params["ticks"]
del params["ticks"]
if "ticks_labels" in params.keys():
ticks_labels = params["ticks_labels"]
del params["ticks_labels"]
elif fmt != "" and len(self.ticks_colorbar[i]) != 0 and self.ticks_colorbar[i][0] > - np.inf:
ticks_labels = [fmt.format(x) for x in self.ticks_colorbar[i]]
scale: str = "linear"
if "scale" in params.keys():
scale = params["scale"]
del params["scale"]
share_axis: bool = False
if "share_axis" in params.keys():
share_axis = params["share_axis"]
del params["share_axis"]
if "location" in params.keys():
del params["location"]
fraction: np.float64 = np.double(1.)
if "fraction" in params.keys():
fraction = params["fraction"]
del params["fraction"]
size_cb: np.float64 = size_colorbar
if "size" in params.keys():
size_cb = params["size"]
del params["size"]
size: np.float64 = size_cb
if not share_axis and "size_legend" in params.keys():
size += params["size_legend"]
del params["size_legend"]
elif not share_axis:
size += size_legend
if "space_between" in params.keys():
size += params["space_between"]
del params["space_between"]
elif not share_axis:
size += size_space
cax = self.ax.inset_axes([0.5 - fraction / 2., pos_b, size_cb, fraction])
# cax = self.fig.add_axes([0.5 - fraction / 2., pos_b, size_cb, fraction])
self.axes.append(cax)
pos_b += size
# cax.set_xticks([])
# cax.set_yticks([])
# cax.set_axis_off()
# if share_axis:
# cax.sharey = self.colorbar[-1].ax
self.colorbar.append(self.fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
cax=cax, **params))
self.cmap.append(cmap)
self.norms.append(norm)
if len(self.ticks_colorbar[i]) == 0 and scale != "linear":
self.colorbar[-1].ax.set_yscale(scale)
elif (ticks_labels is not None and len(self.ticks_colorbar[i]) > 0
and self.ticks_colorbar[i][0] > - np.inf):
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i], labels=ticks_labels)
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] > - np.inf:
self.colorbar[-1].set_ticks(ticks=self.ticks_colorbar[i])
elif len(self.ticks_colorbar[i]) > 0 and self.ticks_colorbar[i][0] == - np.inf:
self.colorbar[-1].set_ticks(ticks=[])
if len(right) > 0:
if "space_between" in self.param_colorbar[right[-1]].keys():
sr += self.param_colorbar[right[-1]]["space_between"]
elif "size" in self.param_colorbar[right[-1]].keys():
sr += self.param_colorbar[right[-1]]["size"] / 2.
else:
sr += size_colorbar / 2
if len(top) > 0:
if "space_between" in self.param_colorbar[top[-1]].keys():
st += self.param_colorbar[top[-1]]["space_between"]
elif "size" in self.param_colorbar[top[-1]].keys():
st += self.param_colorbar[top[-1]]["size"] / 2.
else:
st += size_colorbar / 2.
if len(left) > 0:
if "space_between" in self.param_colorbar[left[-1]].keys():
sl += self.param_colorbar[left[-1]]["space_between"]
pos_l += self.param_colorbar[left[-1]]["space_between"]
elif "size" in self.param_colorbar[left[-1]].keys():
sl += self.param_colorbar[left[-1]]["size"] / 2.
pos_l += self.param_colorbar[left[-1]]["size"] / 2.
else:
sl += size_colorbar / 2
pos_l += size_colorbar / 2
if len(bottom) > 0:
if "space_between" in self.param_colorbar[bottom[-1]].keys():
sb += self.param_colorbar[bottom[-1]]["space_between"]
pos_b += self.param_colorbar[bottom[-1]]["space_between"]
elif "size" in self.param_colorbar[bottom[-1]].keys():
sb += self.param_colorbar[bottom[-1]]["size"] / 2.
pos_b += self.param_colorbar[bottom[-1]]["size"] / 2.
else:
sb += size_colorbar / 2
pos_b += size_colorbar / 2
self.ax.set_axis_off()
self.ax.set_navigate(False)
new_ax_ = self.ax.inset_axes([pos_l, pos_b, 1. - (sl + sr), 1. - (st + sb)])
new_ax_.set_axis_off()
new_ax = self.fig.add_axes(new_ax_.get_position())
# new_ax = self.fig.add_axes([pos_l, pos_b, 1. - (sl + sr), 1. - (st + sb)])
new_ax.set_navigate(True)
self.axes.append(new_ax)
new_ax.sharex = self.ax
new_ax.sharey = self.ax
self.ax = new_ax
self.ax.set_navigate(True)
[docs]
def plot_lines(self) -> None:
"""
Plot all the line of the Graphique
Returns
-------
None
"""
with mpl.rc_context(self.param_font):
if self.ax is None:
self.ax = self.fig.add_axes([0, 0, 1, 1], **self.param_ax)
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
if self.ax_tl is None:
self.ax_tl = self.ax.twiny()
self.ax_tl.set(**self.param_ax_tl)
if self.ax_br is None:
self.ax_br = self.ax.twinx()
self.ax_br.set(**self.param_ax_br)
if self.ax_tr is None:
self.ax_tr = self.ax_tl.twinx()
self.ax_tr.set(**self.param_ax_tr)
index: np.ndarray[int] = np.arange(0, len(self.lines_x))
if len(self.indexs_plot_lines) > 0:
index = np.array(self.indexs_plot_lines)
for i in index:
if len(self.param_lines[i]) > 0:
params_i = self.param_lines[i].copy()
if "axis_config" not in params_i.keys():
axis_config: str = "bl"
else:
axis_config: str = params_i["axis_config"]
del params_i["axis_config"]
if len(self.err_y[i]) > 0:
if isinstance(self.err_x[i], list | np.ndarray) and len(self.err_x[i]) == 0:
err_x = None
else:
err_x = self.err_x[i]
if axis_config == "bl":
self.ax.errorbar(
x=self.lines_x[i], y=self.lines_y[i], xerr=err_x,
yerr=self.err_y[i], **params_i)
elif axis_config == "tl":
self.ax_tl.errorbar(
x=self.lines_x[i], y=self.lines_y[i], xerr=err_x,
yerr=self.err_y[i], **params_i)
elif axis_config == "tr":
self.ax_tr.errorbar(
x=self.lines_x[i], y=self.lines_y[i], xerr=err_x,
yerr=self.err_y[i], **params_i)
else: # axis_config == "br"
self.ax_br.errorbar(
x=self.lines_x[i], y=self.lines_y[i], xerr=err_x,
yerr=self.err_y[i], **params_i)
else:
if "color" in params_i and isinstance(params_i["color"],
list | np.ndarray):
marker: str = ""
if "marker" in params_i.keys():
marker = params_i["marker"]
del params_i["marker"]
if axis_config == "bl":
self.ax.scatter(
self.lines_x[i], self.lines_y[i], marker=marker, **params_i)
elif axis_config == "tl":
self.ax_tl.scatter(
self.lines_x[i], self.lines_y[i], marker=marker, **params_i)
elif axis_config == "tr":
self.ax_tr.scatter(
self.lines_x[i], self.lines_y[i], marker=marker, **params_i)
else: # axis_config == "br":
self.ax_br.scatter(
self.lines_x[i], self.lines_y[i], marker=marker, **params_i)
if not ("linestyle" in params_i.keys()) or params_i["linestyle"] != "":
colors = [to_rgba(c) for c in params_i["color"]]
del params_i["color"]
if axis_config == "bl":
colored_line(self.lines_x[i], self.lines_y[i], colors, self.ax, **params_i)
elif axis_config == "tl":
colored_line(self.lines_x[i], self.lines_y[i], colors, self.ax_tl, **params_i)
elif axis_config == "tr":
colored_line(self.lines_x[i], self.lines_y[i], colors, self.ax_tr, **params_i)
else: # axis_config == "tr"
colored_line(self.lines_x[i], self.lines_y[i], colors, self.ax_br, **params_i)
else:
if axis_config == "bl":
self.ax.plot(self.lines_x[i], self.lines_y[i], **params_i)
elif axis_config == "tl":
self.ax_tl.plot(self.lines_x[i], self.lines_y[i], **params_i)
elif axis_config == "tr":
self.ax_tr.plot(self.lines_x[i], self.lines_y[i], **params_i)
else: # axis_config == "br"
self.ax_br.plot(self.lines_x[i], self.lines_y[i], **params_i)
else:
self.ax.plot(self.lines_x[i], self.lines_y[i])
# bl, default axis
if len(self.x_axe[0]) == 0 or self.x_axe[0][0] > -np.inf:
# if len(self.x_axe[0]) > 0:
# self.ax.set_xlim([self.x_axe[0].min(), self.x_axe[0].max()])
self.ax.set_xticks(self.x_axe[0])
if len(self.labels_x_ticks[0]) == 0 or self.labels_x_ticks[0][0] != "empty":
self.ax.set_xticklabels(self.labels_x_ticks[0])
if len(self.y_axe[0]) == 0 or self.y_axe[0][0] > -np.inf:
# if len(self.y_axe[0]) > 0:
# self.ax.set_ylim([self.y_axe[0].min(), self.y_axe[0].max()])
self.ax.set_yticks(self.y_axe[0])
if len(self.labels_y_ticks[0]) == 0 or self.labels_y_ticks[0][0] != "empty":
self.ax.set_yticklabels(self.labels_y_ticks[0])
# tl
if len(self.x_axe[1]) == 0 or self.x_axe[1][0] > -np.inf:
# if len(self.x_axe[1]) > 0:
# self.ax_tl.set_xlim([self.x_axe[1].min(), self.x_axe[1].max()])
self.ax_tl.set_xticks(self.x_axe[1])
if len(self.labels_x_ticks[1]) == 0 or self.labels_x_ticks[1][0] != "empty":
self.ax_tl.set_xticklabels(self.labels_x_ticks[1])
if len(self.y_axe[1]) == 0 or self.y_axe[1][0] > -np.inf:
# if len(self.y_axe[1]) > 0:
# self.ax_tl.set_ylim([self.y_axe[1].min(), self.y_axe[1].max()])
self.ax_tl.set_yticks(self.y_axe[1])
if len(self.labels_y_ticks[1]) == 0 or self.labels_y_ticks[1][0] != "empty":
self.ax_tl.set_yticklabels(self.labels_y_ticks[1])
# tr
if len(self.x_axe[2]) == 0 or self.x_axe[2][0] > -np.inf:
# if len(self.x_axe[2]) > 0:
# self.ax_tr.set_xlim([self.x_axe[2].min(), self.x_axe[2].max()])
self.ax_tr.set_xticks(self.x_axe[2])
if len(self.labels_x_ticks[2]) == 0 or self.labels_x_ticks[2][0] != "empty":
self.ax_tr.set_xticklabels(self.labels_x_ticks[2])
if len(self.y_axe[2]) == 0 or self.y_axe[2][0] > -np.inf:
# if len(self.y_axe[2]) > 0:
# self.ax_tr.set_ylim([self.y_axe[2].min(), self.y_axe[2].max()])
self.ax_tr.set_yticks(self.y_axe[2])
if len(self.labels_y_ticks[2]) == 0 or self.labels_y_ticks[2][0] != "empty":
self.ax_tr.set_yticklabels(self.labels_y_ticks[2])
# br
if len(self.x_axe[3]) == 0 or self.x_axe[3][0] > -np.inf:
# if len(self.x_axe[3]) > 0:
# self.ax_br.set_xlim([self.x_axe[3].min(), self.x_axe[3].max()])
self.ax_br.set_xticks(self.x_axe[3])
if len(self.labels_x_ticks[3]) == 0 or self.labels_x_ticks[3][0] != "empty":
self.ax_br.set_xticklabels(self.labels_x_ticks[3])
if len(self.y_axe[3]) == 0 or self.y_axe[3][0] > -np.inf:
# if len(self.y_axe[3]) > 0:
# self.ax_br.set_ylim([self.y_axe[3].min(), self.y_axe[3].max()])
self.ax_br.set_yticks(self.y_axe[3])
if len(self.labels_y_ticks[3]) == 0 or self.labels_y_ticks[3][0] != "empty":
self.ax_br.set_yticklabels(self.labels_y_ticks[3])
if self.title != "":
self.ax.set_title(self.title)
[docs]
def plot_texts(self) -> None:
"""
Plot all the texts of the Graphique
Returns
-------
None
"""
with mpl.rc_context(self.param_font):
if self.ax is None:
self.ax = self.fig.add_axes([0, 0, 1, 1], **self.param_ax)
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
if self.ax_tl is None:
self.ax_tl = self.ax.twiny()
self.ax_tl.set(**self.param_ax_tl)
if self.ax_br is None:
self.ax_br = self.ax.twinx()
self.ax_br.set(**self.param_ax_br)
if self.ax_tr is None:
self.ax_tr = self.ax_tl.twinx()
self.ax_tr.set(**self.param_ax_tr)
for i in range(len(self.lines_t_x)):
# for (X, Y, S) in zip(self.lines_t_x[i], self.lines_t_y[i], self.lines_t_s[i]):
params_i = self.param_texts[i].copy()
if "axis_config" in params_i.keys():
axis_config: str = params_i["axis_config"]
del params_i["axis_config"]
else: # axis_config="bl"
axis_config: str = "bl"
if axis_config == "bl":
self.ax.text(self.lines_t_x[i], self.lines_t_y[i], self.lines_t_s[i], **params_i)
elif axis_config == "tl":
self.ax_tl.text(self.lines_t_x[i], self.lines_t_y[i], self.lines_t_s[i], **params_i)
elif axis_config == "tr":
self.ax_tr.text(self.lines_t_x[i], self.lines_t_y[i], self.lines_t_s[i], **params_i)
else: # axis_config == "br"
self.ax_br.text(self.lines_t_x[i], self.lines_t_y[i], self.lines_t_s[i], **params_i)
[docs]
def plot_histogrammes(self) -> None:
"""
Plot the Graphique's histogramme (if there is one)
Returns
-------
None
"""
with mpl.rc_context(self.param_font):
# Axe creation
if self.ax is None:
self.ax = self.fig.add_axes([0, 0, 1, 1], **self.param_ax)
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
if self.ax_tl is None:
self.ax_tl = self.ax.twiny()
self.ax_tl.set(**self.param_ax_tl)
if self.ax_br is None:
self.ax_br = self.ax.twinx()
self.ax_br.set(**self.param_ax_br)
if self.ax_tr is None:
self.ax_tr = self.ax_tl.twinx()
self.ax_tr.set(**self.param_ax_tr)
# plotting histogrammes
for i in range(len(self.vals_histogramme)):
pos = self.bords_histogramme[i][:-1]
largeur = np.array(
self.bords_histogramme[i][1:]) - np.array(self.bords_histogramme[i][:-1])
if len(self.param_histogrammes[i]) > 0:
self.ax.bar(x=pos, height=self.vals_histogramme[i], width=largeur, align='edge',
**self.param_histogrammes[i])
else:
self.ax.bar(
x=pos, height=self.vals_histogramme[i], width=largeur, align='edge')
# axes coordinate configuration
if np.any([len(self.param_lines[i]) > 0 for i in range(len(self.param_lines))]):
self.ax.legend(**self.param_legende)
if len(self.x_axe) == 0 or self.x_axe[0] > -np.inf:
# if len(self.x_axe) > 0:
# self.ax.set_xlim([self.x_axe.min(), self.x_axe.max()])
self.ax.set_xticks(self.x_axe)
if len(self.labels_x_ticks) == 0 or self.labels_x_ticks[0] != "empty":
self.ax.set_xticklabels(self.labels_x_ticks)
if len(self.y_axe) == 0 or self.y_axe[0] > -np.inf:
# if len(self.y_axe) > 0:
# self.ax.set_ylim([self.y_axe.min(), self.y_axe.max()])
self.ax.set_yticks(self.y_axe)
if len(self.labels_y_ticks) == 0 or self.labels_y_ticks[0] != "empty":
self.ax.set_yticklabels(self.labels_y_ticks)
if self.title != "":
self.ax.set_title(self.title)
[docs]
def plot_image(self) -> None:
"""
Plot the Graphique's image (if there is one)
Returns
-------
None
"""
with mpl.rc_context(self.param_font):
if self.ax is None:
self.ax = self.fig.add_axes([0, 0, 1, 1], **self.param_ax)
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
if self.ax_tl is None:
self.ax_tl = self.ax.twiny()
self.ax_tl.set(**self.param_ax_tl)
if self.ax_br is None:
self.ax_br = self.ax.twinx()
self.ax_br.set(**self.param_ax_br)
if self.ax_tr is None:
self.ax_tr = self.ax_tl.twinx()
self.ax_tr.set(**self.param_ax_tr)
params_tableau: dict = self.param_image.copy()
if "axis_config" in params_tableau.keys():
axis_config: str = params_tableau["axis_config"]
del params_tableau["axis_config"]
else: # bl
axis_config: str = "bl"
if len(self.array_image.shape) == 2:
if axis_config == "bl":
self.ax.pcolor(self.x_axe_image,
self.y_axe_image, self.array_image,
cmap=self.cmap[self.index_colorbar_image[0]],
norm=self.norms[self.index_colorbar_image[0]],
**params_tableau)
elif axis_config == "tl":
self.ax_tl.pcolor(self.x_axe_image,
self.y_axe_image, self.array_image,
cmap=self.cmap[self.index_colorbar_image[0]],
norm=self.norms[self.index_colorbar_image[0]],
**params_tableau)
elif axis_config == "tr":
self.ax_tr.pcolor(self.x_axe_image,
self.y_axe_image, self.array_image,
cmap=self.cmap[self.index_colorbar_image[0]],
norm=self.norms[self.index_colorbar_image[0]],
**params_tableau)
else: # axis_config == "br"
self.ax_br.pcolor(self.x_axe_image,
self.y_axe_image, self.array_image,
cmap=self.cmap[self.index_colorbar_image[0]],
norm=self.norms[self.index_colorbar_image[0]],
**params_tableau)
else:
if axis_config == "bl":
self.ax.imshow(self.array_image)
elif axis_config == "tl":
self.ax_tl.imshow(self.array_image)
elif axis_config == "tr":
self.ax_tr.imshow(self.array_image)
else: # axis_config == "br"
self.ax_br.imshow(self.array_image)
[docs]
def plot_contours(self) -> None:
"""
Plot the Graphique's contours (if there are)
Returns
-------
None
"""
params: dict = self.param_contours.copy()
if len(self.color_label_contours) > 0:
params["colors"] = self.color_label_contours
if "axis_config" in params.keys():
axis_config: str = params["axis_config"]
del params["axis_config"]
else: # bl
axis_config: str = "bl"
with mpl.rc_context(self.param_font):
if self.ax is None:
self.ax = self.fig.add_axes([0, 0, 1, 1], **self.param_ax)
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
if self.ax_tl is None:
self.ax_tl = self.ax.twiny()
self.ax_tl.set(**self.param_ax_tl)
if self.ax_br is None:
self.ax_br = self.ax.twinx()
self.ax_br.set(**self.param_ax_br)
if self.ax_tr is None:
self.ax_tr = self.ax_tl.twinx()
self.ax_tr.set(**self.param_ax_tr)
if len(self.levels) > 0:
levels = self.levels # print("levels",levels)
else:
levels = self.nb_contours # print("levels",levels)
if self.tab_contours_is_image:
if len(self.x_axe_image) != self.array_image.shape[1]:
x_axe = self.x_axe_image[:-1] + abs(
abs(self.x_axe_image[1:])
- abs(self.x_axe_image[:-1]))
else:
x_axe = self.x_axe_image
if len(self.y_axe_image) != self.array_image.shape[0]:
y_axe = self.y_axe_image[:-1] + abs(
abs(self.y_axe_image[1:])
- abs(self.y_axe_image[:-1]))
else:
y_axe = self.y_axe_image
if axis_config == "bl":
cs = self.ax.contour(x_axe, y_axe,
self.array_image, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax.clabel(cs, **self.param_labels_contours)
elif axis_config == "tl":
cs = self.ax_tl.contour(x_axe, y_axe,
self.array_image, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax_tl.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax_tl.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax_tl.clabel(cs, **self.param_labels_contours)
elif axis_config == "tr":
cs = self.ax_tr.contour(x_axe, y_axe,
self.array_image, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax_tr.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax_tr.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax_tr.clabel(cs, **self.param_labels_contours)
else: # axis_config == "br"
cs = self.ax_br.contour(x_axe, y_axe,
self.array_image, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax_br.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax_br.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax_br.clabel(cs, **self.param_labels_contours)
else:
if axis_config == "bl":
cs = self.ax.contour(self.x_axe_contours, self.y_axe_contours,
self.array_contours, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax.clabel(cs, **self.param_labels_contours)
elif axis_config == "tl":
cs = self.ax_tl.contour(self.x_axe_contours, self.y_axe_contours,
self.array_contours, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax_tl.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax_tl.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax_tl.clabel(cs, **self.param_labels_contours)
elif axis_config == "tr":
cs = self.ax_tr.contour(self.x_axe_contours, self.y_axe_contours,
self.array_contours, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax_tr.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax_tr.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax_tr.clabel(cs, **self.param_labels_contours)
else: # axis_config == "br"
cs = self.ax_br.contour(self.x_axe_contours, self.y_axe_contours,
self.array_contours, levels, **params)
if len(self.clabels) > 0:
dic_labels: dict = {}
for (n, l) in zip(self.levels, self.clabels):
dic_labels[n] = l
if len(self.clabels_mask) > 0:
self.ax_br.clabel(cs, self.levels[self.clabels_mask], fmt=dic_labels,
**self.param_labels_contours)
else:
self.ax_br.clabel(cs, self.levels, fmt=dic_labels, **self.param_labels_contours)
else:
self.ax_br.clabel(cs, **self.param_labels_contours)
if self.title != "":
self.ax.set_title(self.title)
[docs]
def plot_polygones(self) -> None:
"""
Plot the Graphique's polygones (if there are)
Returns
-------
None
"""
with mpl.rc_context(self.param_font):
for i in range(len(self.index_polygons)):
params: dict = self.param_polygons[i].copy()
if "axis_config" in params.keys():
axis_config: str = params["axis_config"]
del params["axis_config"]
else: # bl
axis_config: str = "bl"
P = Path(self.index_polygons[i])
poly = PathPatch(P, **params)
if axis_config == "bl":
self.ax.add_patch(poly)
elif axis_config == "tl":
self.ax_tl.add_patch(poly)
elif axis_config == "tr":
self.ax_tr.add_patch(poly)
else: # axis_config == "br"
self.ax_br.add_patch(poly)
[docs]
def plot(self, in_Multigraph: bool = False) -> None:
"""
Plot all the Graphique's elements
Parameters
----------
in_Multigraph: bool, optional, default=False
If the Graphique is plotted in a Multigraph, it deactivate globals parameters such as
the police or the style.
Returns
-------
None
"""
param_font: dict = {}
if not in_Multigraph:
if self.style in plt.style.available or self.style == 'default':
plt.style.use(self.style)
else:
print("The style ", self.style, " is not awalible. \n Plese use :\n", plt.style.available)
if self.style == 'dark_background':
self.dark_background()
elif self.style == 'default':
self.default_style()
param_font = self.param_font
with (mpl.rc_context(param_font)):
self.param_ax["title"] = self.title
if self.fig is None:
# self.fig = plt.figure(layout='constrained')
self.fig = plt.figure()
if len(self.param_fig) > 0:
self.fig.set(**self.param_fig)
if self.ax is None and "projection" in self.param_ax:
self.ax = plt.subplot(projection=self.param_ax["projection"])
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
elif self.ax is None:
self.ax = plt.subplot()
if self.axes is None:
self.axes = [self.ax]
else:
self.axes.append(self.ax)
elif self.axes is None:
self.axes = [self.ax]
if self.custum_colorbar_colors is not None:
self.plot_colorbar()
index: np.ndarray[int] = np.arange(0, len(self.lines_x))
if len(self.indexs_plot_lines) > 0:
index = np.array(self.indexs_plot_lines)
if (self.ax_tl is None
and (np.any(["axis_config" in dic.keys() and dic["axis_config"] == "tl"
for dic in np.array(self.param_lines)[index]])
or "axis_config" in self.param_image and self.param_image["axis_config"] == "tl"
or "axis_config" in self.param_contours and self.param_contours["axis_config"] == "tl"
or np.any(["axis_config" in dic.keys() and dic["axis_config"] == "tl"
for dic in self.param_polygons]))):
self.ax_tl = self.ax.twiny()
self.ax_tl.set(**self.param_ax_tl)
self.ax_tl.spines["bottom"].set(**self.param_spines_ax_tl[0])
self.ax_tl.spines["left"].set(**self.param_spines_ax_tl[1])
self.ax_tl.spines["top"].set(**self.param_spines_ax_tl[2])
self.ax_tl.spines["right"].set(**self.param_spines_ax_tl[3])
if len(self.ticks_param_ax_tl[0]) > 0:
self.ax_tl.tick_params(axis="x", **self.ticks_param_ax_tl[0])
if len(self.ticks_param_ax_tl[1]) > 0:
self.ax_tl.tick_params(axis="y", **self.ticks_param_ax_tl[1])
if (self.ax_br is None
and (np.any(["axis_config" in dic.keys() and dic["axis_config"] == "br"
for dic in np.array(self.param_lines)[index]])
or "axis_config" in self.param_image and self.param_image["axis_config"] == "br"
or "axis_config" in self.param_contours and self.param_contours["axis_config"] == "br"
or np.any(["axis_config" in dic.keys() and dic["axis_config"] == "br"
for dic in self.param_polygons]))):
self.ax_br = self.ax.twinx()
self.ax_br.set(**self.param_ax_br)
self.ax_br.spines["bottom"].set(**self.param_spines_ax_br[0])
self.ax_br.spines["left"].set(**self.param_spines_ax_br[1])
self.ax_br.spines["top"].set(**self.param_spines_ax_br[2])
self.ax_br.spines["right"].set(**self.param_spines_ax_br[3])
if len(self.ticks_param_ax_br[0]) > 0:
self.ax_br.tick_params(axis="x", **self.ticks_param_ax_br[0])
if len(self.ticks_param_ax_br[1]) > 0:
self.ax_br.tick_params(axis="y", **self.ticks_param_ax_br[1])
if (self.ax_tr is None
and (np.any(["axis_config" in dic.keys() and dic["axis_config"] == "tr"
for dic in np.array(self.param_lines)[index]])
or "axis_config" in self.param_image and self.param_image["axis_config"] == "tr"
or "axis_config" in self.param_contours and self.param_contours["axis_config"] == "tr"
or np.any(["axis_config" in dic.keys() and dic["axis_config"] == "tr"
for dic in self.param_polygons]))):
if self.ax_br is None:
self.ax_br = self.ax.twinx()
# self.ax_br.set_visible(False)
self.ax_tr = self.ax_br.twiny()
self.ax_tr.set(**self.param_ax_tr)
self.ax_tr.spines["bottom"].set(**self.param_spines_ax_tr[0])
self.ax_tr.spines["left"].set(**self.param_spines_ax_tr[1])
self.ax_tr.spines["top"].set(**self.param_spines_ax_tr[2])
self.ax_tr.spines["right"].set(**self.param_spines_ax_tr[3])
if len(self.ticks_param_ax_tr[0]) > 0:
self.ax_tr.tick_params(axis="x", **self.ticks_param_ax_tr[0])
if len(self.ticks_param_ax_tr[1]) > 0:
self.ax_tr.tick_params(axis="y", **self.ticks_param_ax_tr[1])
if len(self.param_ax) > 0:
args = self.param_ax.copy()
if "projection" in args:
del args["projection"]
self.ax.set(**args)
self.ax.spines["bottom"].set(**self.param_spines_ax[0])
self.ax.spines["left"].set(**self.param_spines_ax[1])
self.ax.spines["top"].set(**self.param_spines_ax[2])
self.ax.spines["right"].set(**self.param_spines_ax[3])
if len(self.ticks_param_ax[0]) > 0:
self.ax.tick_params(axis="x", **self.ticks_param_ax[0])
if len(self.ticks_param_ax[1]) > 0:
self.ax.tick_params(axis="y", **self.ticks_param_ax[1])
if len(self.x_axe[0]) == 0 or self.x_axe[0][0] > -np.inf:
# if len(self.x_axe[0]) > 0:
# self.ax.set_xlim([self.x_axe[0].min(), self.x_axe[0].max()])
self.ax.set_xticks(self.x_axe[0])
if len(self.labels_x_ticks[0]) == 0 or self.labels_x_ticks[0][0] != "empty":
self.ax.set_xticklabels(self.labels_x_ticks[0])
if len(self.y_axe[0]) == 0 or self.y_axe[0][0] > -np.inf:
# if len(self.y_axe[0]) > 0:
# self.ax.set_ylim([self.y_axe[0].min(), self.y_axe[0].max()])
self.ax.set_yticks(self.y_axe[0])
if len(self.labels_y_ticks[0]) == 0 or self.labels_y_ticks[0][0] != "empty":
self.ax.set_yticklabels(self.labels_y_ticks[0])
if len(self.x_axe[1]) == 0 or self.x_axe[1][0] > -np.inf:
# if len(self.x_axe[1]) > 0:
# self.ax_tl.set_xlim([self.x_axe[1].min(), self.x_axe[1].max()])
self.ax_tl.set_xticks(self.x_axe[1])
if len(self.labels_x_ticks[1]) == 0 or self.labels_x_ticks[1][0] != "empty":
self.ax_tl.set_xticklabels(self.labels_x_ticks[1])
if len(self.y_axe[1]) == 0 or self.y_axe[1][0] > -np.inf:
# if len(self.y_axe[0]) > 0:
# self.ax_tl.set_ylim([self.y_axe[1].min(), self.y_axe[1].max()])
self.ax_tl.set_yticks(self.y_axe[1])
if len(self.labels_y_ticks[1]) == 0 or self.labels_y_ticks[1][0] != "empty":
self.ax_tl.set_yticklabels(self.labels_y_ticks[1])
if len(self.x_axe[2]) == 0 or self.x_axe[2][0] > -np.inf:
# if len(self.x_axe[2]) > 0:
# self.ax_tr.set_xlim([self.x_axe[2].min(), self.x_axe[2].max()])
self.ax_tr.set_xticks(self.x_axe[2])
if len(self.labels_x_ticks[2]) == 0 or self.labels_x_ticks[2][0] != "empty":
self.ax_tr.set_xticklabels(self.labels_x_ticks[2])
if len(self.y_axe[2]) == 0 or self.y_axe[2][0] > -np.inf:
# if len(self.y_axe[0]) > 0:
# self.ax_tr.set_ylim([self.y_axe[2].min(), self.y_axe[2].max()])
self.ax_tr.set_yticks(self.y_axe[2])
if len(self.labels_y_ticks[2]) == 0 or self.labels_y_ticks[2][0] != "empty":
self.ax_tr.set_yticklabels(self.labels_y_ticks[2])
if len(self.x_axe[3]) == 0 or self.x_axe[3][0] > -np.inf:
# if len(self.x_axe[3]) > 0:
# self.ax_br.set_xlim([self.x_axe[3].min(), self.x_axe[3].max()])
self.ax_br.set_xticks(self.x_axe[3])
if len(self.labels_x_ticks[3]) == 0 or self.labels_x_ticks[3][0] != "empty":
self.ax_br.set_xticklabels(self.labels_x_ticks[3])
if len(self.y_axe[3]) == 0 or self.y_axe[3][0] > -np.inf:
# if len(self.y_axe[0]) > 0:
# self.ax_br.set_ylim([self.y_axe[3].min(), self.y_axe[3].max()])
self.ax_br.set_yticks(self.y_axe[3])
if len(self.labels_y_ticks[3]) == 0 or self.labels_y_ticks[3][0] != "empty":
self.ax_br.set_yticklabels(self.labels_y_ticks[3])
if self.title != "":
self.ax.set_title(self.title)
if len(self.lines_x) > 0:
self.plot_lines()
if len(self.vals_histogramme) > 0:
self.plot_histogrammes()
if len(self.array_image) > 1:
self.plot_image()
if len(self.array_contours) > 1 or (self.tab_contours_is_image and len(self.array_image) > 1):
self.plot_contours()
if len(self.index_polygons) > 0:
self.plot_polygones()
if len(self.lines_t_x) > 0:
self.plot_texts()
# if (np.any(["label" in dic.keys()
# for dic in np.array(self.param_lines)[index]])
# or np.any(["label" in dic for dic in self.param_histogrammes])
# or np.any(["label" in dic.keys()
# for dic in self.param_polygons])):
# param_legend = self.param_legende.copy()
# if "loc" not in param_legend.keys():
# param_legend["loc"] = "outside right upper"
# # param_legend["loc"] = "outside lower right"
# # param_legend["loc"] = "lower right"
# if 'draggable' not in param_legend.keys():
# param_legend["draggable"] = True
# self.fig.get_constrained_layout()
# self.fig.legend(**param_legend)
param_legend = self.param_legende.copy()
if 'draggable' not in param_legend.keys():
param_legend["draggable"] = True
if (np.any(["label" in dic.keys() and ("axis_config" not in dic.keys()
or dic["axis_config"] == "bl")
for dic in np.array(self.param_lines)[index]])
or np.any(["label" in dic for dic in self.param_histogrammes])
or np.any(["label" in dic.keys() and ("axis_config" not in dic.keys()
or dic["axis_config"] == "bl")
for dic in self.param_polygons])):
self.ax.legend(**param_legend)
if (np.any(["label" in dic.keys() and "axis_config" in dic.keys() and dic["axis_config"] == "tl"
for dic in np.array(self.param_lines)[index]])
or np.any(["label" in dic for dic in self.param_histogrammes])
or np.any(["label" in dic.keys() and "axis_config" in dic.keys() and dic["axis_config"] == "tl"
for dic in self.param_polygons])):
self.ax_tl.legend(**param_legend)
if (np.any(["label" in dic.keys() and "axis_config" in dic.keys() and dic["axis_config"] == "tr"
for dic in np.array(self.param_lines)[index]])
or np.any(["label" in dic for dic in self.param_histogrammes])
or np.any(["label" in dic.keys() and "axis_config" in dic.keys() and dic["axis_config"] == "tr"
for dic in self.param_polygons])):
self.ax_tr.legend(**param_legend)
if (np.any(["label" in dic.keys() and "axis_config" in dic.keys() and dic["axis_config"] == "br"
for dic in np.array(self.param_lines)[index]])
or np.any(["label" in dic for dic in self.param_histogrammes])
or np.any(["label" in dic.keys() and "axis_config" in dic.keys() and dic["axis_config"] == "br"
for dic in self.param_polygons])):
self.ax_br.legend(**param_legend)
self.ax.grid(self.grid)
[docs]
def show(self) -> None:
"""
Show the Graphique
Returns
-------
None
"""
# plt.ion()
self.plot()
plt.show()
self.ax = None
self.axes = None
self.ax_tl = None
self.ax_tr = None
self.ax_br = None
self.fig = None
# ---------------------------------------------------------------------------
# ---------------------------- Graphique building ---------------------------
# ---------------------------------------------------------------------------
[docs]
def line(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
show: bool = True, hide: bool = False, axis_config: str = "bl", set_phenigraph_style: bool = True,
**kwargs) -> Graphique:
"""
Equivalent to plt.plot
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar : optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The coresponding new Graphique
See Also
--------
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```self.line(x,[y1,y2], *args)``` is equivalent to
```plt.plot(x, y1, *args)
plt.plot(x, y2, *args)```
- if y1 and y2 have not the same size:
```line([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```line((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to :
```plt.plot(x, y1, marker=".", label="Curve1")
plt.plot(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.linspace(0, 10, 1000)
>>> alpha = np.linspace(1, 5, 10)
>>> colors = linear_color_interpolation(np.arange(len(alpha)), col_min=C1, col_max=C2)
>>> gr = line(x, [x*a for a in alpha], color=colors)
>>> gr.customized_cmap(alpha, colors)
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.line(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, kwargs_colorbar=kwargs_colorbar, hide=hide, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def errorbar(x: list | np.ndarray, y: list | np.ndarray, err_y: list | np.ndarray,
marker: str = "", scale: str = "", show: bool = True, hide: bool = False,
axis_config: str = "bl", set_phenigraph_style: bool = True,
**kwargs: dict) -> Graphique:
"""
Equivalent to plt.errorbar
Parameters
----------
x : list | array_like
Abscissa
y : list | array_like
Ordinate
err_y : list | array_like
Error associated with y
err_x : list | array_like
Error associated with x
marker : list[str] | array_like[str], str, optional, default=""
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
scale : str, optional, default="linear"
The scales of (x, y) axis :
- default : "" (linear scale for both x and y)
- polar : polar projection : X=r and Y=theta
- loglog, logx, logy : Logarithmic scale for both, x or y axis
- symloglog, symlogx, symlogy : Logarithmic scale for both, x or y axis with positive and négative values
show : bool, optional, default = True
To show the Graphique
hide: bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Whether to set or not the phenigraph style to the Graphique
kwargs
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.errorbar(x=x, y=y, err_y=err_y, marker=marker, scale=scale, hide=hide, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def errorplot(x: list | np.ndarray, y: list | np.ndarray, err_y: list | np.ndarray,
marker: str = "", scale: str = "", show: bool = True, hide: bool = False,
axis_config: str = "bl", set_phenigraph_style: bool = True, **kwargs: dict) -> Graphique:
"""
Equivalent to plt.errorbar but the error is not represented by errorbars but by a
uniform-colored polygon
Parameters
----------
x : list | array_like
Abscissa
y : list | array_like
Ordinate
err_y : list | array_like
Error associated with y
marker : list[str] | array_like[str], str, optional, default=""
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
scale : str, optional, default="linear"
The scales of (x, y) axis :
- default : "" (linear scale for both x and y)
- polar : polar projection : X=r and Y=theta
- loglog, logx, logy : Logarithmic scale for both, x or y axis
- symloglog, symlogx, symlogy : Logarithmic scale for both, x or y axis with positive and négative values
show : bool, optional, default = True
To show the Graphique
hide: bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.errorplot(x=x, y=y, err_y=err_y, marker=marker, scale=scale, hide=hide, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def polar(r: list | np.ndarray, theta: list | np.ndarray,
z: np.ndarray | list | None = None, marker: str = "",
share_colorbar: bool = False, scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False, **kwargs: dict) -> Graphique:
"""
Equivalent to line in polar projection
Parameters
----------
r : list | array_like
Radius
theta : list | array_like
Angle(s)
z : list | array_like, optional
z-axis (represented by a colorscale)
marker: : list[str] | array_like, str, optional, default=""
The marker (ex ".", ",", "o", "v"...)
see matplotlib documentation for all the possibility
share_colorbar : bool, optional, default=True
If True(default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z: str, optional, {"linear", "log", "symlog"}, default="linear"
The scale of the z-axis (linear (default), log, symplog)
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar: dict
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
kwargs
Additional argument to plot() function like linestyle, color...
Returns
-------
Graphique
The new Graphique
Notes
-------
The order of first and second arguments is opposit to the matplotlib one :
The first argument is the radius, then the angle
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=False)
graph.polar(r=r, theta=theta, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def loglog(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False, set_phenigraph_style: bool = True,
**kwargs) -> Graphique:
"""
Equivalent to line with a logarithmique scale for both x and y-axis:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new graphique
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```loglog(x,[y1,y2], *args)``` is equivalent to
```plt.loglog(x, y1, *args)
plt.loglog(x, y2, *args)```
- if y1 and y2 have not the same size:
```loglog([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```loglog((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```plt.loglog(x, y1, marker=".", label="Curve1")
plt.loglog(x, y2, marker=".", label="Curve2")```
Examples
--------
>>> x = np.linspace(0, 10, 1000)
>>> alpha = np.linspace(1, 5, 10)
>>> colors = linear_color_interpolation(np.arange(len(alpha)), col_min=C1, col_max=C2)
>>> gr: Graphique = loglog(x, [x*a for a in alpha], color=colors)
>>> gr.customized_cmap(alpha, colors)
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.loglog(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def symloglog(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False, set_phenigraph_style: bool = True,
**kwargs) -> Graphique:
"""
Equivalent to line with a logarithmique scale for both x and y-axis
Both the negative and positive parts of y are represanted:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```symloglog(x,[y1,y2], *args)``` is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(xscale="symlog", yscale="symlog")```
- if y1 and y2 have not the same size:
```symloglog([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```symloglog((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(xscale="symlog", yscale="symlog")```
Examples
--------
>>> x = np.linspace(-10, 10, 1000)
>>> gr = symloglog(x, np.tan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.symloglog(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def logx(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False,
set_phenigraph_style: bool = True, **kwargs) -> Graphique:
"""
Equivalent to line with a logarithmique scale for x-axis:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```logx(x,[y1,y2], *args)``` is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(scale="log")```
- if y1 and y2 have not the same size:
```logx([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```logx((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(xscale="log")```
Examples
--------
>>> x = np.logspace(-10, 10, 1000)
>>> gr = Graphique()
>>> gr.logx(x, np.arctan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.logx(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def symlogx(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False,
set_phenigraph_style: bool = True, **kwargs) -> Graphique:
"""
Equivalent to line with a logarithmique scale for both x-axis (both negative and positive
part are represanted):
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```symlogx(x,[y1,y2], *args)``` is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(xscale="symlog")```
- if y1 and y2 have not the same size:
```symlogx([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```symlogx((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(xscale="symlog")```
Examples
--------
>>> x = np.append(-np.logspace(10, -10, 1000), np.logspace(-10, 10, 1000))
>>> gr = Graphique()
>>> gr.symlogx(x, np.arctan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.symlogx(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def logy(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False,
set_phenigraph_style: bool = True, **kwargs) -> Graphique:
"""
Equivalent to line with a logarithmique scale for y-axis:
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logx : Graphique.line in log coordinate for x axis and linear for y axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Graphique.symlogy : Similar to Graphique.logy but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```logy(x,[y1,y2], *args)``` is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(yscale="log")```
- if y1 and y2 have not the same size:
```logy([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```logy((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"]```
is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(yscale="log")```
Examples
--------
>>> x = np.logspace(-10, 10, 1000)
>>> gr = logy(x, np.arctan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.logy(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def symlogy(x: np.ndarray | list, y: np.ndarray | list | None = None,
z: np.ndarray | list | None = None,
marker: str | list = "", share_colorbar: bool = False,
scale_z: str = "linear", kwargs_colorbar: dict | None = None,
axis_config: str = "bl", show: bool = True, hide: bool = False,
set_phenigraph_style: bool = True, **kwargs) -> Graphique:
"""
Equivalent to line with a logarithmique scale for y-axis (both positive and negative
part are represanted):
Parameters
----------
x : array_like | list
Abscissa(s)
y : array_like | list, optional
Ordinate(s), if None x became the ordinate and the abscissa is arange(len(x))
z : array_like | list, optional
z-axis (represented by a colorscale)
marker : str | list[str] | array_like[str], optional, default=""
The marker ex ".", ",", "o", "v"... (see matplotlib documentation)
share_colorbar : bool, optional, default=True
If True (default) and z is not None, only one colorscale is used
even if z is in two dimensions
scale_z : str, {'linear', 'log', 'symlog'}, optional, default='linear'
The scale of the z-axis
show : bool, optional, default = True
To show the Graphique
hide : bool, optional, default=False
If True then the new line(s) is/are not plotted with the Graphique.
To plot them, then change the plot order with self.set_indexs_plot_lines
kwargs_colorbar, optional
Extra arguments for the colorbar (if z is not None)
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs, optional
Additional argument to plot() function like linestyle, color....
Returns
-------
Graphique
The new Graphique
See Also
--------
Graphique.line : Build line(s) for the Graphique
Graphique.loglog : Graphique.line in log coordinate for boths x and y axis
Graphique.logy : Graphique.line in log coordinate for y axis and linear for x axis
Graphique.point : To plot a single point
Graphique.errorbar : To plot a line with errorbars
Graphique.errorplot : To plot a line with errorbars represanted as filled area
Graphique.polar : To plot a line in polar coordinates
Graphique.symloglog : Similar to Graphique.loglog but boths negatives and positives values are represanted
Graphique.symlogx : Similar to Graphique.logx but boths negatives and positives values are represanted
Notes
-------
This function has a small improuvment compared with plt.plot :
if y is in two dimensions, the second dimension is plotted :
- ```symlogy(x,[y1,y2], *args)``` is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, *args)
ax.plot(x, y2, *args)
ax.set(yscale="symlog")```
- if y1 and y2 have not the same size:
```symlogy([x1,x2],[y1, y2], *args)```
- If others arguments are list of the same size of x and y, they are also split :
```symlogy((x1, x2], [y1, y2], marker=".", label=["Curve1", "Curve2"])```
is equivalent to
```ax = plt.subplot()
ax.plot(x, y1, marker=".", label="Curve1")
ax.plot(x, y2, marker=".", label="Curve2")
ax.set(yscale="symlog")```
Examples
--------
>>> x = np.linspace(0,np.pi,1000)
>>> gr = gr.symlogy(x, np.tan(x))
>>> gr.show()
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.symlogy(x, y, z=z, marker=marker, share_colorbar=share_colorbar,
scale_z=scale_z, hide=hide, kwargs_colorbar=kwargs_colorbar, axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def histogram(values: np.ndarray, weights: np.ndarray | None = None,
normalization: bool = True, statistic: str = 'sum', bins: int = 10,
show: bool = True, set_phenigraph_style: bool = True, **args) -> Graphique:
"""
Plot the histogram of values
Parameters
----------
values : array_like
The values to histogramed
weights : array_like, optional
The weights to be applied to values
normalization : bool, optional, default=True
If the histogram is normalized or not
statistic : str, optional, default="sum"
The statistic to compute (default is 'sum').
The following statistics are available:
- 'mean': compute the mean of values for points within each bin. Empty bins will be represented by NaN.
- 'std': compute the standard deviation within each bin. This is implicitly calculated with ddof=0.
- 'median': compute the median of values for points within each bin. Empty bins will be represented by NaN.
- 'count': compute the count of points within each bin. This is identical to an unweighted histogram. values array is not
referenced.
- 'sum': compute the sum of values for points within each bin. This is identical to a weighted histogram.
- 'min': compute the minimum of values for points within each bin. Empty bins will be represented by NaN.
- 'max': compute the maximum of values for point within each bin. Empty bins will be represented by NaN.
bins : int, optional, default=10
Number of bins in the histogram
stat_args, dict, optional
Additionals argument for `sp.binned_statistic`
show : bool, optional, default = True
To show the Graphique
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs
Additionals argument for plt.bars
Returns
-------
Graphique
The new Graphique
See also
--------
scipy.stats.binned_statistic
"""
if weights is None:
poids = []
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.histogram(
values=values, weights=weights, normalization=normalization, statistic=statistic,
bins=bins, **args)
if show:
graph.show()
return graph
[docs]
def image(array_image: np.ndarray,
x_axe: list | np.ndarray | None = None, y_axe: list | np.ndarray | None = None,
colorscale: str = "linear",
cmap: str = "default", colorbar_ticks: list | np.ndarray | None = None,
colorbar_label: str = "", kwargs_colorbar: dict | None = None,
colorbar_index: int = ii_max, color_min: str | tuple = None, color_max: str | tuple = None,
vmin: np.float64 = -np.inf, vmax: np.float64 = np.inf, axis_config: str = "bl",
show: bool = True, set_phenigraph_style: bool = True,
**kwargs) -> Graphique:
"""
Plot the array image through plt.pcolor or plt.imshow for 3 color images
Parameters
----------
array_image : np.ndarray
The matrix (2D, or 3D for colored images (the color is on the third axis)) to be plotted
x_axe : list | np.ndarray, optional, default=np.arange(0,array_image.shape[0])
The x-axes coordinate (for the array), only for 2d array_image
y_axe : list | np.ndarray, optional, default=np.arange(0,array_image.shape[1])
The y-axes coordinate (for the array), only for 2d array_image
colorscale : str, optional, default="linear", {"linear", "log", "symlog"}
The scale for the colorbar
cmap : str, optional, default="default"
The colormap, default a linear color interpolation between two colors CX
colorbar_ticks : list | array_like, optional
The colorbar's ticks
colorbar_label : str, optional, default=""
The colorbar's label
kwargs_colorbar : dict, optional
Additional arguments for the colorbar :
- location: str, {'right', 'top', 'bottom', 'left'}
Indicate where the colorbar should be plotted
- scale: str, {'linear', 'log', 'symlog'}
The scale of the colorbar
- ticks: list | array_like
- format: str
ticks' format
- label: str
The label to plot along the colorbar
- size: float, default=0.01
relative width of the colorbar
- fraction: float, default=1
relative hight of the colorbar
- space_between: float, default=0.01
relative space between colorsbars (and the plot)
colorbar_index : int, optional
The index of a previouly defined colorbar, to use insted of building a new one, all the others colorbar are
ignored if provided
vmin : np.float64, optional, default : the minimum of array_image
The minimum value for the colorbar
vmax : np.float64, optional, default : the maximum of array_image
The maximum value for the colorbar
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
show : bool, optional, default = True
To show the Graphique
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs
Additionals arguments for pcolor
Returns
-------
None
See Also
--------
matplotlib.pyplot.pcolor
Use to plot 2d array images
matplotlib.pyplot.imshow
Use to plot 3-colors images
Graphique.contours
To draw levels lines onto the image
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
graph: Graphique = Graphique(set_phenigraph_style=set_phenigraph_style)
graph.image(array_image=array_image, x_axe=x_axe, y_axe=y_axe, colorscale=colorscale, cmap=cmap,
colorbar_ticks=colorbar_ticks, colorbar_label=colorbar_label, kwargs_colorbar=kwargs_colorbar,
colorbar_index=colorbar_index, color_min=color_min, color_max=color_max, vmin=vmin, vmax=vmax,
axis_config=axis_config, **kwargs)
if show:
graph.show()
return graph
[docs]
def level_surface(x: np.ndarray | list, y: np.ndarray | list,
vals: np.ndarray | list, npix_x: int = 400, npix_y: int = 400,
logx: bool = False, logy: bool = False,
method: str = 'cubic', log_vals: bool = False, axis_config: str = "bl",
show: bool = True, set_phenigraph_style: bool = True, **kwargs) -> Graphique:
"""
Returns an image representing the 2d contour line associated with the points
points defined by x, y, vals
Parameters
----------
x : np.ndarray | list
list of size n and dimension 1
containing the abscissa of the points
y : np.ndarray | list
list of size n and dimension 1
containing the odrides of the points
vals : np.ndarray | list
list of size n and dimension 1
containing point values to be interpolated and displayed
npix_x : int, optional, default = 400
number of image pixels on x axis
npix_y : int, optional, default = 400
number of image pixels on y axis
logx : bool, optional, default = False
indicates whether the x axis is logarithmically subdivided or not
logy : bool, optional, default = False
indicates whether the y axis is logarithmically subdivided or not
method : str, optional, default = "cubic
interplotation method: 'nearest', 'linear' where by default
'cubic'. See doc scipy.interpolate.griddata
log_vals : bool, optional, default = False
indicates whether values are displayed (and extrapolated) on a logarithmic scale or not.
on a logarithmic scale
axis_config : str, optional, {"bl", "tl", "br", "tr"}, default="bl"
The positions of x-y axis :
- "bl" is x-axis on the bottom, y-axis on the left (default).
- "tl" is x-axis on the top, y-axis on the left.
- "br" is x-axis on the bottom, y-axis on the right.
- "tr" is x-axis on the top, y-axis on the right.
show : bool, optional, default = True
To show the Graphique (default=True)
set_phenigraph_style : bool, optional=True, default=True
Wheather to set or not the phenigraph style to the Graphique
kwargs
dictionaries of complementary arguments to images
Returns
-------
Graphique
The new Graphique
"""
if axis_config not in ["bl", "tl", "tr", "br"]:
raise UserWarning("""The axis configuration can only be "bl", "tl"; "tr" or "br", not """, axis_config)
points: np.ndarray = np.array([x, y]).T
if logx:
x_int: np.ndarray = np.geomspace(np.min(x), np.max(x), npix_x)
else:
x_int: np.ndarray = np.linspace(np.min(x), np.max(x), npix_x)
if logy:
y_int: np.ndarray = np.geomspace(np.min(y), np.max(y), npix_y)
else:
y_int: np.ndarray = np.linspace(np.min(y), np.max(y), npix_y)
xi_x, xi_y = np.meshgrid(x_int, y_int)
if log_vals:
tab: np.ndarray = griddata(points, np.log10(vals),
xi=(xi_x, xi_y), method=method, rescale=True)
tab = 10 ** tab
print(tab.min(), tab.max())
else:
tab: np.ndarray = griddata(points, vals, xi=(xi_x, xi_y), method=method)
res: Graphique = image(tab, x_int, y_int, shading='nearest', show=False, axis_config=axis_config,
set_phenigraph_style=set_phenigraph_style, **kwargs)
res.config_colorbar(scale="log")
if show:
res.show()
return res
[docs]
class Multigraph:
"""
To plot multiples Graphiques in a single Figure
"""
def __init__(self, nrows: int = 1, ncols: int = 1, filename: str = "", directory: str = ""):
"""
To build a Multigraph
Parameters
----------
nrows : int, optional, default=1
Numbers of rows in the array containing the Graphiques
ncols : int, optional, default=1
Numbers of collumns in the array containing the Graphiques
filename : str, optional, default=""
To load an existing Multigraph (if not "")
directory : str, optional, default=""
The directory of the loaded Multigraph, if filename != "". If filename
alreaday contain the total path, the directory is automaticaly deduced
Notes
----------
If a nrows is a string it will be interpredted as nrows=filename
```mg=Multigraph("filename")``` will try to load the Mutigraph filename
"""
if isinstance(nrow, str):
filename: str = nrows
nrows: int = 1
if '.npz' in filename:
filename = filename[:-4]
if filename == "":
self.directory: str = "./"
self.filename: str = "graph_without_name"
self.ext: str = ".png"
self.style: str = 'default' # global style:
# styles available: plt.style.available : 'default' 'Solarize_Light2'
# '_classic_test_patch' '_mpl-gallery' '_mpl-gallery-nogrid'
# 'bmh' 'classic' 'dark_background' 'fast' 'fivethirtyeight' 'ggplot'
# 'grayscale' 'seaborn' 'seaborn-bright' 'seaborn-colorblind' 'seaborn-dark' 'seaborn-dark-palette'
# 'seaborn-darkgrid' 'seaborn-deep' 'seaborn-muted' 'seaborn-notebook' 'seaborn-paper' 'seaborn-pastel'
# 'seaborn-poster' 'seaborn-talk' 'seaborn-ticks' 'seaborn-white' 'seaborn-whitegrid' 'tableau-colorblind10'
self.param_font: dict = {"font.size": 13} # Contains additional parameters for global font management
self.param_fig: dict = dict() # Contains additional parameters for the Figure ex : facecolor="w"...
self.param_grid_spec: dict = dict() # Contains additional parameters for the grid : hspace, vspace...
self.param_enrg_fig: dict = dict(bbox_inches="tight")
self.nrows: int = nrows
self.ncols: int = ncols
self.list_Graphs: list[Graphique] = []
self.list_coords: list[int | list[int | tuple]] = []
self.list_sharex_axis_coord: list[int | tuple] = []
self.list_sharey_axis_coord: list[int | tuple] = []
self.param_subplot: list[dict] = []
self.occupy_coordinates: list[list[int]] = [] # List of coordinates of the occupy slots to test if a Graphique
# could be added with a new set of coordinate
self.fig = None
if filename != "":
self.filename = filename
if directory != "":
self.directory = directory
elif "/" in directory:
i: int = directory.find("/")
while directory.find("/") > 0:
# Cherche la dernière occurrence de "/"
i = directory.find("/")
self.directory = filename[:i]
self.filename = filename[i:]
else:
self.directory = "./"
values_files: np.lib.npyio.NpzFile = np.load(directory + filename + ".npz")
values_to_load: dict = ndarray_dict_to_dict(dict(values_files))
values_files.close()
self.load_dict(values_to_load)
[docs]
def load_dict(self, values_to_load: dict) -> None:
"""
load a Graphix contain in a dictionary
Parameters
----------
values_to_load : dict
Dictionary containing all the information needed to build a Multigraph.
This dictionary is produced by Multigraph.to_dict()
Returns
-------
None
See Also
--------
Multigraph.to_dict
Produce a dictionary that can be used to build a new Multigraph
"""
if "ext" in values_to_load.keys():
self.ext: str = values_to_load["ext"]
if "style" in values_to_load.keys():
self.style: str = values_to_load["style"]
if "param_font" in values_to_load.keys():
self.param_font: str = values_to_load["param_font"]
if "param_fig" in values_to_load.keys():
self.param_fig: str = values_to_load["param_fig"]
if "param_enrg_fig" in values_to_load.keys():
self.param_enrg_fig: str = values_to_load["param_enrg_fig"]
if "param_grid_spec" in values_to_load.keys():
self.param_grid_spec: str = values_to_load["param_grid_spec"]
if "nrows" in values_to_load.keys():
self.nrows: str = values_to_load["nrows"]
if "ncols" in values_to_load.keys():
self.ncols: str = values_to_load["ncols"]
if "list_Graphs" in values_to_load.keys():
self.list_Graphs: str = values_to_load["list_Graphs"]
if "list_coords" in values_to_load.keys():
self.list_coords: str = values_to_load["list_coords"]
if "list_sharex_axis_coord" in values_to_load.keys():
self.list_sharex_axis_coord: str = values_to_load["list_sharex_axis_coord"]
if "list_sharey_axis_coord" in values_to_load.keys():
self.list_sharey_axis_coord: str = values_to_load["list_sharey_axis_coord"]
if "occupy_coordinates" in values_to_load.keys():
self.occupy_coordinates: str = values_to_load["occupy_coordinates"]
if "param_subplot" in values_to_load.keys():
self.param_subplot: str = values_to_load["param_subplot"]
[docs]
def to_dict(self) -> dict:
"""
Build a dictionary to be saved with np.saved_compressed
Returns
-------
dict
See Also
--------
Multigraph.load_dict
To load the produced dictionary in another Multigraph
"""
enrg: dict = dict() # Dictionary containing all the necessary information :
# Used like : np.savez_compressed(name_fichier,**enrg)
enrg["ext"] = self.ext
enrg["style"] = self.style
enrg["param_font"] = self.param_font
enrg["param_fig"] = self.param_fig
enrg["param_enrg_fig"] = self.param_enrg_fig
enrg["param_grid_spec"] = self.param_grid_spec
enrg["nrows"] = self.nrows
enrg["ncols"] = self.ncols
enrg["list_Graphs"] = self.list_Graphs
enrg["list_coords"] = self.list_coords
enrg["list_sharex_axis_coord"] = self.list_sharex_axis_coord
enrg["list_sharey_axis_coord"] = self.list_sharey_axis_coord
enrg["occupy_coordinates"] = self.occupy_coordinates
enrg["param_subplot"] = self.param_subplot
return enrg
[docs]
def save(self, filename: str = "mgraph_without_name", directory: str = None) -> None:
"""
Save the Multi.graph in self.directory (default the current working directory) in npz compressed
format.
Parameters
----------
filename: str, optinal, default="mgraph_without_name"
The name of the .npz file (default: "mgraph_without_name")
directory: str, optional, default="./"
Graphique's directory (default self.directory (default : the curent working directory))
Returns
-------
None
"""
if filename != "mgraph_without_name":
if ".npz" in filename:
self.filename = filename[:-4]
else:
self.filename = filename
if directory is not None:
self.directory = directory
enrg = dict_to_ndarray_dict(self.to_dict(), separator="-.-")
if ".npz" not in self.filename:
if self.directory[-1] == "/":
np.savez_compressed(self.directory +
self.filename + ".npz", **enrg)
else:
np.savez_compressed(self.directory + "/" +
self.filename + ".npz", **enrg)
else:
if self.directory[-1] == "/":
np.savez_compressed(self.directory +
self.filename, **enrg)
else:
np.savez_compressed(self.directory + "/" +
self.filename, **enrg)
[docs]
def add_graphique(self, coord: int | list[int, tuple], graph: Graphique = None,
sharex: int | list[int, tuple] = None,
sharey: int | list[int, tuple] = None, **kwargs):
"""
To add a new Graphique in the Multigraph at the coordinates defined by coord.
This Graphique can cover several slots
Parameters
----------
coord : int | list[int, tuple]
the Graphique's coordinates : if self.nrows or nself.ncols =1 it can be an int, either a list
of int :
[index_rows, index_cols]. If this Graphique extend on severals slots, coord should be on this form :
[(index_rows_min, index_rows_max), (index_cols_min, index_cols_min)]
graph : Graphique, optional, default : an empty Graphique
The Graphique to add, default a new empty Graphique is created
sharex : int | list[int, tuple], optional
Coordinates of the Graphique to wich the x axis is shared if needed. The corresponding Graphique
should already be in the Multigraph. If the new Graphique is on multiples slots then the Graphique to which the
coordinates are shared should occupy the same number of raw.
sharey : int | list[int, tuple], optional
Coordinates of the Graphique to wich the y axis is shared if needed. The corresponding Graphique
should already be in the Multigraph. If the new Graphique is on multiples slots then the Graphique to which the
coordinates are shared should occupy the same number of cols
kwargs
Extra-parameters for plt.subplot
Returns
-------
None
"""
if graph is None:
graph = Graphique()
elif not isinstance(graph, Graphique):
raise UserWarning("Multigraph.add_Graphique : graph should be a Graphique not a ", type(graph))
if isinstance(coord, int) and self.nrows > 1 and self.ncols > 1:
raise UserWarning("Multigraph.add_Graphique : The Multigraph isn't linear nrow=",
self.nrows, "ncols=", self.ncols,
"The coordinate of the added Graphique should be a list, not an int")
elif isinstance(coord, int) and coord >= self.nrows * self.ncols:
raise UserWarning("Multigraph.add_Graphique : The coordinate of the added Graphique ",
coord, "is higher than the maximum :", self.nrows * self.ncols - 1)
elif isinstance(coord, list) and isinstance(coord[0], int) and coord[0] >= self.nrows:
raise UserWarning("Multigraph.add_Graphique : The first coordinate of the added Graphique ",
coord[0], "is higher than the maximum :", self.nrows - 1)
elif isinstance(coord, list) and isinstance(coord[1], int) and coord[1] >= self.ncols:
raise UserWarning("Multigraph.add_Graphique : The second coordinate of the added Graphique ",
coord[1], "is higher than the maximum :", self.nrows - 1)
elif isinstance(coord, list) and isinstance(coord[0], tuple) and coord[0][1] >= self.nrows:
raise UserWarning("Multigraph.add_Graphique : The first maximum coordinate of the added Graphique ",
coord[0][1], "is higher than the maximum :", self.nrows - 1)
elif isinstance(coord, list) and isinstance(coord[1], tuple) and coord[1][1] >= self.ncols:
raise UserWarning("Multigraph.add_Graphique : The second maximum coordinate of the added Graphique ",
coord[1][1], "is higher han the maximum :", self.ncols - 1)
occupy_coordinates: list = []
if isinstance(coord, int):
if self.ncols == 1:
if coord < 0:
coord = (self.nrows + coord) % self.nrows
if [coord, 0] in self.occupy_coordinates or [coord, 0] in occupy_coordinates:
raise UserWarning("Multigraph.add_graphique : "
"The coordinate ", [coord, 0], "is already occupy")
else:
occupy_coordinates.append([coord, 0])
coord: list = [coord, 0]
else:
if coord < 0:
coord = (self.cols + coord) % self.ncols
if [0, coord] in self.occupy_coordinates or [0, coord] in occupy_coordinates:
raise UserWarning("Multigraph.add_graphique : The coordinate ", [0, coord], "is already occupy")
else:
occupy_coordinates.append([0, coord])
coord: list = [0, coord]
elif isinstance(coord, list) and isinstance(coord[0], int) and isinstance(coord[1], int):
if coord in self.occupy_coordinates or coord in occupy_coordinates:
raise UserWarning("Multigraph.add_graphique : The coordinate ", coord, "is already occupy")
else:
occupy_coordinates.append(coord)
elif isinstance(coord, list) and isinstance(coord[0], int):
for i in range(coord[1][0], coord[1][1] + 1):
if [coord[0], i] in self.occupy_coordinates or [coord[0], i] in occupy_coordinates:
raise UserWarning("Multigraph.add_graphique : The coordinate ", [coord[0], i], "is already occupy")
else:
occupy_coordinates.append([coord[0], i])
elif isinstance(coord, list) and isinstance(coord[1], int):
for i in range(coord[0][0], coord[0][1] + 1):
if [i, coord[1]] in self.occupy_coordinates or [i, coord[1]] in occupy_coordinates:
raise UserWarning("Multigraph.add_graphique : The coordinate ", [i, coord[1]], "is already occupy")
else:
occupy_coordinates.append([i, coord[1]])
else:
for i in range(coord[0][0], coord[0][1] + 1):
for j in range(coord[1][0], coord[1][1] + 1):
if [i, j] in self.occupy_coordinates or [i, j] in occupy_coordinates:
raise UserWarning("Multigraph.add_graphique : The coordinate ", [i, j], "is already occupy")
else:
occupy_coordinates.append([i, j])
if sharex is not None and sharex not in self.list_coords:
raise UserWarning("Multigraph.add_graphique : there is no Graphique at the coordinates indicates"
" for the sharex parameter")
elif sharex is not None:
if coord[1] != sharex[1]:
raise UserWarning(
"Multigraph.add_graphique : the second coordinates of the sharex Graphique doesn't match "
"with the new coordinates")
else:
sharex = [ii_max, ii_max]
if sharey is not None and sharey not in self.list_coords:
raise UserWarning("Multigraph.add_graphique : there is no Graphique at the coordinates indicates"
" for the sharey parameter")
elif sharey is not None:
if coord[0] != sharey[0]:
raise UserWarning(
"Multigraph.add_graphique : the first coordinates of the sharey Graphique doesn't match "
"with the new coordinates")
else:
sharey = [ii_max, ii_max]
self.occupy_coordinates.extend(occupy_coordinates)
self.list_Graphs.append(graph)
self.list_coords.append(coord)
self.list_sharex_axis_coord.append(sharex)
self.list_sharey_axis_coord.append(sharey)
self.param_subplot.append(kwargs)
[docs]
def config_fig(self, **kwargs) -> None:
"""
Additionals parameters for the Figure saving
Parameters
----------
kwargs
- igsize 2-tuple of floats, default: rcParams["figure.figsize"] (default: [6.4, 4.8])
Figure dimension (width, height) in inches.
- dpi float, default: rcParams["figure.dpi"] (default: 100.0)
Dots per inch.
- facecolor default: rcParams["figure.facecolor"] (default: 'white')
The figure patch facecolor.
- edgecolor default: rcParams["figure.edgecolor"] (default: 'white')
The figure patch edge color.
- linewidth float
The linewidth of the frame (i.e. the edge linewidth of the figure patch).
- frameon bool, default: rcParams["figure.frameon"] (default: True)
If False, suppress drawing the figure background patch.
- layout {'onstrained', 'compressed', 'tight', 'none', LayoutEngine, None}, default: None
The layout mechanism for positioning of plot elements to avoid overlapping Axes decorations
(labels, ticks, etc). Note that layout managers can have significant performance penalties.
'constrained': The constrained layout solver adjusts Axes sizes to avoid overlapping Axes
decorations. Can handle complex plot layouts and colorbars, and is thus recommended.
See Constrained layout guide for examples.
'compressed': uses the same algorithm as 'constrained', but removes extra space between
fixed-aspect-ratio Axes. Best for simple grids of Axes.
'tight': Use the tight layout mechanism. This is a relatively simple algorithm that adjusts the
subplot parameters so that decorations do not overlap.
See Tight layout guide for examples.
'none': Do not use a layout engine.
A LayoutEngine instance. Builtin layout classes are ConstrainedLayoutEngine and TightLayoutEngine,
more easily accessible by 'constrained' and 'tight'. Passing an instance allows third parties to
provide their own layout engine.
If not given, fall back to using the parameters tight_layout and constrained_layout, including their
config defaults rcParams["figure.autolayout"] (default: False) and
rcParams["figure.constrained_layout.use"] (default: False).
- alpha scalar or None
- animated bool
- clip_on bool
- constrained_layout unknown
- constrained_layout_pads unknown
- dpi float
- edgecolor color
- facecolor color
- figheight float
- figwidth float
- frameon bool
- gid str
- in_layout bool
- label object
- layout_engine {'constrained', 'compressed', 'tight', 'none', LayoutEngine, None}
- linewidth number
- mouseover bool
- picker None or bool or float
- rasterized bool
- size_inches (float, float) or float
- sketch_params (scale: float, length: float, randomness: float)
- snap bool or None
- tight_layout unknown
- transform Transform
- url str
- visible bool
- zorder float
Returns
-------
None
See Also
--------
matplotlib.figure.Figure.savefig
"""
self.param_fig.update(kwargs)
[docs]
def config_enrg_fig(self, **kwargs) -> None:
"""
Additionals parameters for the Figure saving
see https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.savefig.html#matplotlib.figure.Figure.savefig
Parameters
----------
kwargs
- figsize 2-tuple of floats, default: rcParams["figure.figsize"] (default: [6.4, 4.8])
Figure dimension (width, height) in inches.
- dpi float, default: rcParams["figure.dpi"] (default: 100.0)
Dots per inch.
- facecolor default: rcParams["figure.facecolor"] (default: 'white')
The figure patch facecolor.
- edgecolor default: rcParams["figure.edgecolor"] (default: 'white')
The figure patch edge color.
- linewidth float
The linewidth of the frame (i.e. the edge linewidth of the figure patch).
- frameon bool, default: rcParams["figure.frameon"] (default: True)
If False, suppress drawing the figure background patch.
- layout {'onstrained', 'compressed', 'tight', 'none', LayoutEngine, None}, default: None
The layout mechanism for positioning of plot elements to avoid overlapping Axes decorations
(labels, ticks, etc). Note that layout managers can have significant performance penalties.
-- 'constrained': The constrained layout solver adjusts Axes sizes to avoid overlapping Axes
decorations. Can handle complex plot layouts and colorbars, and is thus recommended.
See Constrained layout guide for examples.
-- 'compressed': uses the same algorithm as 'constrained', but removes extra space between
fixed-aspect-ratio Axes. Best for simple grids of Axes.
-- 'tight': Use the tight layout mechanism. This is a relatively simple algorithm that adjusts the
subplot parameters so that decorations do not overlap.
See Tight layout guide for examples.
'none': Do not use a layout engine.
A LayoutEngine instance. Builtin layout classes are ConstrainedLayoutEngine and TightLayoutEngine,
more easily accessible by 'constrained' and 'tight'. Passing an instance allows third parties to
provide their own layout engine.
If not given, fall back to using the parameters tight_layout and constrained_layout, including their
config defaults rcParams["figure.autolayout"] (default: False) and
rcParams["figure.constrained_layout.use"] (default: False).
- alpha scalar or None
- animated bool
- clip_on bool
- constrained_layout unknown
- constrained_layout_pads unknown
- dpi float
- edgecolor color
- facecolor color
- figheight float
- figwidth float
- frameon bool
- gid str
- in_layout bool
- label object
- layout_engine {'constrained', 'compressed', 'tight', 'none', LayoutEngine, None}
- linewidth number
- mouseover bool
- picker None or bool or float
- rasterized bool
- size_inches (float, float) or float
- sketch_params (scale: float, length: float, randomness: float)
- snap bool or None
- tight_layout unknown
- transform Transform
- url str
- visible bool
- zorder float
Returns
-------
None
"""
self.param_enrg_fig.update(kwargs)
[docs]
def config_grid_spec(self, **dico) -> None:
"""
Additionals parameters for the grid_spec
Parameters
----------
dico
- left, right, top, bottomfloat, optional : Extent of the subplots as a fraction of figure width or height.
Left cannot be larger than right, and bottom cannot be larger than top.
If not given, the values will be inferred from a figure or rcParams at draw time.
See also GridSpec.get_subplot_params.
- wspace float, optional :
The amount of width reserved for space between subplots, expressed as a fraction
of the average axis width. If not given, the values will be inferred from a figure or rcParams
when necessary. See also GridSpec.get_subplot_params.
- hspace float, optional :
The amount of height reserved for space between subplots, expressed as a
fraction of the average axis height. If not given, the values will be inferred from a figure or rcParams
when necessary. See also GridSpec.get_subplot_params.
- width_ratios array-like of length ncols, optional :
Defines the relative widths of the columns.
Each column gets a relative width of width_ratios[i] / sum(width_ratios).
If not given, all columns will have the same width.
- height_ratios array-like of length nrows, optional
Defines the relative heights of the rows.
Each row gets a relative height of height_ratios[i] / sum(height_ratios).
If not given, all rows will have the same height.
Returns
-------
None
See Also
--------
matplotlib.gridspec.GridSpec
"""
self.param_grid_spec.update(dico)
[docs]
def config_font(self, **dico) -> None:
"""
Global font parameter
Parameters
----------
kwargs
'family' : 'fantasy','monospace','sans-serif','serif','cursive'
'styles' : 'normal', 'italic', 'oblique'
'size' : valeur numérique
'variants' : 'normal', 'small-caps'
'weight' : 'light', 'normal', 'medium', 'semibold', 'bold', 'heavy', 'black'
Returns
-------
None
"""
k: list[str] = dico.keys()
vals: list = dico.values()
dico: dict = {}
for K, L in zip(k, vals):
if "font." not in K:
dico['font.' + K] = L
else:
dico[K] = L
self.param_font.update(dico)
[docs]
def plot(self) -> None:
"""
Plot all the Multigraph's elements
Parameters
----------
in_Multigraph: bool, optional, default=False
If the Graphique is plotted in a Multigraph, it deactivate globals parameters such as
the police or the style.
Returns
-------
None
"""
if self.style in plt.style.available or self.style == 'default':
plt.style.use(self.style)
else:
print("The style ", self.style, " is not awalible. \n Please use :\n", plt.style.available)
with mpl.rc_context(self.param_font):
param_fig = {'figsize': [6.4 * self.ncols, 4.8 * self.nrows]}
if len(self.param_fig) > 0:
param_fig.update(self.param_fig)
self.fig = plt.figure(**param_fig)
spec = self.fig.add_gridspec(self.nrows, self.ncols, **self.param_grid_spec)
for (graph, coords, sharex, sharey, args) in zip(self.list_Graphs, self.list_coords,
self.list_sharex_axis_coord, self.list_sharey_axis_coord,
self.param_subplot):
if isinstance(sharex[0], int) and sharex[0] == ii_max:
sharex = None
elif isinstance(sharex, list):
sharex = self.list_Graphs[self.list_coords.index(sharex)].ax
# else: sharex is bool
if isinstance(sharey[0], int) and sharey[0] == ii_max:
sharey = None
elif isinstance(sharey, list):
sharey = self.list_Graphs[self.list_coords.index(sharey)].ax
projection: str = None
graph.fig = self.fig
if "projection" in graph.param_ax:
projection = graph.param_ax["projection"]
if isinstance(coords[0], int) and isinstance(coords[1], int):
# graph.ax = self.fig.add_subplot(spec[coords[0], coords[1]], projection=projection, sharex=sharex,
# sharey=sharey, **args)
graph.ax = self.fig.add_subplot(spec[coords[0], coords[1]], projection=projection, **args)
if sharex is not None:
graph.ax.sharex(sharex)
if sharey is not None:
graph.ax.sharey(sharey)
elif isinstance(coords[0], int):
# graph.ax = self.fig.add_subplot(spec[coords[0], coords[1][0]:coords[1][1] + 1], projection=projection,
# sharex=sharex, sharey=sharey, **args)
graph.ax = self.fig.add_subplot(spec[coords[0], coords[1][0]:coords[1][1] + 1],
projection=projection,
**args)
if sharex is not None:
graph.ax.sharex(sharex)
if sharey is not None:
graph.ax.sharey(sharey)
elif isinstance(coords[1], int):
# graph.ax = self.fig.add_subplot(spec[coords[0][0]:coords[0][1] + 1, coords[1]], projection=projection,
# sharex=sharex, sharey=sharey, **args)
#
graph.ax = self.fig.add_subplot(spec[coords[0][0]:coords[0][1] + 1, coords[1]],
projection=projection,
**args)
if sharex is not None:
graph.ax.sharex(sharex)
if sharey is not None:
graph.ax.sharey(sharey)
else:
# graph.ax = self.fig.add_subplot(spec[coords[0][0]:coords[0][1] + 1, coords[1][0]:coords[1][1] + 1],
# projection=projection, sharex=sharex, sharey=sharey, **args)
graph.ax = self.fig.add_subplot(spec[coords[0][0]:coords[0][1] + 1, coords[1][0]:coords[1][1] + 1],
projection=projection, **args)
if sharex is not None:
graph.ax.sharex(sharex)
if sharey is not None:
graph.ax.sharey(sharey)
graph.plot(in_Multigraph=True)
self.fig.tight_layout()
[docs]
def show(self) -> None:
"""
Show the Graphique
Returns
-------
None
"""
self.plot()
self.fig.tight_layout()
plt.show()
self.fig = None
for graph in self.list_Graphs:
graph.fig = None
graph.ax = None