Skip to content

Commit

Permalink
Fix border color and width (#38)
Browse files Browse the repository at this point in the history
* Check for border color and width

* Update local variable name too

* Handle stroke width as a sequence

* Use relative border width when appropriate

* Add explicit test for points content

* Use edge_width for napari v0.4
  • Loading branch information
andy-sweet authored Jun 16, 2024
1 parent 5778489 commit 857129b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 12 deletions.
33 changes: 32 additions & 1 deletion napari_svg/_tests/test_write_layer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import numpy as np
import pytest
from pathlib import Path
from napari.layers import Image, Points, Labels, Shapes, Vectors
from napari.utils.colormaps.colormap_utils import ensure_colormap
from napari_svg import (
Expand Down Expand Up @@ -160,4 +161,34 @@ def test_write_image_colormaps_vispy(tmpdir, layer_writer_and_data, path_ensure,
assert return_path == path

# Check file now exists
assert os.path.isfile(path)
assert os.path.isfile(path)


def test_write_points_with_attributes(request, tmp_path):
data = [
[0, 0],
[0, 128],
[128, 128],
]
size = [16, 20, 24]
face_color = ['red', 'green', 'blue']
edge_color = ['cyan', 'magenta', 'yellow']
edge_width = [0.05, 0.25, 0.5]
layer = Points(
data,
opacity=0.5,
size=size,
face_color=face_color,
edge_color=edge_color,
edge_width=edge_width,
edge_width_is_relative=True,
)
test_name = request.node.name
path = tmp_path / f'{test_name}-actual.svg'
layer_data, layer_attrs, _ = layer.as_layer_data_tuple()

return_path = napari_write_points(path, layer_data, layer_attrs)
assert return_path == path

expected_path = Path(__file__).parent / f'{test_name}-expected.svg'
assert path.read_text() == expected_path.read_text()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 24 additions & 11 deletions napari_svg/layer_to_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,20 @@ def points_to_xml(data, meta):
else:
face_color = np.ones((data.shape[0], 4))

if 'edge_color' in meta:
edge_color = meta['edge_color']
if 'border_color' in meta:
stroke_color = meta['border_color']
elif 'edge_color' in meta:
stroke_color = meta['edge_color']
else:
edge_color = np.zeros((data.shape[0], 4))
edge_color[:, 3] = 1
stroke_color = np.zeros((data.shape[0], 4))
stroke_color[:, 3] = 1

if 'edge_width' in meta:
edge_width = meta['edge_width']
if 'border_width' in meta:
stroke_width = meta['border_width']
elif 'edge_width' in meta:
stroke_width = meta['edge_width']
else:
edge_width = 1
stroke_width = np.ones((data.shape[0],))

if 'opacity' in meta:
opacity = meta['opacity']
Expand All @@ -203,17 +207,26 @@ def points_to_xml(data, meta):
# Find extrema of data
extrema = np.array([points.min(axis=0), points.max(axis=0)])

props = {'stroke-width': str(edge_width), 'opacity': str(opacity)}
# Ensure stroke width is an array to handle older versions of
# napari (e.g. v0.4.0) where it could be a scalar.
stroke_width = np.broadcast_to(stroke_width, (data.shape[0],)).copy()

if meta.get('border_width_is_relative') or meta.get('edge_width_is_relative'):
stroke_width *= size

xml_list = []
for p, s, fc, ec in zip(points, size, face_color, edge_color):
for p, s, fc, sc, sw in zip(points, size, face_color, stroke_color, stroke_width):
cx = str(p[1])
cy = str(p[0])
r = str(s / 2)
fc_int = (255 * fc).astype(int)
fill = f'rgb{tuple(fc_int[:3])}'
ec_int = (255 * ec).astype(int)
stroke = f'rgb{tuple(ec_int[:3])}'
sc_int = (255 * sc).astype(int)
stroke = f'rgb{tuple(sc_int[:3])}'
props = {
'stroke-width': str(sw),
'opacity': str(opacity),
}
element = Element(
'circle', cx=cx, cy=cy, r=r, stroke=stroke, fill=fill, **props
)
Expand Down

0 comments on commit 857129b

Please sign in to comment.