def __init__(self, file, methodName, reportEnabled): super().__init__(file, methodName, reportEnabled) # superclass sets the following # self.file = file # self._methodName = methodName # self._reportEnabled = reportEnabled self.ndim = None self.count = None self.contents = None self._fileType = "restart" self._contents = [] self._lineList = [] self._lineListLen = [] self.propNameList = [] if self._methodName == pm.names.paradram: self._readRestartParaDRAM() else: pm.abort( msg= "Internal error occurred. Unrecognized methodName in the class \n" "constructor of RestartFileContents: " + self.methodName, marginTop=1, marginBot=1, methodName="ParaMonte")
def __init__( self , matrix : tp.Union[ np.ndarray, tp.List[np.ndarray] ] , plotType : str , methodName : tp.Optional[ str ] = "ParaMonte" , reportEnabled : tp.Optional[ bool ] = True , resetPlot = None ): self.matrix = matrix if isinstance(matrix, np.ndarray): self.numEllipsoid = np.shape(matrix)[0] #elif instance(matrix, list): # self.numEllipsoid = len(matrix) else: pm.abort( msg = "The input argument ``matrix`` must be a numpy 3D" + newline + "array of matrices representing the covariance/correlation " + newline + "matrices of the ellipsoids or. The first dimension of array" + newline + "must count over the ellipsoids." + newline , marginTop = 1 , marginBot = 1 , methodName = methodName ) import pandas as pd self._dfIndex = pd.DataFrame.from_dict({ "indices" : list(range( self.numEllipsoid )) }) super().__init__( plotType = plotType , dataFrame = self._dfIndex , methodName = methodName , reportEnabled = reportEnabled , resetPlot = resetPlot ) self._reset() if resetPlot is None: self._resetPlot = self._reset self._progress.note()
def _reportCorruptFile(self): pm.abort( msg="The structure of the file: " + newline + newline + " \"" + self.file + "\"" + newline + newline + "does not match a " + self._methodName + " " + self._fileType + " file." + newline + "The contents of the file may have been compromised." + newline + "Verify the integrity of the contents of this file before attempting to reread it.", marginTop=2, marginBot=1, methodName=self._methodName)
def _reportWrongPlotName(self, plotNames): pm.abort( msg="The input argument ``plotNames`` must be a string representing" + newline + "the name of a plot belonging to the TabularFileContents class or," + newline + "a list of such plot names. You have entered: " + plotNames + newline + "Possible plots are: " + newline + newline + newline.join(self._plotTypeList) + newline + newline + "Here is the help for the ``reset()`` method: " + newline + newline + self._resetPlot.__doc__, marginTop=1, marginBot=1, methodName=self._methodName)
def helpme(specification=""): """ | Return help on the input ParaDRAM specification. If no input is provided, then the weblink to the entire list of ParaDRAM specifications will be output. **Parameters** specification A string that can take be any of the simulation specifications of a ParaDRAM object, such as, ``"chainSize"``, ``"sampleSize"``, ... **Returns** None """ import _paramonte as pm if isinstance(specification, str): if specification != "": specification = "#" + specification.lower() else: pm.abort( msg= "The input argument to helpme() function must be a string whose value \n" + "can be the name of one of the specifications of the ParaDRAM sampler.\n" + "For example, to get information about the variable `chainSize`, try:\n\n" + " pmpd.spec.helpme(\"chainSize\")\n\n" + "where ``pmpd`` is the name of the ParaDRAM sampler object.\n" + "For more information and examples on the usage, visit:\n\n" + " " + pm.website.home.url, methodName=pm.names.paradram, marginTop=1, marginBot=1) print("Visit: " + pm.website.home.usage.paradram.specifications.url + specification)
def _resetPlot(self, resetType="soft", plotNames="all"): """ Reset the properties of the plot to the original default settings. Use this method when you change many attributes of the plot and you want to clean up and go back to the default settings. **Parameters** resetType (optional) An optional string with possible value of ``"hard"``. If provided, the plot object will be regenerated from scratch. This includes reading the original data frame again and resetting everything. If not provided, then only the plot settings will be reset without reseting the dataFrame. plotNames (optional) An optional string value or list of string values representing the names of plots to reset. If no value is provided, then all plots will be reset. **Returns** None **Example** .. code-block:: python reset("hard") # regenerate all plots from scratch reset("hard","line3") # regenerate line3 plot from scratch reset("hard",["line","line3"]) # regenerate line and line3 plots """ requestedPlotTypeList = [] if isinstance(plotNames, str): plotTypeLower = plotNames.lower() if plotTypeLower == "all": requestedPlotTypeList = self._plotTypeList elif plotNames in self._plotTypeList: requestedPlotTypeList = [plotNames] else: self._reportWrongPlotName(plotNames) elif isinstance(plotNames, list): for plotName in plotNames: if plotName not in self._plotTypeList: self._reportWrongPlotName(plotName) else: self._reportWrongPlotName("a none-string none-list object.") resetTypeIsHard = None if isinstance(resetType, str): resetTypeIsHard = resetType.lower() == "hard" else: resetTypeIsHard = None pm.abort( msg="The input argument resetType must be a string representing" + newline + "the type of the reset to be performed on the plots." + newline + "A list of possible plots includes: \"hard\", \"soft\"" + newline + "Here is the help for the ``reset()`` method: " + newline + newline + self._resetPlot.__doc__, marginTop=1, marginBot=1, methodName=self._methodName) ############################################################################################################################ #### reset plots ############################################################################################################################ for requestedPlotType in requestedPlotTypeList: plotObject = None requestedPlotTypeLower = requestedPlotType.lower() is3d = "3" in requestedPlotTypeLower isLine = "line" in requestedPlotTypeLower isScatter = "scatter" in requestedPlotTypeLower isJointplot = "jointplot" in requestedPlotTypeLower isHistplot = "histplot" in requestedPlotTypeLower isKdeplot1 = "kdeplot1" in requestedPlotTypeLower isKdeplot2 = "kdeplot2" in requestedPlotTypeLower isContourf = "contourf" in requestedPlotTypeLower isContour3 = "contour3" in requestedPlotTypeLower isContour = "contour" in requestedPlotTypeLower and not ( isContourf or isContour3) isGridPlot = "grid" in requestedPlotTypeLower isLineScatterPlot = isLine or isScatter isDensityPlot = isJointplot or isHistplot or isKdeplot1 or isKdeplot2 or isContourf or isContour3 or isContour if not resetTypeIsHard: plotComponent = getattr(self, "plot") plotObject = getattr(plotComponent, requestedPlotType) plotObject._reset() ######################################################################################################################## #### reset line / scatter ######################################################################################################################## if isLineScatterPlot: if resetTypeIsHard: plotObject = LineScatterPlot( plotType=requestedPlotType, dataFrame=self.df, methodName=self._methodName, reportEnabled=self._reportEnabled, resetPlot=self._resetPlot) plotObject.ycolumns = self.df.columns[self._offset] # :] plotObject.ccolumns = self._sampleLogFuncColName plotObject.colorbar.kws.extend = "neither" plotObject.colorbar.kws.orientation = "vertical" plotObject.colorbar.kws.spacing = "uniform" if is3d: plotObject.zcolumns = self._sampleLogFuncColName if self.ndim > 1: plotObject.xcolumns = self.df.columns[self._offset] plotObject.ycolumns = self.df.columns[self._offset + 1] if isLine: if isScatter: plotObject.lineCollection.enabled = False plotObject.plot.enabled = True plotObject.plot.kws.alpha = 0.2 plotObject.plot.kws.color = "grey" plotObject.plot.kws.linewidth = 0.75 else: plotObject.lineCollection.enabled = True plotObject.plot.enabled = False ######################################################################################################################## #### reset density plots: kdeplot / histplot / jointplot / contour / contourf / contour3 ######################################################################################################################## if isDensityPlot: if resetTypeIsHard: plotObject = DensityPlot(plotType=requestedPlotType, dataFrame=self.df, methodName=self._methodName, reportEnabled=self._reportEnabled, resetPlot=self._resetPlot) plotObject.xcolumns = self.df.columns[self._offset] if not (isHistplot or isKdeplot1): if self.ndim == 1: plotObject.xcolumns = self.df.columns[self._offset - 1] plotObject.ycolumns = self.df.columns[self._offset] else: plotObject.ycolumns = self.df.columns[self._offset + 1] ######################################################################################################################## #### reset GridPlot ######################################################################################################################## if isGridPlot: if resetTypeIsHard: plotObject = GridPlot(plotType=requestedPlotType, dataFrame=self.df, methodName=self._methodName, reportEnabled=self._reportEnabled, resetPlot=self._resetPlot) endColindex = np.min( [self._offset + 3, self._offset + self.ndim]) plotObject.columns = self.df.columns[self._offset - 1:endColindex] plotObject.ccolumn = self._sampleLogFuncColName ######################################################################################################################## #### reset target component ######################################################################################################################## if (isLineScatterPlot or isDensityPlot ) and not (plotObject._type.is3d or self._isProgressFile): xtarget = 0 # dummy if isDensityPlot: xtarget = self.df[plotObject.xcolumns].values.flatten()[ self.stats.maxLogFunc.idrow] if plotObject._type.is1d: plotObject.target.value = [xtarget, 0] if plotObject._type.is2d: ytarget = self.df[plotObject.ycolumns].values.flatten()[ self.stats.maxLogFunc.idrow] plotObject.target.value = [xtarget, ytarget] if isDensityPlot and plotObject._type.is1d: plotObject.target.axhline.enabled = False if isLine or isScatter: plotObject.target.axvline.enabled = False plotObject.target.label = "maxLogFunc" ######################################################################################################################## if plotObject is not None: setattr(self.plot, requestedPlotType, plotObject)
def __init__(self, file, fileType, delimiter, methodName, parseContents=True, reportEnabled=True): super().__init__(file, methodName, reportEnabled) markovChainRequested = fileType == "markovChain" self._isProgressFile = "progress" == fileType self._sampleLogFuncColName = "" if self._isProgressFile else "SampleLogFunc" #if "sample"==fileType: # fileSuffix = "sample" #elif fileType=="chain" or markovChainRequested: # fileSuffix = "chain" #elif self._isProgressFile: # fileSuffix = "progress" #else: # pm.abort( msg = "Internal error occurred. The input fileType is not recognized.\n" # + "Please report this error at:\n\n" # + " " + pm.website.github.issues.url # , methodName = self._methodName # , marginTop = 1 # , marginBot = 1 # ) if fileType != "sample" and fileType != "chain" and not ( self._isProgressFile or markovChainRequested): pm.abort( msg= "Internal error occurred. The input fileType is not recognized.\n" + "Please report this error at:\n\n" + " " + pm.website.github.issues.url, methodName=self._methodName, marginTop=1, marginBot=1) ############################################################################################################################ #### data ############################################################################################################################ self.delimiter = delimiter import pandas as pd self.df = pd.read_csv(self.file, delimiter=self.delimiter, header=0) if self._isProgressFile: self._offset = -1 else: self._offset = list(self.df.columns).index( self._sampleLogFuncColName) + 1 # index of the first variable self.ndim = len(self.df.columns) - self._offset self.count = len(self.df.iloc[:, 1]) self.ncol = len(self.df.iloc[1, :]) if markovChainRequested: CumSumWeight = np.cumsum(self.df.iloc[:, self._offset - 2].values, dtype=np.int32) if CumSumWeight[-1] != self.count: # it is indeed a compact chain #dfMarkov = pd.DataFrame( columns=list(self.df.columns), index=list(range(CumSumWeight[-1])) ) dfMarkov = np.zeros( (CumSumWeight[-1], self.ndim + self._offset)) istart = 0 for i in range(self.count): iend = CumSumWeight[i] #dfMarkov.iloc[istart:iend,:] = self.df.iloc[i].values dfMarkov[istart:iend, :] = self.df.iloc[i].values istart = iend columns = self.df.columns self.df = pd.DataFrame(dfMarkov) self.count = len(self.df.iloc[:, 1]) self.df.columns = columns self._progress.note() if not self._isProgressFile: self._progress.note(msg="ndim = " + str(self.ndim) + ", count = " + str(self.count), end=newline, pre=True) # set dynamic properties if parseContents: self._progress.note(msg="parsing file contents... ", end=newline, pre=True) self.contents = Struct() for icol, colName in enumerate(self.df.columns): setattr(self.contents, colName, self.df[colName]) ############################################################################################################################ #### statistics ############################################################################################################################ if not self._isProgressFile: self.stats = Struct() #### add chain cormat self._progress.note( msg="computing the sample correlation matrix... ", end=newline, pre=True) self.stats.cormat = ccm.CorMat(dataFrame=self.df, columns=range( self._offset, self._offset + self.ndim), methodName=self._methodName, reportEnabled=self._reportEnabled, method="pearson") self.stats.cormat() #### add chain covmat self._progress.note( msg="computing the sample covariance matrix... ", end=newline, pre=True) self.stats.covmat = ccm.CovMat(dataFrame=self.df, columns=range( self._offset, self._offset + self.ndim), methodName=self._methodName, reportEnabled=self._reportEnabled) self.stats.covmat() #### add chain autocorrelation self._progress.note( msg="computing the sample autocorrelations... ", end=newline, pre=True) self.stats.autocorr = AutoCorr(dataFrame=self.df, columns=range( self._offset - 1, self._offset + self.ndim), methodName=self._methodName, reportEnabled=self._reportEnabled) self.stats.autocorr() #### add chain maxLogFunc self.stats.maxLogFunc = getMaxLogFunc(dataFrame=self.df) ############################################################################################################################ #### graphics ############################################################################################################################ self._plotTypeList = ["line", "scatter", "lineScatter"] if not self._isProgressFile: self._plotTypeList += [ "line3", "scatter3", "lineScatter3", "jointplot", "histplot", "kdeplot1", "kdeplot2", "contour3", "contourf", "contour", "grid" ] self._progress.note(msg="adding the graphics tools... ", end=newline, pre=True) self.plot = Struct() self._resetPlot(resetType="hard") self.plot.reset = self._resetPlot
def _resetPlot(self, resetType="soft", plotNames="all"): """ Reset the properties of the plot to the original default settings. Use this method when you change many attributes of the plot and you want to clean up and go back to the default settings. **Parameters** resetType (optional) An optional string with possible value of ``"hard"``. If provided, the plot object will be regenerated from scratch. This includes reading the original data frame again and resetting everything. If not provided, then only the plot settings will be reset without reseting the dataFrame. plotNames (optional) An optional string value or list of string values representing the names of plots to reset. If no value is provided, then all plots will be reset. **Returns** None **Example** .. code-block:: python reset("hard") # regenerate all plots from scratch reset("hard","covmat2") # regenerate covmat2 plot from scratch reset("hard",["covmat2","covmat3"]) # regenerate covmat2 & covmat3 plots """ requestedPlotTypeList = [] if isinstance(plotNames, str): plotTypeLower = plotNames.lower() if plotTypeLower == "all": requestedPlotTypeList = self._plotTypeList elif plotNames in self._plotTypeList: requestedPlotTypeList = [plotNames] else: self._reportWrongPlotName(plotNames) elif isinstance(plotNames, list): for plotName in plotNames: if plotName not in self._plotTypeList: self._reportWrongPlotName(plotName) else: self._reportWrongPlotName("a none-string none-list object.") resetTypeIsHard = None if isinstance(resetType, str): resetTypeIsHard = resetType.lower() == "hard" else: resetTypeIsHard = None pm.abort( msg="The input argument resetType must be a string representing" + newline + "the type of the reset to be performed on the plots." + newline + "A list of possible plots includes: \"hard\", \"soft\"" + newline + "Here is the help for the ``reset()`` method: " + newline + newline + self._resetPlot.__doc__, marginTop=1, marginBot=1, methodName=self._methodName) ############################################################################################################################ #### reset plots ############################################################################################################################ for requestedPlotType in requestedPlotTypeList: plotObject = None requestedPlotTypeLower = requestedPlotType.lower() #is3d = "3" in requestedPlotTypeLower isLine = "line" in requestedPlotTypeLower isScatter = "scatter" in requestedPlotTypeLower isCovMat = "covmat" in requestedPlotTypeLower isCorMat = "cormat" in requestedPlotTypeLower if not resetTypeIsHard: plotComponent = getattr(self, "plot") plotObject = getattr(plotComponent, requestedPlotType) plotObject._reset() ######################################################################################################################## #### reset line / scatter ######################################################################################################################## if isLine or isScatter: if resetTypeIsHard: plotObject = LineScatterPlot( plotType=requestedPlotType, dataFrame=self.df, methodName=self._methodName, reportEnabled=self._reportEnabled, resetPlot=self._resetPlot) if self._methodName == pm.names.paradram: plotObject.ycolumns = self.propNameList[0] plotObject.ccolumns = [] plotObject.colorbar.kws.extend = "neither" plotObject.colorbar.kws.orientation = "vertical" plotObject.colorbar.kws.spacing = "uniform" if isLine: if isScatter: plotObject.lineCollection.enabled = False plotObject.plot.enabled = True plotObject.plot.kws.alpha = 0.2 plotObject.plot.kws.color = "grey" plotObject.plot.kws.linewidth = 0.75 else: plotObject.lineCollection.enabled = True plotObject.plot.enabled = False setattr(self.plot, requestedPlotType, plotObject) ######################################################################################################################## #### reset covmat / cormat ######################################################################################################################## if isCovMat or isCorMat: if self._methodName == pm.names.paradram: matrix = None if isCovMat: matrix = self.contents.covMat if isCorMat: matrix = self.contents.corMat if resetTypeIsHard: plotObject = EllipsoidPlot( matrix=matrix, plotType=requestedPlotType, methodName=self._methodName, reportEnabled=self._reportEnabled, resetPlot=self._resetPlot) plotObject.rows = plotObject.getLogLinSpace() plotObject.center = self.contents.meanVec plotObject.title.enabled = True matrixType = "covariance" if isCovMat else "correlation" plotObject.title.label = "Evolution of the " + matrixType + " matrices of the proposal distribution" plotObject.colorbar.kws.extend = "neither" plotObject.colorbar.kws.orientation = "vertical" plotObject.colorbar.kws.spacing = "uniform" setattr(self.plot, requestedPlotType, plotObject)
def runSampler(self, ndim: int, getLogFunc: tp.Callable[[tp.List[float]], float], inputFile: tp.Optional[str] = None) -> None: """ Run ParaDRAM sampler and return nothing. **Parameters** ndim An integer representing the number of dimensions of the domain of the user's objective function ``getLogFunc(point)``. It must be a positive integer. getLogFunc(point) represents the user's objective function to be sampled, which must take a single input argument ``point`` of type numpy-float64 array of length ``ndim`` and must return the natural logarithm of the objective function. inputFile (optional) A string input representing the path to an external input namelist of simulation specifications. **WARNING** Use this optional argument with caution and only if you know what you are doing. Specifying this option will cause the sampler to ignore all other simulation specifications set by the user via the ``spec`` component of the sampler instance. **Returns** None """ if not isinstance(ndim, int) or ndim < 1: pm.abort( msg="The input argument ndim must be a positive integer," + newline + "representing the number of dimensions of the domain of" + newline + "the user's objective function getLogFunc()." + newline + "You have entered ndim = " + str(ndim), methodName=self._methodName, marginTop=1, marginBot=1) if not callable(getLogFunc): pm.abort( msg="The input argument getLogFunc must be a callable function." + newline + "It represents the user's objective function to be sampled," + newline + "which must take a single input argument of type numpy" + newline + "float64 array of length ndim and must return the" + newline + "natural logarithm of the objective function.", methodName=self._methodName, marginTop=1, marginBot=1) if inputFile is not None and not isinstance(inputFile, str): pm.abort( msg="The input argument ``inputFile`` must be of type str." + newline + "It is an optional string input representing the path to" + newline + "an external input namelist of simulation specifications." + newline + "USE THIS OPTIONAL ARGUMENT WITH CAUTION AND" + newline + "ONLY IF YOU KNOW WHAT YOU ARE DOING." + newline + "Specifying this option will cause the sampler to ignore" + newline + "all other simulation specifications set by the user via" + newline + "the ``spec`` component of the sampler instance." + newline + "You have entered inputFile = " + str(inputFile), methodName=self._methodName, marginTop=1, marginBot=1) def getLogFunc2arg(ndim, point): PointVec = np.array(point[0:ndim]) return getLogFunc(PointVec) self._runSampler(ndim, getLogFunc2arg, inputFile)
def getLogLinSpace ( self , base : tp.Optional[ np.float64 ] = 1.2 , logskip : tp.Optional[ np.int32 ] = 0.2 , lowerLim : tp.Optional[ np.int32 ] = 1 , upperLim : tp.Optional[ np.int32 ] = None ): """ Generate logarithmically-uniformly-spaced **unique** integer numbers between the input lowerLim and upperLim. These numbers are to be used as the row indices in the plots. **Parameters** base (optional) The base of the logarithm used for generating the logarithmically-uniform range of integers. The default value is ``1.2``. logskip (optional) The minimum logarithmic space jump between the generated log-linearly-spaced integer numbers. The default value is ``0.2``. lowerLim (optional) The natural (non-logarithmic) lower limit of the generated log-linearly-spaced integer numbers. If not provided, the default value is ``1``. upperLim (optional) The natural (non-logarithmic) upper limit of the generated log-linearly-spaced integer numbers. If not provided, the default value is the maximum of the number of the rows of the input dataframe to the BasePlot constructor. **Returns** A set of unique log-linearly-spaced integer numbers. **Example** .. code-block:: python rows = getLogLinSpace(1.01, 1, 1, 10000) """ if upperLim is None and self._dfref is not None: upperLim = len(self._dfref().index) elif upperLim is None and self.rows is not None: upperLim = len(self.rows[-1]) else: pm.abort( msg = "Either the input argument ``upperLim`` or the dataFrame of the plot object" + newline + "must be given in order to generate a log-linear range of values. " + newline + "Here is the documentation of getLogLinSpace():" + newline + newline + self.getLogLinSpace.__doc__ + newline , marginTop = 1 , marginBot = 1 , methodName = self._methodName ) return pm.utils.getLogIntSpace(base,logskip,lowerLim,upperLim)
def getLinSpace ( self , skip = None , lowerLim : tp.Optional[ np.int32 ] = 1 , upperLim : tp.Optional[ np.int32 ] = None ): """ Generate linearly-spaced **unique** integer numbers between the input lowerLim and upperLim. These numbers can be used as the row indices in the plots. **Parameters** skip (optional) The linear spacing between the generated points. If ``skip`` is specified as input, any input value for ``npoint`` will be ignored. The default value is ``None``. lowerLim (optional) The natural (non-logarithmic) lower limit of the generated linearly-spaced integer numbers. If not provided, the default value is ``1``. upperLim (optional) The natural (non-logarithmic) upper limit of the generated linearly-spaced integer numbers. If not provided, the default value is the maximum of the number of the rows of the input dataframe to the ``BasePlot`` constructor. **Returns** A set of unique linearly-spaced integer numbers. **Example** .. code-block:: python rows = getLinSpace(3, 1, 10000) """ if upperLim is None and self._dfref is not None: upperLim = len(self._dfref().index) elif upperLim is None and self.rows is not None: upperLim = len(self.rows[-1]) else: pm.abort( msg = "Either the input argument ``upperLim`` or the dataFrame of the plot object" + newline + "must be given in order to generate a linear range of values. " + newline + "Here is the documentation of getLinSpace():" + newline + newline + self.getLinSpace.__doc__ + newline , marginTop = 1 , marginBot = 1 , methodName = self._methodName ) if skip is None: skip = (upperLim - lowerLim) // 256 if skip<1: skip = 1 return range(lowerLim,upperLim,skip)