####################################################################################################################################
####################################################################################################################################
####
#### MIT License
####
#### ParaMonte: plain powerful parallel Monte Carlo library.
####
#### Copyright (C) 2012-present, The Computational Data Science Lab
####
#### This file is part of the ParaMonte library.
####
#### Permission is hereby granted, free of charge, to any person obtaining a
#### copy of this software and associated documentation files (the "Software"),
#### to deal in the Software without restriction, including without limitation
#### the rights to use, copy, modify, merge, publish, distribute, sublicense,
#### and/or sell copies of the Software, and to permit persons to whom the
#### Software is furnished to do so, subject to the following conditions:
####
#### The above copyright notice and this permission notice shall be
#### included in all copies or substantial portions of the Software.
####
#### THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#### EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#### MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
#### IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
#### DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
#### OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
#### OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
####
#### ACKNOWLEDGMENT
####
#### ParaMonte is an honor-ware and its currency is acknowledgment and citations.
#### As per the ParaMonte library license agreement terms, if you use any parts of
#### this library for any purposes, kindly acknowledge the use of ParaMonte in your
#### work (education/research/industry/development/...) by citing the ParaMonte
#### library as described on this page:
####
#### https://github.com/cdslaborg/paramonte/blob/main/ACKNOWLEDGMENT.md
####
####################################################################################################################################
####################################################################################################################################
import numpy as np
import typing as tp
import weakref as wref
import _paramonte as pm
import _pmutils as pmutils
from paramonte.vis.Target import Target
from paramonte.vis._BasePlot import BasePlot
Struct = pmutils.Struct
newline = pmutils.newline
####################################################################################################################################
#### LineScatterPlot class
####################################################################################################################################
[docs]class LineScatterPlot(BasePlot):
"""
This is the LineScatterPlot class for generating instances
of line or scatter plots or the combination of the two in
two or three dimensions based on the visualization tools
of the ``matplotlib`` and ``seaborn`` Python libraries.
**Usage**
First generate an object of this class by optionally
passing the following parameters described below. Then call
the ``make()`` method. The generated object is also callable
with the same input parameters as the object's constructor.
**Parameters**
plotType
A string indicating the name of the plot to be constructed.
dataFrame (optional)
A pandas dataFrame whose data will be plotted.
methodName (optional)
The name of the ParaMonte sample requesting the BasePlot.
reportEnabled (optional)
A boolean whose value indicates whether guidelines should be
printed in the standard output.
resetPlot (optional)
A function that resets the properties of the plot as desired
from outside. If provided, a pointer to this function will be
saved for future internal usage.
**Attributes**
xcolumns
An attribute that determines the columns of dataFrame
to be visualized as the X-axis. It can have three forms:
1. A list of column indices in dataFrame.
2. A list of column names in dataFrame.columns.
3. A ``range(start,stop,step)`` of column indices.
Examples:
1. ``xcolumns = [0,1,4,3]``
2. ``xcolumns = ["SampleLogFunc","SampleVariable1"]``
3. ``xcolumns = range(17,7,-2)``
The default behavior includes all columns of the dataFrame.
ycolumns
An attribute that determines the columns of dataFrame
to be visualized as the Y-axis. It can have three forms:
1. A list of column indices in dataFrame.
2. A list of column names in dataFrame.columns.
3. A ``range(start,stop,step)`` of column indices.
Examples:
1. ``ycolumns = [0,1,4,3]``
2. ``ycolumns = ["SampleLogFunc","SampleVariable1"]``
3. ``ycolumns = range(17,7,-2)``
The default behavior includes all columns of the dataFrame.
zcolumns (exists only in 3D plot objects)
An attribute that determines the columns of dataFrame
to be visualized as the Z-axis. It can have three forms:
1. A list of column indices in dataFrame.
2. A list of column names in dataFrame.columns.
3. A ``range(start,stop,step)`` of column indices.
Examples:
1. ``zcolumns = [0,1,4,3]``
2. ``zcolumns = ["SampleLogFunc","SampleVariable1"]``
3. ``zcolumns = range(17,7,-2)``
The default behavior includes all columns of the dataFrame.
ccolumns
An attribute that determines the columns of dataFrame
to be used for color mapping. It can have three forms:
1. A list of column indices in dataFrame.
2. A list of column names in dataFrame.columns.
3. A ``range(start,stop,step)`` of column indices.
Examples:
1. ``ccolumns = [0,1,4,3]``
2. ``ccolumns = ["SampleLogFunc","SampleVariable1"]``
3. ``ccolumns = range(17,7,-2)``
If ``ccolumns`` is set to ``None``, then no color-mapping
will be made. If it is set to an empty list ``[]``, then
the values from the ``rows`` attribute will be used for
color-mapping.
rows
An attribute that determines the rows of dataFrame to be
visualized. It can be either:
1. A ``range(start,stop,step)``, or,
2. A list of row indices in dataFrame.index.
Examples:
1. ``rows = range(17,7,-2)``
2. ``rows = [i for i in range(7,17)]``
The default behavior includes all rows of the dataFrame.
plot (exists only for line or lineScatter plots in 2D and 3D)
A structure with two attributes:
enabled
A boolean indicating whether a call to the ``plot()``
function of the matplotlib library should be made
or not.
kws
A structure whose components are directly passed as
keyword arguments to the ``plot()`` function.
Example usage:
.. code-block:: python
plot.enabled = True
plot.kws.linewidth = 1
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
scatter (exists only for scatter / lineScatter plots in 2D and 3D)
A structure with two attributes:
enabled
A boolean indicating whether a call to the
``scatter()`` function of the matplotlib library
should be made or not.
kws
A structure whose components are directly passed as
keyword arguments to the ``scatter()`` function.
Example usage:
.. code-block:: python
scatter.enabled = True
scatter.kws.s = 2
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
lineCollection (exists only for 2D / 3D line / lineScatter plots)
A structure with two attributes:
enabled
A boolean indicating whether a call to the
``LineCollection()`` class of the matplotlib
library should be made or not. This will result
in line plots that are color-mapped.
kws
A structure whose components are directly passed as
keyword arguments to the ``LineCollection()`` class
of matplotlib library.
Example usage:
.. code-block:: python
lineCollection.enabled = True
lineCollection.kws.linewidth = 1
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
set
A structure with two attributes:
enabled
A boolean indicating whether a call to the ``set()``
function of the seaborn library should be made or not.
kws
A structure whose components are directly passed as
keyword arguments to the ``set()`` function.
Example usage:
.. code-block:: python
set.kws.style = "darkgrid"
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
axes (available only in 1D and 2D plots)
A structure with one attribute:
kws
A structure whose components are directly passed as
keyword arguments to the ``gca()`` function of the
matplotlib library.
Example usage:
.. code-block:: python
axes.kws.facecolor = "w"
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
axes3d (available only in 3D plots)
A structure with one attribute:
kws
A structure whose components are directly passed as
keyword arguments to the ``Axes3D()`` function of the
matplotlib library.
Example usage:
.. code-block:: python
axes3d.kws.facecolor = "w"
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
figure
A structure with two attributes:
enabled
A boolean indicating whether a call to the ``figure()``
function of the matplotlib library should be made or not.
If a call is made, a new figure will be generated.
Otherwise, the current active figure will be used.
kws
A structure whose components are directly passed as
keyword arguments to the ``figure()`` function.
Example usage:
.. code-block:: python
figure.kws.facecolor = "w"
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
colorbar (exists only for plots that require colorbar)
A structure with two attributes:
enabled
A boolean indicating whether a call to the ``colorbar()``
function of the matplotlib library should be made or not.
If a call is made, a new figure will be generated.
Otherwise, the current active figure will be used.
kws
A structure whose components are directly passed as
keyword arguments to the ``colorbar()`` function of
the matplotlib library.
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
A colorbar will be added to a plot only if a color-mappings
is requested in the plot.
legend (may not exist for some types of plots)
A structure with two attributes:
enabled
A boolean indicating whether a call to the ``legend()``
function of the matplotlib library should be made or not.
If a call is made, a new figure will be generated.
Otherwise, the current active figure will be used.
kws
A structure whose components are directly passed as
keyword arguments to the ``legend()`` function.
Example usage:
.. code-block:: python
legend.kws.labels = ["Variable1", "Variable2"]
**NOTE**
If a desired property is missing among the ``kws``
attributes, simply add the field and its value to
the component.
A legend will be added to a plot only if no color-mappings are
requested in the plot.
currentFig
A structure whose attributes are the outputs of various plotting
tools used to make the current figure. These include the handle
to the current figure, the handle to the current axes in the plot,
the handle to the colorbar (if any exists), and other Python
plotting tools used to make to generate the figure.
target (available only in 1D and 2D plot objects)
A callable object of the ParaMonte library's ``Target`` class
which can be used to add target point or lines to the current
active plot.
**Returns**
An object of class ``LineScatterPlot``.
---------------------------------------------------------------------------
"""
################################################################################################################################
#### __init__
################################################################################################################################
def __init__( self
, plotType # : str
, dataFrame = None # : tp.Optional[ pd.DataFrame ] = None
, methodName = "ParaMonte" # : tp.Optional[ str ] = "ParaMonte"
, reportEnabled = True # : tp.Optional[ bool ] = True
, resetPlot = None
):
super().__init__( plotType = plotType
, dataFrame = dataFrame
, methodName = methodName
, reportEnabled = reportEnabled
, resetPlot = resetPlot
)
self._reset()
if resetPlot is None: self._resetPlot = self._reset
self._progress.note()
################################################################################################################################
#### _reset
################################################################################################################################
[docs] def _reset(self):
super()._reset()
self._indexOffset = 1
self.xcolumns = None
self.ycolumns = None
self.ccolumns = [] # indicates the use of default column for colormap. To turn off
self._xlabel = None
self._ylabel = None
self._zlabel = None
self._xlimit = None
self._ylimit = None
self._zlimit = None
self._xscale = None
self._yscale = None
self._zscale = None
if not self._type.is3d: self.target = Target()
if self._type.isLine:
self.plot = Struct()
self.plot.enabled = False
self.plot.kws = Struct()
self.lineCollection = Struct()
self.lineCollection.kws = Struct()
self.lineCollection.enabled = True
if self._type.isScatter:
self.scatter = Struct()
self.scatter.enabled = True
self.scatter.kws = Struct()
if self._type.is3d:
self.zcolumns = []
self.colorbar = Struct()
self.colorbar.kws = Struct()
if (self._type.isScatter and self.ccolumns is not None) or (self._type.isLine and self.lineCollection.enabled):
self.colorbar.enabled = True
else:
self.colorbar.enabled = False
self._isdryrun = True
self.make()
self._isdryrun = False
################################################################################################################################
#### __call__
################################################################################################################################
[docs] def __call__( self
, reself : tp.Optional[ bool ] = False
, **kwargs
):
"""
Call the ``make()`` method of the current
instance of the class.
**Parameters**
Any arguments that can be passed to the
``make()`` method of the plot object.
**Returns**
Any return value from the ``make()``
method of the plot object.
"""
return self.make(reself, **kwargs)
################################################################################################################################
#### make
################################################################################################################################
[docs] def make( self
, reself : tp.Optional[ bool ] = False
, **kwargs
):
"""
Generate a line/scatter plot from the
selected columns of the object's dataframe.
**Parameters**
reself
A logical variable. If ``True``, an instance of
the object will be returned to the calling routine
upon exit. The default value is ``False``.
**Returns**
The object self if ``reself = True`` otherwise, ``None``.
However, this method causes side-effects by manipulating
the existing attributes of the object.
"""
for key in kwargs.keys():
if hasattr(self,key):
setattr(self, key, kwargs[key])
elif key=="dataFrame":
setattr( self, "_dfref", wref.ref(kwargs[key]) )
else:
raise Exception ( "Unrecognized input '"+key+"' class attribute detected." + newline
+ self._getDocString()
)
# set what to plot
cEnabled = self.ccolumns is not None
from collections.abc import Iterable
if self.ccolumns is not None and not isinstance(self.ccolumns, Iterable): self.ccolumns = [self.ccolumns]
# if no colormap, then
if self._type.isLine and not cEnabled: self.plot.enabled = True
############################################################################################################################
#### scatter plot properties
############################################################################################################################
if self._type.isScatter:
if isinstance(self.scatter.kws,Struct):
if "s" not in vars(self.scatter.kws).keys(): self.scatter.kws.s = 2
if "c" not in vars(self.scatter.kws).keys(): self.scatter.kws.c = None
if "cmap" not in vars(self.scatter.kws).keys() or self.scatter.kws.cmap is None: self.scatter.kws.cmap = "autumn"
if "alpha" not in vars(self.scatter.kws).keys(): self.scatter.kws.alpha = 1
if "edgecolors" not in vars(self.scatter.kws).keys(): self.scatter.kws.edgecolors = None
if "zorder" not in vars(self.scatter.kws).keys(): self.scatter.kws.zorder = 2
if not cEnabled: self.scatter.kws.cmap = None
else:
raise Exception ( "The scatter.kws component of the current LineScatterPlot object must" + newline
+ "be an object of class Struct(), essentially a structure with components" + newline
+ "whose names are the input arguments to the scatter() function of the" + newline
+ "matplotlib library." + newline
+ self._getDocString()
)
############################################################################################################################
#### line plot properties
############################################################################################################################
if self._type.isLine:
if isinstance(self.plot.kws,Struct):
if "linewidth" in vars(self.plot.kws).keys():
if self.plot.kws.linewidth==0: self.plot.kws.linewidth = 1
else:
self.plot.kws.linewidth = 1
if "zorder" not in vars(self.plot.kws).keys(): self.plot.kws.zorder = 1
else:
raise Exception ( "The plot.kws component of the current LineScatterPlot object must" + newline
+ "be an object of class Struct(), essentially a structure with components" + newline
+ "whose names are the input arguments to the plot() function of the" + newline
+ "matplotlib library." + newline
+ self._getDocString()
)
if isinstance(self.lineCollection.kws, Struct):
if "cmap" not in vars(self.lineCollection.kws).keys() or self.lineCollection.kws.cmap is None: self.lineCollection.kws.cmap = "autumn"
if "alpha" not in vars(self.lineCollection.kws).keys(): self.lineCollection.kws.alpha = 1
if "linewidth" not in vars(self.lineCollection.kws).keys(): self.lineCollection.kws.linewidth = 1
else:
objectType = "LineCollection"
if self._type.is3d: objectType = "Line3DCollection"
raise Exception ( "The lineCollection.kws component of the current LineScatterPlot object must" + newline
+ "be an object of class Struct(), essentially a structure with components" + newline
+ "whose names are the input arguments to the " + objectType + "() class of the" + newline
+ "matplotlib library." + newline
+ self._getDocString()
)
############################################################################################################################
#### legend properties
############################################################################################################################
if self.legend.enabled:
if not isinstance(self.legend.kws,Struct):
raise Exception ( "The legend.kws component of the current LineScatterPlot object must" + newline
+ "be an object of class Struct(), essentially a structure with components" + newline
+ "whose names are the input arguments to the legend() function of the" + newline
+ "matplotlib library." + newline
+ self._getDocString()
)
############################################################################################################################
#### figure properties
############################################################################################################################
if self.figure.enabled:
if isinstance(self.figure.kws, Struct):
if "dpi" not in vars(self.figure.kws).keys(): self.figure.kws.dpi = 150
if "facecolor" not in vars(self.figure.kws).keys(): self.figure.kws.facecolor = "w"
if "edgecolor" not in vars(self.figure.kws).keys(): self.figure.kws.edgecolor = "w"
else:
raise Exception ( "The figure.kws component of the current LineScatterPlot object must" + newline
+ "be an object of class Struct(), essentially a structure with components" + newline
+ "whose names are the input arguments to the figure() function of the" + newline
+ "matplotlib library." + newline
+ self._getDocString()
)
############################################################################################################################
############################################################################################################################
if self._isdryrun: return
############################################################################################################################
############################################################################################################################
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
if self._type.is3d: from mpl_toolkits.mplot3d.art3d import Line3DCollection
plt.ion() # turn on the interactive mode. Used to detach the figure from the command line in ipython
############################################################################################################################
#### generate figure and axes if needed
############################################################################################################################
self._constructBasePlot()
############################################################################################################################
#### check data type
############################################################################################################################
self._checkDataType()
############################################################################################################################
#### check rows presence. This must be checked here, because it depends on the integrity of the in input dataFrame.
############################################################################################################################
if self.rows is None: self.rows = range(len(self._dfref().index))
############################################################################################################################
#### check columns presence. This must be checked here, because it depends on the integrity of the in input dataFrame.
############################################################################################################################
if self.xcolumns is None:
lgxicol = 0
xcolindex = []
xcolnames = ["Count"]
if self._type.isScatter : self.scatter._xvalues = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
if self._type.isLine : self.plot._xvalues = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
else:
xcolnames, xcolindex = pm.dfutils.getColNamesIndex(self._dfref().columns,self.xcolumns)
if self.ycolumns is None:
lgyicol = 0
ycolindex = []
ycolnames = ["Count"]
if self._type.isScatter : self.scatter._yvalues = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
if self._type.isLine : self.plot._yvalues = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
else:
ycolnames, ycolindex = pm.dfutils.getColNamesIndex(self._dfref().columns,self.ycolumns)
if self._type.is3d:
if self.zcolumns is None:
lgzicol = 0
zcolindex = []
zcolnames = ["Count"]
if self._type.isScatter : self.scatter._zvalues = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
if self._type.isLine : self.plot._zvalues = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
else:
zcolnames, zcolindex = pm.dfutils.getColNamesIndex(self._dfref().columns, self.zcolumns)
############################################################################################################################
#### set colormap data
############################################################################################################################
if cEnabled:
if len(self.ccolumns)==0:
ccolindex = []
ccolnames = ["Count"]
if self._type.isScatter : self.scatter.kws.c = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
if self._type.isLine : cdata = np.array( self._dfref().index[self.rows] + self._indexOffset ).flatten()
else:
ccolnames, ccolindex = pm.dfutils.getColNamesIndex(self._dfref().columns,self.ccolumns)
else:
ccolindex = []
ccolnames = []
#self.scatter.kws.c = None
############################################################################################################################
#### check the consistency of the lengths
############################################################################################################################
xcolindexlen = len(xcolindex)
ycolindexlen = len(ycolindex)
ccolindexlen = len(ccolindex)
maxLenColumns = np.max ( [ xcolindexlen
, ycolindexlen
, ccolindexlen
]
)
if xcolindexlen!=maxLenColumns and xcolindexlen>1: raise Exception("length of xcolumns must be either 1 or equal to the lengths of ycolumns or ccolumns.")
if ycolindexlen!=maxLenColumns and ycolindexlen>1: raise Exception("length of ycolumns must be either 1 or equal to the lengths of xcolumns or ccolumns.")
if ccolindexlen!=maxLenColumns and ccolindexlen>1: raise Exception("length of ccolumns must be either 1 or equal to the lengths of xcolumns or ycolumns.")
if self._type.is3d:
zcolindexlen = len(zcolindex)
if zcolindexlen!=maxLenColumns and zcolindexlen>1: raise Exception("length of zcolumns must be either 1 or equal to the lengths of xcolumns or ycolumns.")
############################################################################################################################
#### assign data in case of single column assignments
############################################################################################################################
if xcolindexlen==1:
lgxicol = 0
if self._type.isScatter : self.scatter._xvalues = self._dfref().iloc[self.rows,xcolindex].values.flatten()
if self._type.isLine : self.plot._xvalues = self._dfref().iloc[self.rows,xcolindex].values.flatten()
if ycolindexlen==1:
lgyicol = 0
if self._type.isScatter : self.scatter._yvalues = self._dfref().iloc[self.rows,ycolindex].values.flatten()
if self._type.isLine : self.plot._yvalues = self._dfref().iloc[self.rows,ycolindex].values.flatten()
if self._type.is3d:
if zcolindexlen==1:
lgzicol = 0
if self._type.isScatter : self.scatter._zvalues = self._dfref().iloc[self.rows,zcolindex].values.flatten()
if self._type.isLine : self.plot._zvalues = self._dfref().iloc[self.rows,zcolindex].values.flatten()
if cEnabled:
if ccolindexlen==1:
if self._type.isScatter : self.scatter.kws.c = self._dfref().iloc[self.rows,ccolindex].values.flatten()
if self._type.isLine : cdata = self._dfref().iloc[self.rows,ccolindex].values.flatten()
############################################################################################################################
#### add line/scatter plot
############################################################################################################################
if self.legend.enabled: self.legend._labels = []
if self._type.isScatter and self.scatter.enabled: self.currentFig.scatterList = []
if self._type.isLine:
if self.plot.enabled: self.currentFig.plotList = []
if cEnabled and self.lineCollection.enabled:
self.currentFig.lineCollectionList = []
self.currentFig.plotList = []
for i in range(maxLenColumns):
if xcolindexlen>1:
lgxicol = i
if self._type.isScatter : self.scatter._xvalues = self._dfref().iloc[self.rows,xcolindex[i]].values.flatten()
if self._type.isLine : self.plot._xvalues = self._dfref().iloc[self.rows,xcolindex[i]].values.flatten()
if ycolindexlen>1:
lgyicol = i
if self._type.isScatter : self.scatter._yvalues = self._dfref().iloc[self.rows,ycolindex[i]].values.flatten()
if self._type.isLine : self.plot._yvalues = self._dfref().iloc[self.rows,ycolindex[i]].values.flatten()
if cEnabled:
if ccolindexlen>1:
if self._type.isScatter : self.scatter.kws.c = self._dfref().iloc[self.rows,ccolindex[i]].values.flatten()
if self._type.isLine : cdata = self._dfref().iloc[self.rows,ccolindex[i]].values.flatten()
if self.legend.enabled:
if xcolindexlen<2 and ycolindexlen>1:
self.legend._labels.append(ycolnames[lgyicol])
elif xcolindexlen>1 and ycolindexlen<2:
self.legend._labels.append(xcolnames[lgxicol])
else:
self.legend._labels.append( xcolnames[lgxicol] + "-" + ycolnames[lgyicol] )
if self._type.is3d:
if zcolindexlen>1:
lgzicol = i
if self._type.isScatter : self.scatter._zvalues = self._dfref().iloc[self.rows,zcolindex[i]].values.flatten()
if self._type.isLine : self.plot._zvalues = self._dfref().iloc[self.rows,zcolindex[i]].values.flatten()
if self.legend.enabled:
if zcolindexlen>1: self.legend._labels[-1] += "-" + zcolnames[lgzicol]
########################################################################################################################
#### add scatter plot
########################################################################################################################
if self._type.isScatter and self.scatter.enabled:
if self._type.is3d:
self.currentFig.scatterList.append( self.currentFig.axes.scatter( self.scatter._xvalues
, self.scatter._yvalues
, self.scatter._zvalues
, **vars(self.scatter.kws)
) )
else:
self.currentFig.scatterList.append( self.currentFig.axes.scatter( self.scatter._xvalues
, self.scatter._yvalues
, **vars(self.scatter.kws)
) )
########################################################################################################################
#### add line plot
########################################################################################################################
if self._type.isLine:
if self.plot.enabled:
if self._type.is3d:
self.currentFig.plotList.append ( self.currentFig.axes.plot ( self.plot._xvalues
, self.plot._yvalues
, self.plot._zvalues
, **vars(self.plot.kws)
) )
else:
self.currentFig.plotList.append ( self.currentFig.axes.plot ( self.plot._xvalues
, self.plot._yvalues
, **vars(self.plot.kws)
) )
if cEnabled and self.lineCollection.enabled:
self.lineCollection.kws.norm = norm = plt.Normalize(cdata.min(), cdata.max())
if self._type.is3d:
# properly and automatically set the axes limits via plot()
self.currentFig.plotList.append ( self.currentFig.axes.plot ( self.plot._xvalues
, self.plot._yvalues
, self.plot._zvalues
, linewidth = 0
) )
# now add the lineCollection
points = np.array([self.plot._xvalues, self.plot._yvalues, self.plot._zvalues]).T.reshape(-1, 1, 3)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
lineCollection = Line3DCollection( segments, **vars(self.lineCollection.kws) )
else:
# properly and automatically set the axes limits via plot()
self.currentFig.plotList.append ( self.currentFig.axes.plot ( self.plot._xvalues
, self.plot._yvalues
, linewidth = 0
) )
# now add the lineCollection
points = np.array([self.plot._xvalues, self.plot._yvalues]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
lineCollection = LineCollection( segments, **vars(self.lineCollection.kws) )
lineCollection.set_array(cdata)
#lineCollection.set_linewidth(0.5)
#lineCollection.set_solid_capstyle("round")
self.currentFig.lineCollectionList.append( self.currentFig.axes.add_collection(lineCollection) )
############################################################################################################################
#### add colorbar
############################################################################################################################
cbarEnabled = cEnabled and self.colorbar.enabled and (ccolindexlen<2) # and (not hasattr(self.currentFig,"colorbar"))
if cbarEnabled:
self.colorbar.kws.mappable = None
if self._type.isLine and self.lineCollection.enabled:
self.colorbar.kws.mappable = self.currentFig.lineCollectionList[0]
elif self._type.isScatter and self.scatter.enabled:
self.colorbar.kws.mappable = self.currentFig.scatterList[0]
if self.colorbar.kws.mappable is not None:
self.colorbar.kws.ax = self.currentFig.axes
self.currentFig.colorbar = self.currentFig.figure.colorbar( **vars(self.colorbar.kws) )
self.currentFig.colorbar.set_label( label = ", ".join(ccolnames) )
############################################################################################################################
#### set axes scales
############################################################################################################################
if self._xscale is not None: self.currentFig.axes.set_xscale(self._xscale)
if self._yscale is not None: self.currentFig.axes.set_yscale(self._yscale)
if self._zscale is not None and self._type.is3d: self.currentFig.axes.set_zscale(self._zscale)
############################################################################################################################
#### set axes limits
############################################################################################################################
if self._xlimit is not None:
currentLim = list(self.currentFig.axes.get_xlim())
if self._xlimit[0] is not None: currentLim[0] = self._xlimit[0]
if self._xlimit[1] is not None: currentLim[1] = self._xlimit[1]
self.currentFig.axes.set_xlim(currentLim)
if self._ylimit is not None:
currentLim = list(self.currentFig.axes.get_ylim())
if self._ylimit[0] is not None: currentLim[0] = self._ylimit[0]
if self._ylimit[1] is not None: currentLim[1] = self._ylimit[1]
self.currentFig.axes.set_ylim(currentLim)
if self._zlimit is not None and self._type.is3d:
currentLim = list(self.currentFig.axes.get_zlim())
if self._zlimit[0] is not None: currentLim[0] = self._zlimit[0]
if self._zlimit[1] is not None: currentLim[1] = self._zlimit[1]
self.currentFig.axes.set_zlim(currentLim)
############################################################################################################################
#### add axes labels
############################################################################################################################
if self._xlabel is None:
if xcolindexlen>1:
self.currentFig.axes.set_xlabel("Variable Values")
else:
self.currentFig.axes.set_xlabel(xcolnames[0])
else:
self.currentFig.axes.set_xlabel(self._xlabel)
if self._ylabel is None:
if ycolindexlen>1:
self.currentFig.axes.set_ylabel("Variable Values")
else:
self.currentFig.axes.set_ylabel(ycolnames[0])
else:
self.currentFig.axes.set_ylabel(self._ylabel)
if self._type.is3d:
if self._zlabel is None:
if zcolindexlen>1:
self.currentFig.axes.set_zlabel("Variable Values")
else:
self.currentFig.axes.set_zlabel(zcolnames[0])
else:
self.currentFig.axes.set_zlabel(self._zlabel)
############################################################################################################################
#### set legend and other BasePlot properties
############################################################################################################################
self._finalizeBasePlot()
if not self._type.is3d: self.target.currentFig.axes = self.currentFig.axes
############################################################################################################################
if reself: return self
################################################################################################################################
#### _getDocString
################################################################################################################################
[docs] def _getDocString(self):
docString = newline \
+ "Here is the help information on the LineScatterPlot class:" + newline \
+ newline \
+ self.__doc__ \
+ newline \
+ "Here is the help information on the parent BasePlot class:" + newline \
+ newline \
+ super().__doc__
return docString
################################################################################################################################
#### helpme
################################################################################################################################
[docs] def helpme(self, topic=None):
"""
Print the documentation for the input string topic.
If the topic does not exist, the documentation for
the object will be printed.
**Parameters**
topic (optional)
A string containing the name of the object
for which help is needed.
**Returns**
None
**Example**
.. code-block:: python
:linenos:
helpme()
helpme("make")
helpme("helpme")
helpme("getLogLinSpace")
"""
try:
exec("print(self."+topic+".__doc__)")
except:
print(self._getDocString())
return None
################################################################################################################################