"""Shapes that are circular in nature."""fromnumbersimportNumberimportmatplotlib.pyplotaspltfrommatplotlib.axesimportAxesfrom..data.datasetimportDatasetfrom..plotting.styleimportplot_with_custom_stylefrom.bases.shapeimportShape
[docs]classCircle(Shape):""" Class representing a hollow circle. .. plot:: :scale: 75 :caption: This shape is generated using the panda dataset. from data_morph.data.loader import DataLoader from data_morph.shapes.circles import Circle _ = Circle(DataLoader.load_dataset('panda')).plot() Parameters ---------- dataset : Dataset The starting dataset to morph into other shapes. r : numbers.Number, optional The radius of the circle. """def__init__(self,dataset:Dataset,r:Number=None)->None:self.cx:Number=dataset.df.x.mean()"""numbers.Number: The x coordinate of the circle's center."""self.cy:Number=dataset.df.y.mean()"""numbers.Number: The y coordinate of the circle's center."""self.r:Number=rordataset.df.std().mean()*1.5"""numbers.Number: The radius of the circle."""def__repr__(self)->str:returnf'<{self.__class__.__name__} cx={self.cx} cy={self.cy} r={self.r}>'
[docs]defdistance(self,x:Number,y:Number)->float:""" Calculate the absolute distance between this circle's edge and a point (x, y). Parameters ---------- x, y : numbers.Number Coordinates of a point in 2D space. Returns ------- float The absolute distance between this circle's edge and the point (x, y). """returnabs(self._euclidean_distance((self.cx,self.cy),(x,y))-self.r)
[docs]@plot_with_custom_styledefplot(self,ax:Axes=None)->Axes:""" Plot the shape. Parameters ---------- ax : matplotlib.axes.Axes, optional An optional :class:`~matplotlib.axes.Axes` object to plot on. Returns ------- matplotlib.axes.Axes The :class:`~matplotlib.axes.Axes` object containing the plot. """ifnotax:fig,ax=plt.subplots(layout='constrained')fig.get_layout_engine().set(w_pad=0.2,h_pad=0.2)_=ax.axis('equal')_=ax.add_patch(plt.Circle((self.cx,self.cy),self.r,ec='k',fill=False))_=ax.autoscale()returnax
[docs]classBullseye(Shape):""" Class representing a bullseye shape comprising two concentric circles. .. plot:: :scale: 75 :caption: This shape is generated using the panda dataset. from data_morph.data.loader import DataLoader from data_morph.shapes.circles import Bullseye _ = Bullseye(DataLoader.load_dataset('panda')).plot() Parameters ---------- dataset : Dataset The starting dataset to morph into other shapes. """def__init__(self,dataset:Dataset)->None:stdev=dataset.df.std().mean()self.circles:list[Circle]=[Circle(dataset,r)forrin[stdev,stdev*2]]"""list[Circle]: The inner and outer :class:`Circle` objects."""def__repr__(self)->str:returnself._recursive_repr('circles')
[docs]defdistance(self,x:Number,y:Number)->float:""" Calculate the minimum absolute distance between this bullseye's inner and outer circles' edges and a point (x, y). Parameters ---------- x, y : numbers.Number Coordinates of a point in 2D space. Returns ------- float The minimum absolute distance between this bullseye's inner and outer circles' edges and the point (x, y). See Also -------- Circle.distance : A bullseye consists of two circles, so we use the minimum distance to one of the circles. """returnmin(circle.distance(x,y)forcircleinself.circles)
[docs]@plot_with_custom_styledefplot(self,ax:Axes=None)->Axes:""" Plot the shape. Parameters ---------- ax : matplotlib.axes.Axes, optional An optional :class:`~matplotlib.axes.Axes` object to plot on. Returns ------- matplotlib.axes.Axes The :class:`~matplotlib.axes.Axes` object containing the plot. """forcircleinself.circles:ax=circle.plot(ax)returnax