Source code for paramonte.vis.Target

####################################################################################################################################
####################################################################################################################################
####
####   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 typing as tp
import _pmutils as pmutils

Struct = pmutils.Struct
newline = pmutils.newline

####################################################################################################################################
#### Target class
####################################################################################################################################

[docs]class Target: """ This is the Target class for generating instances of a target on the current active figure and axis. **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** values (optional) A pair (list, array, or tuple) of floats, representing the (x,y) coordinates of the target. axes The axes object to which the target must be added. The default is ``None`` in which case the output of the matplotlib's ``gca()`` function will be used to get the current active axes. **Attributes** All of the parameters described above, except ``axes``. The input axes object (whether user-provided or automatically fetched) will be stored as a component of the object's attribute ``currentFig``. axvline (optional) A structure with two components: enabled A logical value, indicating whether an ``axvline`` will be added to the plot or not. If set to ``False`` no vertical target line will be added. kws A structure whose components will be passed to the matplotlib's ``axvline()`` function. For example: .. code-block:: python :linenos: axvline.kws.linewidth = 0.5 axvline.kws.color = "orangered" axvline.kws.linestyle = ":" axvline.kws.ymin = 0.1 axvline.kws.ymax = 1.9 **NOTE** If a desired property is missing in the structure, simply add the property and its value to the structure. axhline (optional) A structure with two components: enabled A logical value, indicating whether an ``axhline`` will be added to the plot or not. If set to ``False`` no horizontal target line will be added. kws A structure whose components will be passed to the matplotlib's ``axhline()`` function. For example: .. code-block:: python :linenos: axhline.kws.linewidth = 0.5 axhline.kws.color = "orangered" axhline.kws.linestyle = ":" axhline.kws.xmin = 0.1 axhline.kws.xmax = 1.9 **NOTE** If a desired property is missing in the structure, simply add the property and its value to the structure. scatter (optional) A structure with two components: enabled A logical value, indicating whether an ``scatter`` will be added to the plot or not. If set to ``False`` no target scatter circle will be added. kws A structure whose components will be passed to the matplotlib's ``scatter()`` function. For example: .. code-block:: python scatter.kws.s = 20 scatter.kws.color = "orangered" NOTE: If a desired property is missing in the NOTE: structure, simply add the property and NOTE: its value to the structure. currentFig An structure which is initially ``None``, but upon making a plot, is populated with attributes representing all outputs from matplotlib function calls, with the following attributes: axes The output of matplotlib's ``gca()`` function or, the input axes object by the user. axhline The output of matplotlib's ``axhline()`` function. axvline The output of matplotlib's ``axvline()`` function. scatter The output of matplotlib's ``scatter()`` function. **Returns** self An object of class ``Target``. --------------------------------------------------------------------------- """ ################################################################################################################################ #### __init__ ################################################################################################################################ def __init__( self , values : tp.Optional[ tp.Union[ tp.List[int] , tp.List[float] ] ] = [0,0] , axes = None #: tp.Optional[ plt.axes ] = None ): self.label = None self.value = values self.axvline = Struct() self.axvline.kws = Struct() self.axvline.enabled = True self.axhline = Struct() self.axhline.kws = Struct() self.axhline.enabled = True self.scatter = Struct() self.scatter.kws = Struct() self.scatter.enabled = True self.currentFig = Struct() self.currentFig.axes = axes if self.currentFig.axes is not None: self.currentFig.figure = self.currentFig.axes.get_figure() 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 target object. **Returns** Any return value from the ``make()`` method of the target object. """ return self.make(reself, **kwargs)
################################################################################################################################ #### make ################################################################################################################################
[docs] def make( self , reself : tp.Optional[ bool ] = False , **kwargs ): """ Add a target on an existing plot (the current active axes object) based on the ``values`` attribute of the target object. **Parameters** reself A logical variable. If ``True``, an instance of the object will be returned upon exit to the calling routine. 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, val in kwargs.items(): if hasattr(self,key): setattr(self, key, val) elif key=="axes": self.currentFig.axes = val self.currentFig.figure = self.currentFig.axes.get_figure() else: raise Exception ( "Unrecognized input '"+key+"' class attribute detected." + newline + self._getDocString() ) # set what to plot if not isinstance(self.value, list): self.value = [self.value] ############################################################################################################################ #### setup the vertical line ############################################################################################################################ if self.axvline.enabled: if isinstance(self.axvline.kws,Struct): #if targetExists: self.axvline.kws.x = self.value[0] if "linewidth" not in vars(self.axvline.kws).keys(): self.axvline.kws.linewidth = 0.5 if "linestyle" not in vars(self.axvline.kws).keys(): self.axvline.kws.linestyle = "-" if "zorder" not in vars(self.axvline.kws).keys(): self.axvline.kws.zorder = 1000 if "color" not in vars(self.axvline.kws).keys(): self.axvline.kws.color = "orangered" else: raise Exception ( "The axvline.kws component of the current Target object must" + newline + "be an object of class Struct(), essentially a structure with components" + newline + "whose names are the input arguments to the axvline() function of the" + newline + "matplotlib library." + newline + self._getDocString() ) ############################################################################################################################ #### setup the horizontal line ############################################################################################################################ if self.axhline.enabled: if isinstance(self.axhline.kws,Struct): #if targetExists: self.axhline.kws.y = self.value[1] if "linewidth" not in vars(self.axhline.kws).keys(): self.axhline.kws.linewidth = 0.5 if "linestyle" not in vars(self.axhline.kws).keys(): self.axhline.kws.linestyle = "-" if "color" not in vars(self.axhline.kws).keys(): self.axhline.kws.color = "orangered" if "zorder" not in vars(self.axhline.kws).keys(): self.axhline.kws.zorder = 1001 else: raise Exception ( "The axhline.kws component of the current Target object must" + newline + "be an object of class Struct(), essentially a structure with components" + newline + "whose names are the input arguments to the axhline() function of the" + newline + "matplotlib library." + newline + self._getDocString() ) ############################################################################################################################ #### setup the scatter line ############################################################################################################################ if self.scatter.enabled: if isinstance(self.scatter.kws,Struct): #if targetExists: self.scatter.kws.x = self.value[0] #if targetExists: self.scatter.kws.y = self.value[1] if "s" not in vars(self.scatter.kws).keys(): self.scatter.kws.s = 20 if "color" not in vars(self.scatter.kws).keys(): self.scatter.kws.color = "orangered" if "zorder" not in vars(self.scatter.kws).keys(): self.scatter.kws.zorder = 1002 else: raise Exception ( "The scatter.kws component of the current Target 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() ) ############################################################################################################################ ############################################################################################################################ if self._isdryrun: return ############################################################################################################################ ############################################################################################################################ from matplotlib import pyplot as plt plt.ion() # turn on the interactive mode. Used to detach the figure from the command line in ipython # generate figure and axes if needed if self.currentFig.axes is None: self.currentFig.axes = plt.gca() self.currentFig.figure = self.currentFig.axes.get_figure() try: plt.sca(self.currentFig.axes) except: self.currentFig.axes = plt.gca() self.currentFig.figure = plt.gcf() #plt.figure(self.currentFig.figure.number) ############################################################################################################################ #### add target ############################################################################################################################ xlimCurrent = self.currentFig.axes.get_xlim() ylimCurrent = self.currentFig.axes.get_ylim() if self.axvline.enabled: #if "ymin" not in vars(self.axvline.kws).keys(): self.axvline.kws.ymin = ylimCurrent[0] #if "ymax" not in vars(self.axvline.kws).keys(): self.axvline.kws.ymax = ylimCurrent[1] self.currentFig.axvline = self.currentFig.axes.axvline ( self.value[0] , **vars(self.axvline.kws) ) if self.axhline.enabled: #if "xmin" not in vars(self.axhline.kws).keys(): self.axhline.kws.xmin = xlimCurrent[0] #if "xmax" not in vars(self.axhline.kws).keys(): self.axhline.kws.xmax = xlimCurrent[1] self.currentFig.axhline = self.currentFig.axes.axhline ( self.value[1] , **vars(self.axhline.kws) ) if self.scatter.enabled: self.currentFig.scatter = self.currentFig.axes.scatter ( self.value[0] , self.value[1] , **vars(self.scatter.kws) ) self.currentFig.axes.set_xlim(xlimCurrent) self.currentFig.axes.set_ylim(ylimCurrent) ############################################################################################################################ if reself: return self
################################################################################################################################ #### _getDocString ################################################################################################################################
[docs] def _getDocString(self): docString = newline \ + "Here is the help information on the Target class:" + newline \ + newline \ + self.__doc__ return docString
################################################################################################################################