def plotDensity(self, axes=None, hist=True, bins=100, color='b'): """Plots the mesh density in x/y/z-direction. ``hist=True`` is recommended, since otherwise plots generally appear fairly noisy. .. note:: If no ``axes`` are given or they do not have the necessary size, will create new ones. .. image:: ../imgs/pyfrp_mesh/density_plot.png Keyword Args: axes (list): List of ``matplotlib.axes``. hist (bool): Summarize densities in bins. bins (int): Number of bins used for hist. color (str): Color of plot. Returns: list: List of ``matplotlib.axes``. """ x, y, z = self.getCellCenters() volSortedByX, xSorted = pyfrp_misc_module.sortListsWithKey( self.mesh.getCellVolumes(), x) volSortedByY, ySorted = pyfrp_misc_module.sortListsWithKey( self.mesh.getCellVolumes(), y) volSortedByZ, zSorted = pyfrp_misc_module.sortListsWithKey( self.mesh.getCellVolumes(), z) if axes == None: fig, axes = pyfrp_plot_module.makeSubplot( [1, 3], titles=["Density(x)", "Density(y)", "Density(z)"]) else: if len(axes) < 3: printWarning( "axes do not have right have, will create new ones.") fig, axes = pyfrp_plot_module.makeSubplot( [1, 3], titles=["Density(x)", "Density(y)", "Density(z)"]) if hist: xSorted, volSortedByX = pyfrp_misc_module.simpleHist( xSorted, volSortedByX, bins) ySorted, volSortedByY = pyfrp_misc_module.simpleHist( ySorted, volSortedByY, bins) zSorted, volSortedByZ = pyfrp_misc_module.simpleHist( zSorted, volSortedByZ, bins) axes[0].plot(xSorted, volSortedByX, color=color) axes[1].plot(ySorted, volSortedByY, color=color) axes[2].plot(zSorted, volSortedByZ, color=color) for ax in axes: pyfrp_plot_module.redraw(ax) return axes
def plotDensity(self,axes=None,hist=True,bins=100,color='b'): """Plots the mesh density in x/y/z-direction. ``hist=True`` is recommended, since otherwise plots generally appear fairly noisy. .. note:: If no ``axes`` are given or they do not have the necessary size, will create new ones. .. image:: ../imgs/pyfrp_mesh/density_plot.png Keyword Args: axes (list): List of ``matplotlib.axes``. hist (bool): Summarize densities in bins. bins (int): Number of bins used for hist. color (str): Color of plot. Returns: list: List of ``matplotlib.axes``. """ x,y,z=self.getCellCenters() volSortedByX,xSorted=pyfrp_misc_module.sortListsWithKey(self.mesh.getCellVolumes(),x) volSortedByY,ySorted=pyfrp_misc_module.sortListsWithKey(self.mesh.getCellVolumes(),y) volSortedByZ,zSorted=pyfrp_misc_module.sortListsWithKey(self.mesh.getCellVolumes(),z) if axes==None: fig,axes = pyfrp_plot_module.makeSubplot([1,3],titles=["Density(x)","Density(y)","Density(z)"]) else: if len(axes)<3: printWarning("axes do not have right have, will create new ones.") fig,axes = pyfrp_plot_module.makeSubplot([1,3],titles=["Density(x)","Density(y)","Density(z)"]) if hist: xSorted,volSortedByX=pyfrp_misc_module.simpleHist(xSorted,volSortedByX,bins) ySorted,volSortedByY=pyfrp_misc_module.simpleHist(ySorted,volSortedByY,bins) zSorted,volSortedByZ=pyfrp_misc_module.simpleHist(zSorted,volSortedByZ,bins) axes[0].plot(xSorted,volSortedByX,color=color) axes[1].plot(ySorted,volSortedByY,color=color) axes[2].plot(zSorted,volSortedByZ,color=color) for ax in axes: pyfrp_plot_module.redraw(ax) return axes
def compareICInterpolation(self,axes=None,roi=None): """Shows initial image, its interpolation, the resulting initial condition and its interpolation back onto an image. See also :py:func:`showICimg`, :py:func:`showInterpolatedICImg`, :py:func:`showIC`, :py:func:`showInterpolatedIC`. Will create new axes if necessary. .. warning:: Some images might be flipped due to plotting functions. Will be fixed in future version. .. image:: ../imgs/pyfrp_simulation/ICcompare.png Keyword Args: roi (pyfrp.subclasses.pyfrp_ROI.ROI): A PyFRAP ROI. axes (matplotlib.axes): List of axes of length 4. Returns: list: List of axes. """ if axes==None: fig,axes = pyfrp_plot_module.makeSubplot([2,2],titles=["Original Image","Interpolated Image","IC","Reinterpolated IC"],sup="simulation") self.showICimg(ax=axes[0]) self.showInterpolatedICImg(ax=axes[1]) self.showIC(ax=axes[2],roi=roi) self.showInterpolatedIC(ax=axes[3],roi=roi) for ax in axes: pyfrp_plot_module.redraw(ax) return axes
def showInterpolatedICImg(self,ax=None): """Shows interpolation of initial condition image. See also :py:func:`computeInterpolatedICImg`. .. image:: ../imgs/pyfrp_simulation/showInterpolatedICimg.png Keyword Args: ax (matplotlib.axes): Axes to be used for plotting. Returns: matplotlib.axes: Axes used for plotting. """ if ax==None: fig,axes = pyfrp_plot_module.makeSubplot([1,1],titles=["Interpolated Image"],sup="simulation") ax=axes[0] xInt, yInt, f=self.computeInterpolatedICImg() #print np.shape(xInt) #raw_input() X,Y=np.meshgrid(xInt,yInt) imgInt=np.zeros(np.shape(X)) for i in range(np.shape(X)[0]): for j in range(np.shape(Y)[0]): imgInt[i,j]=f(X[i,j],Y[i,j]) ax.imshow(imgInt) return ax
def showInterpolatedIC(self,ax=None,roi=None): """Shows ICs interpolated back onto 2D image. If ``roi`` is specified, will only interpolate nodes of this ROI. See also :py:func:`computeInterpolatedIC`. .. image:: ../imgs/pyfrp_simulation/showInterpolatedIC.png Keyword Args: roi (pyfrp.subclasses.pyfrp_ROI.ROI): A PyFRAP ROI. ax (matplotlib.axes): Axes to be used for plotting. Returns: matplotlib.axes: Axes used for plotting. """ X,Y,interpIC=self.computeInterpolatedIC(roi=roi) if ax==None: fig,axes = pyfrp_plot_module.makeSubplot([1,1],titles=["Interpolated IC"],sup="simulation") ax=axes[0] ax.imshow(interpIC) return ax
def showInterpolatedICImg(self, ax=None): """Shows interpolation of initial condition image. See also :py:func:`computeInterpolatedICImg`. .. image:: ../imgs/pyfrp_simulation/showInterpolatedICimg.png Keyword Args: ax (matplotlib.axes): Axes to be used for plotting. Returns: matplotlib.axes: Axes used for plotting. """ if ax == None: fig, axes = pyfrp_plot_module.makeSubplot( [1, 1], titles=["Interpolated Image"], sup="simulation") ax = axes[0] xInt, yInt, f = self.computeInterpolatedICImg() #print np.shape(xInt) #raw_input() X, Y = np.meshgrid(xInt, yInt) imgInt = np.zeros(np.shape(X)) for i in range(np.shape(X)[0]): for j in range(np.shape(Y)[0]): imgInt[i, j] = f(X[i, j], Y[i, j]) ax.imshow(imgInt) return ax
def showInterpolatedIC(self, ax=None, roi=None): """Shows ICs interpolated back onto 2D image. If ``roi`` is specified, will only interpolate nodes of this ROI. See also :py:func:`computeInterpolatedIC`. .. image:: ../imgs/pyfrp_simulation/showInterpolatedIC.png Keyword Args: roi (pyfrp.subclasses.pyfrp_ROI.ROI): A PyFRAP ROI. ax (matplotlib.axes): Axes to be used for plotting. Returns: matplotlib.axes: Axes used for plotting. """ X, Y, interpIC = self.computeInterpolatedIC(roi=roi) if ax == None: fig, axes = pyfrp_plot_module.makeSubplot( [1, 1], titles=["Interpolated IC"], sup="simulation") ax = axes[0] ax.imshow(interpIC) return ax
def plotSolStack(self,phi,ROIs,withGeometry=True,vmin=None,vmax=None,ax=None,colorbar=False): """Plots a stack of the solution variable in a given list of ROIs. Will automatically compute the direction in which ROI lies in the 3D space and reduce the ROI into this plane for contour plot. If ``vmin=None`` or ``vmax=None``, will compute overall maximum and minimum values over all ROIs. Args: phi (fipy.CellVariable): Simulation solution variable (or numpy array). ROIs (list): List of :py:class:`pyfrp.subclasses.pyfrp_ROI.ROI` objects. Keyword Args: withGeometry (bool): Show geometry inside plot. vmin (float): Overall minimum value to be displayed in plot. vmax (float): Overall maximum value to be displayed in plot. ax (matplotlib.axes): Axes used for plotting. colorbar (bool): Display color bar. Returns: matplotlib.axes: Axes used for plotting. """ if ax==None: fig,axes = pyfrp_plot_module.makeSubplot([1,1],titles=["Simulation IC stack"],proj=['3d']) ax=axes[0] #Plot geometry if withGeometry: #self.embryo.geometry.updateGeoFile() ax=self.embryo.geometry.plotGeometry(ax=ax) #Find vmin/vmax over all ROIs vminNew=[] vmaxNew=[] for r in ROIs: vminNew.append(min(phi[r.meshIdx])) vmaxNew.append(max(phi[r.meshIdx])) if vmin==None: vmin=min(vminNew) if vmax==None: vmax=min(vmaxNew) for r in ROIs: plane=r.getMaxExtendPlane() zs=r.getPlaneMidCoordinate() zdir=r.getOrthogonal2Plane() ax=r.plotSolutionVariable(phi,ax=ax,vmin=vmin,vmax=vmax,plane=plane,zs=zs,zdir=zdir,colorbar=colorbar) return ax
def compareICInterpolation(self, axes=None, roi=None): """Shows initial image, its interpolation, the resulting initial condition and its interpolation back onto an image. See also :py:func:`showICimg`, :py:func:`showInterpolatedICImg`, :py:func:`showIC`, :py:func:`showInterpolatedIC`. Will create new axes if necessary. .. warning:: Some images might be flipped due to plotting functions. Will be fixed in future version. .. image:: ../imgs/pyfrp_simulation/ICcompare.png Keyword Args: roi (pyfrp.subclasses.pyfrp_ROI.ROI): A PyFRAP ROI. axes (matplotlib.axes): List of axes of length 4. Returns: list: List of axes. """ if axes == None: fig, axes = pyfrp_plot_module.makeSubplot([2, 2], titles=[ "Original Image", "Interpolated Image", "IC", "Reinterpolated IC" ], sup="simulation") self.showICimg(ax=axes[0]) self.showInterpolatedICImg(ax=axes[1]) self.showIC(ax=axes[2], roi=roi) self.showInterpolatedIC(ax=axes[3], roi=roi) for ax in axes: pyfrp_plot_module.redraw(ax) return axes
def showICimg(self,ax=None,typ='contour',colorbar=True,scale=True,nlevels=25,vmin=None,vmax=None): """Plots image used for initial condition either as contour or surface plot. .. image:: ../imgs/pyfrp_simulation/showICimg.png Keyword Args: ax (matplotlib.axes): Axes used for plotting. scale (bool): Equal axis. vmin (float): Overall minimum value to be displayed in plot. vmax (float): Overall maximum value to be displayed in plot. nlevels (int): Number of contour levels to display. Returns: matplotlib.axes: Axes used for plotting. """ #Check of entered plot type makes sense if typ not in ['contour','surface']: printError("Unknown plot type "+ typ) return ax if self.ICimg!=None: if vmin==None: vmin=min(self.ICimg.flatten()) if vmax==None: vmax=max(self.ICimg.flatten()) levels=np.linspace(vmin,1.01*vmax,nlevels) if ax==None: if typ=='surface': fig,axes = pyfrp_plot_module.makeSubplot([1,1],proj=['3d'],sup="",tight=False) else: fig,axes = pyfrp_plot_module.makeSubplot([1,1],sup="",tight=False) ax=axes[0] res=self.ICimg.shape[0] if 'quad' in self.embryo.analysis.process.keys(): X,Y=np.meshgrid(np.arange(res,2*res),np.arange(res,2*res)) else: X,Y=np.meshgrid(np.arange(res),np.arange(res)) if typ=='contour': plt_ICs=ax.contourf(X,Y,self.ICimg,levels=levels,vmin=vmin,vmax=vmax) if scale: plt.axis('equal') elif typ=='surface': plt_ICs=ax.plot_surface(X,Y,self.ICimg,cmap='jet',vmin=vmin,vmax=vmax) if colorbar: cb=plt.colorbar(plt_ICs,orientation='horizontal',pad=0.05,shrink=0.9) plt.draw() return ax else: printWarning("ICimg is not analyzed yet. Run data analysis first.") return None
def showIC(self,ax=None,roi=None,nlevels=25,vmin=None,vmax=None,typ='contour',scale=True): """Plots initial conditions applied to mesh in 2D or 3D. If ``roi`` is given, will only plot initial conditions for nodes inside ROI, else will plot initial condition for all nodes in mesh. .. note:: Simulation needs to be run first before this plotting function can be used. Example: >>> simulation.plotIC(typ='contour') will produce the following: .. image:: ../imgs/pyfrp_simulation/showIC.png See also :py:func:`pyfrp.modules.pyfrp_plot_module.plotSolutionVariable` and :py:func:`pyfrp.subclasses.pyfrp_ROI.plotSolutionVariable`. Keyword Args: roi (pyfrp.subclasses.pyfrp_ROI.ROI): A PyFRAP ROI object. vmin (float): Overall minimum value to be displayed in plot. vmax (float): Overall maximum value to be displayed in plot. ax (matplotlib.axes): Axes used for plotting. nlevels (int): Number of contour levels to display. typ (str): Typ of plot. scale (bool): Equal axis in case of contour plot. Returns: matplotlib.axes: Axes used for plotting. """ if self.IC!=None: if ax==None: if typ=='surface': fig,axes = pyfrp_plot_module.makeSubplot([1,1],titles=["IC"],proj=['3d'],sup="",tight=False) else: fig,axes = pyfrp_plot_module.makeSubplot([1,1],titles=["IC"],sup="",tight=False) ax=axes[0] if roi==None: x,y,z=self.mesh.getCellCenters() if vmin==None: vmin=min(self.IC) if vmax==None: vmax=max(self.IC) levels=np.linspace(vmin,1.01*vmax,nlevels) if typ=='contour': ax.tricontourf(x,y,self.IC,vmin=vmin,vmax=vmax,levels=levels) if scale: ax.autoscale(enable=True, axis='both', tight=True) elif typ=='surface': ax.plot_trisurf(x,y,self.IC,cmap='jet',vmin=vmin,vmax=vmax) else: printError("Unknown plot type "+ typ) ax.get_figure().canvas.draw() else: ax=roi.plotSolutionVariable(self.IC,ax=ax,nlevels=nlevels,vmin=vmin,vmax=vmax,typ=typ) return ax else: printWarning("IC is not generated yet. Run simulation first.") return None
def plotCellCenters(self,ax=None,proj=None,color='k',indicateHeight=False,s=5.,roi=None): """Plots location of cell centers of mesh. .. note:: If no ``ax`` are given will create new ones. If ``proj=[3d]``, will create 3D scatter plot, otherwise project cell centers in 2D. Example: Create figure >>> fig,axes = pyfrp_plot_module.makeSubplot([2,2],titles=['2D','2D indicate','3D','3D indicate'],proj=[None,None,'3d','3d']) Plot in 4 different ways >>> mesh.plotCellCenters(ax=axes[0],s=1.) >>> mesh.plotCellCenters(ax=axes[1],indicateHeight=True,s=5.) >>> mesh.plotCellCenters(ax=axes[2],s=3.) >>> mesh.plotCellCenters(ax=axes[3],indicateHeight=True,s=3.) .. image:: ../imgs/pyfrp_mesh/plotCellCenters.png Keyword Args: ax (matplotlib.axes): Axes to plot in. proj (list): List of projections. color (str): Color of mesh nodes. indicateHeight (bool): Indicate height by color. s (float): Size of marker. roi (pyfrp.subclasses.pyfrp_ROI): ROI. Returns: matplotlib.axes: Matplotlib axes. """ if ax==None: fig,axes = pyfrp_plot_module.makeSubplot([1,1],titles=["Cell Centers"],proj=proj) ax=axes[0] x,y,z = self.getCellCenters() if roi!=None: x=x[roi.meshIdx] y=y[roi.meshIdx] z=z[roi.meshIdx] if pyfrp_plot_module.is3DAxes(ax): if indicateHeight: #color=cm.jet() ax.scatter(x,y,z,c=z,s=s) else: ax.scatter(x,y,z,c=color,s=s) else: if indicateHeight: ax.scatter(x,y,c=z,s=s) else: ax.scatter(x,y,c=color,s=s) pyfrp_plot_module.redraw(ax) return ax
def showICimg(self, ax=None, typ='contour', colorbar=True, scale=True, nlevels=25, vmin=None, vmax=None): """Plots image used for initial condition either as contour or surface plot. .. image:: ../imgs/pyfrp_simulation/showICimg.png Keyword Args: ax (matplotlib.axes): Axes used for plotting. scale (bool): Equal axis. vmin (float): Overall minimum value to be displayed in plot. vmax (float): Overall maximum value to be displayed in plot. nlevels (int): Number of contour levels to display. Returns: matplotlib.axes: Axes used for plotting. """ #Check of entered plot type makes sense if typ not in ['contour', 'surface']: printError("Unknown plot type " + typ) return ax if self.ICimg != None: if vmin == None: vmin = min(self.ICimg.flatten()) if vmax == None: vmax = max(self.ICimg.flatten()) levels = np.linspace(vmin, 1.01 * vmax, nlevels) if ax == None: if typ == 'surface': fig, axes = pyfrp_plot_module.makeSubplot([1, 1], proj=['3d'], sup="", tight=False) else: fig, axes = pyfrp_plot_module.makeSubplot([1, 1], sup="", tight=False) ax = axes[0] res = self.ICimg.shape[0] if 'quad' in self.embryo.analysis.process.keys(): X, Y = np.meshgrid(np.arange(res, 2 * res), np.arange(res, 2 * res)) else: X, Y = np.meshgrid(np.arange(res), np.arange(res)) if typ == 'contour': plt_ICs = ax.contourf(X, Y, self.ICimg, levels=levels, vmin=vmin, vmax=vmax) if scale: plt.axis('equal') elif typ == 'surface': plt_ICs = ax.plot_surface(X, Y, self.ICimg, cmap='jet', vmin=vmin, vmax=vmax) if colorbar: cb = plt.colorbar(plt_ICs, orientation='horizontal', pad=0.05, shrink=0.9) plt.draw() return ax else: printWarning("ICimg is not analyzed yet. Run data analysis first.") return None
def showIC(self, ax=None, roi=None, nlevels=25, vmin=None, vmax=None, typ='contour', scale=True): """Plots initial conditions applied to mesh in 2D or 3D. If ``roi`` is given, will only plot initial conditions for nodes inside ROI, else will plot initial condition for all nodes in mesh. .. note:: Simulation needs to be run first before this plotting function can be used. Example: >>> simulation.plotIC(typ='contour') will produce the following: .. image:: ../imgs/pyfrp_simulation/showIC.png See also :py:func:`pyfrp.modules.pyfrp_plot_module.plotSolutionVariable` and :py:func:`pyfrp.subclasses.pyfrp_ROI.plotSolutionVariable`. Keyword Args: roi (pyfrp.subclasses.pyfrp_ROI.ROI): A PyFRAP ROI object. vmin (float): Overall minimum value to be displayed in plot. vmax (float): Overall maximum value to be displayed in plot. ax (matplotlib.axes): Axes used for plotting. nlevels (int): Number of contour levels to display. typ (str): Typ of plot. scale (bool): Equal axis in case of contour plot. Returns: matplotlib.axes: Axes used for plotting. """ if self.IC != None: if ax == None: if typ == 'surface': fig, axes = pyfrp_plot_module.makeSubplot([1, 1], titles=["IC"], proj=['3d'], sup="", tight=False) else: fig, axes = pyfrp_plot_module.makeSubplot([1, 1], titles=["IC"], sup="", tight=False) ax = axes[0] if roi == None: x, y, z = self.mesh.getCellCenters() if vmin == None: vmin = min(self.IC) if vmax == None: vmax = max(self.IC) levels = np.linspace(vmin, 1.01 * vmax, nlevels) if typ == 'contour': ax.tricontourf(x, y, self.IC, vmin=vmin, vmax=vmax, levels=levels) if scale: ax.autoscale(enable=True, axis='both', tight=True) elif typ == 'surface': ax.plot_trisurf(x, y, self.IC, cmap='jet', vmin=vmin, vmax=vmax) else: printError("Unknown plot type " + typ) ax.get_figure().canvas.draw() else: ax = roi.plotSolutionVariable(self.IC, ax=ax, nlevels=nlevels, vmin=vmin, vmax=vmax, typ=typ) return ax else: printWarning("IC is not generated yet. Run simulation first.") return None
def plotSolStack(self, phi, ROIs, withGeometry=True, vmin=None, vmax=None, ax=None, colorbar=False): """Plots a stack of the solution variable in a given list of ROIs. Will automatically compute the direction in which ROI lies in the 3D space and reduce the ROI into this plane for contour plot. If ``vmin=None`` or ``vmax=None``, will compute overall maximum and minimum values over all ROIs. Args: phi (fipy.CellVariable): Simulation solution variable (or numpy array). ROIs (list): List of :py:class:`pyfrp.subclasses.pyfrp_ROI.ROI` objects. Keyword Args: withGeometry (bool): Show geometry inside plot. vmin (float): Overall minimum value to be displayed in plot. vmax (float): Overall maximum value to be displayed in plot. ax (matplotlib.axes): Axes used for plotting. colorbar (bool): Display color bar. Returns: matplotlib.axes: Axes used for plotting. """ if ax == None: fig, axes = pyfrp_plot_module.makeSubplot( [1, 1], titles=["Simulation IC stack"], proj=['3d']) ax = axes[0] #Plot geometry if withGeometry: #self.embryo.geometry.updateGeoFile() ax = self.embryo.geometry.plotGeometry(ax=ax) #Find vmin/vmax over all ROIs vminNew = [] vmaxNew = [] for r in ROIs: vminNew.append(min(phi[r.meshIdx])) vmaxNew.append(max(phi[r.meshIdx])) if vmin == None: vmin = min(vminNew) if vmax == None: vmax = min(vmaxNew) for r in ROIs: plane = r.getMaxExtendPlane() zs = r.getPlaneMidCoordinate() zdir = r.getOrthogonal2Plane() ax = r.plotSolutionVariable(phi, ax=ax, vmin=vmin, vmax=vmax, plane=plane, zs=zs, zdir=zdir, colorbar=colorbar) return ax
def plotCellCenters(self, ax=None, proj=None, color='k', indicateHeight=False, s=5., roi=None): """Plots location of cell centers of mesh. .. note:: If no ``ax`` are given will create new ones. If ``proj=[3d]``, will create 3D scatter plot, otherwise project cell centers in 2D. Example: Create figure >>> fig,axes = pyfrp_plot_module.makeSubplot([2,2],titles=['2D','2D indicate','3D','3D indicate'],proj=[None,None,'3d','3d']) Plot in 4 different ways >>> mesh.plotCellCenters(ax=axes[0],s=1.) >>> mesh.plotCellCenters(ax=axes[1],indicateHeight=True,s=5.) >>> mesh.plotCellCenters(ax=axes[2],s=3.) >>> mesh.plotCellCenters(ax=axes[3],indicateHeight=True,s=3.) .. image:: ../imgs/pyfrp_mesh/plotCellCenters.png Keyword Args: ax (matplotlib.axes): Axes to plot in. proj (list): List of projections. color (str): Color of mesh nodes. indicateHeight (bool): Indicate height by color. s (float): Size of marker. roi (pyfrp.subclasses.pyfrp_ROI): ROI. Returns: matplotlib.axes: Matplotlib axes. """ if ax == None: fig, axes = pyfrp_plot_module.makeSubplot([1, 1], titles=["Cell Centers"], proj=proj) ax = axes[0] x, y, z = self.getCellCenters() if roi != None: x = x[roi.meshIdx] y = y[roi.meshIdx] z = z[roi.meshIdx] if pyfrp_plot_module.is3DAxes(ax): if indicateHeight: #color=cm.jet() ax.scatter(x, y, z, c=z, s=s) else: ax.scatter(x, y, z, c=color, s=s) else: if indicateHeight: ax.scatter(x, y, c=z, s=s) else: ax.scatter(x, y, c=color, s=s) pyfrp_plot_module.redraw(ax) return ax