Source code for graphics

[docs]class Graphics: """ This class tends to provide basic graphic tools based on `matplotlib` and `mayavi`. Accepts one optional argument `env` which determines the types of the function to be visualized: - `numeric`: is a numerical function (regular python functions) - `sympy`: Sympy symbolic function - `sage`: Sage symbolic function """ def __init__(self, env='numeric', numpoints=50): """ Accepts one optional argument `env` which determines the types of the function to be visualized: - 'numeric': is a numerical function (regular python functions) - 'sympy': Sympy symbolic function - 'sage': Sage symbolic function """ self.Env = env self.NumPoints = numpoints self.title = "" self.color = [] self.X = [] self.Y = [] self.Z = [] self.pX = [] self.pY = [] self.pZ = [] self.pColor = [] self.pMarker = [] self.xlabel = '$x$' self.ylabel = '$y$' self.zlabel = '$z$' self.xmin = None self.xmax = None self.ymin = None self.ymax = None self.zmin = None self.zmax = None self.legend = [] self.plegend = [] self.thickness = [] self.grid = True self.PlotCount = 0 self.PlotType = ''
[docs] def SetLabelX(self, lbl): """ Sets the label for `X` axis """ self.xlabel = lbl
[docs] def SetLabelY(self, lbl): """ Sets the label for `Y` axis """ self.ylabel = lbl
[docs] def SetLabelZ(self, lbl): """ Sets the label for `Z` axis """ self.zlabel = lbl
[docs] def SetTitle(self, ttl): """ Sets the title of the graph. """ self.title = ttl
[docs] def Point(self, pnts, color='blue', marker="o", legend=""): """ Adds a list of points to the plot. """ if len(pnts[0]) == 2: self.PlotType = '2D' TX = [] TY = [] for p in pnts: TX.append(p[0]) TY.append(p[1]) self.pX.append(TX) self.pY.append(TY) elif len(pnts[0]): self.PlotType = '3D' TX = [] TY = [] TZ = [] for p in pnts: TX.append(p[0]) TY.append(p[1]) TZ.append(p[2]) self.pX.append(TX) self.pY.append(TY) self.pZ.append(TZ) self.pColor.append(color) self.pMarker.append(marker) self.plegend.append(legend) self.thickness.append(1)
[docs] def Plot2D(self, func, xrng, color='blue', legend="", thickness=1): """ Appends a curve to the Graphics object. The parameters are as follows: - `func`: the function to be plotted, - `xrng`: a triple of the form `(x, a, b)`, where `x` is the `func`'s independents variable, over the range `[a, b]`, - `color`: the color of the current curve, - `legend`: the text for the legend of the current crve. """ if self.PlotType == '': self.PlotType = '2D' elif self.PlotType != '2D': raise Exception("Cannot combine 2d and 3d plots") if self.Env == 'numeric': f_ = func elif self.Env == 'sympy': from sympy import lambdify f_ = lambdify(xrng[0], func, "numpy") elif self.Env == 'sage': from sage.all import fast_callable f_ = fast_callable(func, vars=[xrng[0]]) elif self.Env == 'symengine': from symengine import sympify from sympy import lambdify t_func = sympify(func) f_ = lambdify(xrng[0], t_func, "numpy") else: raise Exception( "The function type is not recognized. Only 'numeric', 'sympy' and 'sage' are accepted.") # if self.X == []: stp_lngt = float(xrng[2] - xrng[1]) / self.NumPoints self.X.append( [xrng[1] + i * stp_lngt for i in range(self.NumPoints + 1)]) self.xmin = xrng[1] self.xmax = xrng[2] TempY = [f_(x) for x in self.X[-1]] if self.ymin is None: self.ymin = min(TempY) self.ymax = max(TempY) else: self.ymin = min(min(TempY), self.ymin) self.ymax = max(max(TempY), self.ymax) self.Y.append(TempY) self.color.append(color) self.legend.append(legend) self.thickness.append(thickness) self.PlotCount += 1
[docs] def ParamPlot2D(self, funcs, rng, color='blue', legend="", thickness=1): """ Appends a parametric curve to the Graphics object. The parameters are as follows: - ``funcs``: the tupleof functions to be plotted, - ``rng``: a triple of the form `(t, a, b)`, where `t` is the `funcs`'s independents variable, over the range `[a, b]`, - ``color``: the color of the current curve, - ``legend``: the text for the legend of the current crve. """ if self.PlotType == '': self.PlotType = '2D' elif self.PlotType != '2D': raise Exception("Cannot combine 2d and 3d plots") if self.Env == 'numeric': f_0 = funcs[0] f_1 = funcs[1] elif self.Env == 'sympy': from sympy import lambdify f_0 = lambdify(rng[0], funcs[0], "numpy") f_1 = lambdify(rng[0], funcs[1], "numpy") elif self.Env == 'sage': from sage.all import fast_callable f_0 = fast_callable(funcs[0], vars=[rng[0]]) f_1 = fast_callable(funcs[1], vars=[rng[0]]) elif self.Env == 'symengine': from symengine import sympify from sympy import lambdify t_f0 = sympify(funcs[0]) t_f1 = sympify(funcs[1]) f_0 = lambdify((xrng[0], yrng[0]), t_f0, "numpy") f_1 = lambdify((xrng[0], yrng[0]), t_f1, "numpy") else: raise Exception( "The function type is not recognized. Only 'numeric', 'sympy' and 'sage' are accepted.") # if self.X == []: stp_lngt = float(rng[2] - rng[1]) / self.NumPoints line_points = [rng[1] + i * stp_lngt for i in range(self.NumPoints + 1)] TempX = [f_0(t) for t in line_points] self.X.append(TempX) if self.xmin is None: self.xmin = min(TempX) self.xmax = max(TempX) else: self.xmin = min(min(TempX), self.xmin) self.xmax = max(max(TempX), self.xmax) TempY = [f_1(t) for t in line_points] if self.ymin is None: self.ymin = min(TempY) self.ymax = max(TempY) else: self.ymin = min(min(TempY), self.ymin) self.ymax = max(max(TempY), self.ymax) self.Y.append(TempY) self.color.append(color) self.legend.append(legend) self.thickness.append(thickness) self.PlotCount += 1
[docs] def Plot3D(self, func, xrng, yrng): """ Sets a surface to the Graphics object. The parameters are as follows: - ``func``: the function to be plotted, - ``xrng``: a triple of the form `(x, a, b)`, where `x` is the first `func`s independents variable, over the range `[a, b]`, - ``yrng``: a triple of the form `(y, c, d)`, where `x` is the second `func`'s independents variable, over the range `[c, d]`. """ import numpy as np if self.PlotType == '': self.PlotType = '3D' elif self.PlotType != '3D': raise Exception("Cannot combine 2d and 3d plots") if self.Env == 'numeric': f_ = func elif self.Env == 'sympy': from sympy import lambdify f_ = lambdify((xrng[0], yrng[0]), func, "numpy") elif self.Env == 'sage': from sage.all import fast_callable f_ = fast_callable(func, vars=[xrng[0], yrng[0]]) elif self.Env == 'symengine': from symengine import sympify from sympy import lambdify t_func = sympify(func) f_ = lambdify((xrng[0], yrng[0]), t_func, "numpy") else: raise Exception( "The function type is not recognized. Only 'numeric', 'sympy' and 'sage' are accepted.") # self.f_ = f_ x_stp_lngt = float(xrng[2] - xrng[1]) / self.NumPoints y_stp_lngt = float(yrng[2] - yrng[1]) / self.NumPoints if self.X == []: self.X = [xrng[1] + i * x_stp_lngt for i in range(self.NumPoints + 1)] self.xmin = xrng[1] self.xmax = xrng[2] self.Y = [yrng[1] + i * y_stp_lngt for i in range(self.NumPoints + 1)] self.ymin = yrng[1] self.ymax = yrng[2] X = np.array(self.X) Y = np.array(self.Y) self.X, self.Y = np.meshgrid(X, Y) self.Z = f_(self.X, self.Y) self.intX, self.intY = np.mgrid[xrng[1]:xrng[ 2]:x_stp_lngt, yrng[1]:yrng[2]:y_stp_lngt] self.intZ = f_(self.intX, self.intY)
[docs] def save(self, fname="fig.png"): """ Saves the outpu of the `Graphics` object to the file `fname`. """ import numpy as np if self.PlotType == '2D': import matplotlib.pyplot as plt try: plt.axis([self.xmin, self.xmax, self.ymin, self.ymax]) except: pass if self.title != "": plt.title(self.title) if self.xlabel != '': plt.xlabel(self.xlabel, color='gray') if self.ylabel != '': plt.ylabel(self.ylabel, color='gray') for idx in range(len(self.pX)): plt.plot(self.pX[idx], self.pY[idx], color=self.pColor[ idx], marker=self.pMarker[idx], ls='') for idx in range(self.PlotCount): plt.plot(self.X[idx], self.Y[idx], color=self.color[ idx], linewidth=self.thickness[idx]) plt.legend(self.plegend + self.legend, loc=2) plt.grid(self.grid) elif self.PlotType == '3D': from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from matplotlib import cm fig = plt.figure() ax = Axes3D(fig) ax.set_xlabel(self.xlabel) ax.set_ylabel(self.ylabel) ax.set_zlabel(self.zlabel) # ax.set_xlim3d(self.xmin, self.xmin) # ax.set_ylim3d(self.ymin, self.ymax) # ax.set_zlim3d(0, 1) ax = fig.add_subplot(projection='3d') alpha = 1 for idx in range(len(self.pX)): alpha = .6 ax.scatter(self.pX[idx], self.pY[idx], self.pZ[ idx], color=self.pColor[idx], marker=self.pMarker[idx]) ax.plot_surface(self.X, self.Y, self.Z, rstride=1, cstride=1, linewidth=.1, cmap=cm.jet, alpha=alpha) plt.savefig(fname)
[docs] def interact(self): """ Shows an interavtive demo of the 3D surface, using `mayavi`, so it requires `mayavi` for python to be installed. """ if self.PlotType != '3D': raise Exception("No 3D surface is available.") import numpy as np from mayavi import mlab s = mlab.surf(self.intX, self.intY, self.intZ) mlab.show()