From 12cc78f0a48d0f285f09e066af817846f89181c8 Mon Sep 17 00:00:00 2001 From: Deren Date: Sat, 22 Apr 2023 14:39:02 -0400 Subject: [PATCH 1/6] Point extents func to fit marker size + stroke --- toyplot/mark.py | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/toyplot/mark.py b/toyplot/mark.py index b435d548..f63ba28c 100644 --- a/toyplot/mark.py +++ b/toyplot/mark.py @@ -805,7 +805,7 @@ def __init__( self._table = toyplot.require.instance(table, toyplot.data.Table) - # We require at last one coordinate dimension (number of dimensions = D) + # We require at least one coordinate dimension (number of dimensions = D) self._coordinate_axes = toyplot.require.string_vector(coordinate_axes, min_length=1) D = len(self._coordinate_axes) @@ -839,6 +839,43 @@ def domain(self, axis): columns = [coordinate_column for coordinate_axis, coordinate_column in zip(itertools.cycle(self._coordinate_axes), self._coordinates) if coordinate_axis == axis] return toyplot.data.minimax([self._table[column] for column in columns]) + def extents(self, axis: str): + """Return extents in 2 dimensions. + + TODO: could support higher dimensions + """ + # iterate over entered axes (e.g., ['x', 'y']) if exists for Mark + assert all(i in self._coordinate_axes for i in axis) + + # get coordinates + coords = tuple(self._table[i] for i in self._coordinates) + + # get empty extents arrays to be filled below. + xext = numpy.zeros(coords[0].size) + yext = numpy.zeros(coords[0].size) + + # extents requires marker shape (rect or not), size, and stroke-width + stroke_width = self._mstyle.get("stroke-width", 0) + iterdata = zip( + range(coords[0].size), + self._table[self._marker[0]], + self._table[self._msize[0]], + ) + + # fill extents (left, right, top, bottom) for each marker + for idx, shape, size in iterdata: + + # if 'r2x1' then width is 2X height + if shape[0] == "r": + width, height = (int(i) for i in shape[1:].split("x")) + else: + width, height = 1, 1 + + # extent is half of size diameter, stroke is already half + xext[idx] = (width * size) / 2 + stroke_width + yext[idx] = (height * size) / 2 + stroke_width + return coords, (-xext, xext, -yext, yext) + @property def markers(self): result = [] From ff6dcf1579d6a513ccf9d4ed1739f5673446b784 Mon Sep 17 00:00:00 2001 From: Deren Date: Sat, 22 Apr 2023 18:18:15 -0400 Subject: [PATCH 2/6] only check value stroke_width if _mstyle --- toyplot/mark.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/toyplot/mark.py b/toyplot/mark.py index f63ba28c..b35160af 100644 --- a/toyplot/mark.py +++ b/toyplot/mark.py @@ -855,7 +855,9 @@ def extents(self, axis: str): yext = numpy.zeros(coords[0].size) # extents requires marker shape (rect or not), size, and stroke-width - stroke_width = self._mstyle.get("stroke-width", 0) + stroke_width = 0 + if hasattr(self, "_mstyle"): + stroke_width = self._mstyle.get("stroke-width", 0) iterdata = zip( range(coords[0].size), self._table[self._marker[0]], From 19c3ebf431873a01d8e15251166993090edaf1bb Mon Sep 17 00:00:00 2001 From: Deren Date: Sat, 22 Apr 2023 18:26:17 -0400 Subject: [PATCH 3/6] _mstyle can be None, or {} w/ or w/o stroke-width key --- toyplot/mark.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/toyplot/mark.py b/toyplot/mark.py index b35160af..107eb816 100644 --- a/toyplot/mark.py +++ b/toyplot/mark.py @@ -855,9 +855,8 @@ def extents(self, axis: str): yext = numpy.zeros(coords[0].size) # extents requires marker shape (rect or not), size, and stroke-width - stroke_width = 0 - if hasattr(self, "_mstyle"): - stroke_width = self._mstyle.get("stroke-width", 0) + _mstyle = {} if self._mstyle is None else self._mstyle + stroke_width = _mstyle.get("stroke-width", 0) iterdata = zip( range(coords[0].size), self._table[self._marker[0]], From c4985f873b07dc12696ebfdbc0eaaeb33834e401 Mon Sep 17 00:00:00 2001 From: Deren Date: Wed, 24 May 2023 18:26:00 -0400 Subject: [PATCH 4/6] bugfix: Point extents for 1 or 2 dim data --- toyplot/mark.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/toyplot/mark.py b/toyplot/mark.py index 107eb816..3084b1af 100644 --- a/toyplot/mark.py +++ b/toyplot/mark.py @@ -839,16 +839,15 @@ def domain(self, axis): columns = [coordinate_column for coordinate_axis, coordinate_column in zip(itertools.cycle(self._coordinate_axes), self._coordinates) if coordinate_axis == axis] return toyplot.data.minimax([self._table[column] for column in columns]) - def extents(self, axis: str): - """Return extents in 2 dimensions. - - TODO: could support higher dimensions + def extents(self, axes): + """Return extents in 1 or 2 dimensions. """ # iterate over entered axes (e.g., ['x', 'y']) if exists for Mark - assert all(i in self._coordinate_axes for i in axis) + assert all(i in self._coordinate_axes for i in axes) - # get coordinates - coords = tuple(self._table[i] for i in self._coordinates) + # get coordinates of 'x' 'y' from potentially ['x', 'y0', 'x', 'y1', ... etc] + axis_map = {key: index for index, key in enumerate(self._coordinate_axes)} + coords = tuple([self._table[self._coordinates[axis_map[axis]]] for axis in axes]) # get empty extents arrays to be filled below. xext = numpy.zeros(coords[0].size) From 33f03c952ac922cf543f89d4f0bfd4cdc0ab8e63 Mon Sep 17 00:00:00 2001 From: Deren Date: Thu, 25 May 2023 13:47:45 -0400 Subject: [PATCH 5/6] minor change to trigger tests --- toyplot/mark.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/toyplot/mark.py b/toyplot/mark.py index 3084b1af..fb9d43b4 100644 --- a/toyplot/mark.py +++ b/toyplot/mark.py @@ -874,6 +874,8 @@ def extents(self, axes): # extent is half of size diameter, stroke is already half xext[idx] = (width * size) / 2 + stroke_width yext[idx] = (height * size) / 2 + stroke_width + + # return is usually parsed: (x, y), (left, right, bottom, top) = ... return coords, (-xext, xext, -yext, yext) @property From 7f349640fd2a08eea505dc807c393708cb34631a Mon Sep 17 00:00:00 2001 From: Deren Date: Mon, 12 Jun 2023 17:19:00 -0400 Subject: [PATCH 6/6] cosmetic --- toyplot/mark.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/toyplot/mark.py b/toyplot/mark.py index fb9d43b4..147bfee5 100644 --- a/toyplot/mark.py +++ b/toyplot/mark.py @@ -840,8 +840,7 @@ def domain(self, axis): return toyplot.data.minimax([self._table[column] for column in columns]) def extents(self, axes): - """Return extents in 1 or 2 dimensions. - """ + """Return extents in 1 or 2 dimensions.""" # iterate over entered axes (e.g., ['x', 'y']) if exists for Mark assert all(i in self._coordinate_axes for i in axes)