plopp 25.4.0__py3-none-any.whl → 25.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -81,6 +81,7 @@ class Line:
81
81
  'linestyle': 'solid',
82
82
  'linewidth': 1.5,
83
83
  'color': f'C{artist_number}',
84
+ 'zorder': 2,
84
85
  }
85
86
  markers = list(Line2D.markers.keys())
86
87
  default_plot_style = {
@@ -88,6 +89,7 @@ class Line:
88
89
  'linewidth': 1.5,
89
90
  'marker': markers[(artist_number + 2) % len(markers)],
90
91
  'color': f'C{artist_number}',
92
+ 'zorder': 2,
91
93
  }
92
94
 
93
95
  if line_data["hist"]:
@@ -95,40 +97,35 @@ class Line:
95
97
  line_data['values']['x'],
96
98
  line_data['values']['y'],
97
99
  label=self.label,
98
- zorder=10,
99
100
  **{**default_step_style, **line_args},
100
101
  )[0]
101
102
 
102
103
  self._mask = self._ax.step(line_data['mask']['x'], line_data['mask']['y'])[
103
104
  0
104
105
  ]
105
- self._mask.update_from(self._line)
106
- self._mask.set_color(mask_color)
107
- self._mask.set_label(None)
108
- self._mask.set_linewidth(self._mask.get_linewidth() * 3)
109
- self._mask.set_zorder(self._mask.get_zorder() - 1)
110
- self._mask.set_visible(line_data['mask']['visible'])
111
106
  else:
112
107
  self._line = self._ax.plot(
113
108
  line_data['values']['x'],
114
109
  line_data['values']['y'],
115
110
  label=self.label,
116
- zorder=10,
117
111
  **{**default_plot_style, **line_args},
118
112
  )[0]
119
- self._mask = self._ax.plot(
120
- line_data['mask']['x'],
121
- line_data['mask']['y'],
122
- zorder=11,
123
- mec=mask_color,
124
- mfc="None",
125
- mew=3.0,
126
- linestyle="none",
127
- marker=self._line.get_marker(),
128
- visible=line_data['mask']['visible'],
129
- )[0]
113
+ self._mask = self._ax.plot(line_data['mask']['x'], line_data['mask']['y'])[
114
+ 0
115
+ ]
130
116
 
131
- self.line_mask = sc.array(dims=['x'], values=~np.isnan(line_data['mask']['y']))
117
+ self._mask.update_from(self._line)
118
+ self._mask.set_color(mask_color)
119
+ self._mask.set_label(None)
120
+ self._mask.set_visible(line_data['mask']['visible'])
121
+ if self._line.get_marker().lower() != 'none':
122
+ self._mask.set(
123
+ mec=mask_color, mfc='None', mew=3.0, zorder=self._line.get_zorder() + 1
124
+ )
125
+ if self._line.get_linestyle().lower() != 'none':
126
+ self._mask.set(
127
+ lw=self._line.get_linewidth() * 3, zorder=self._line.get_zorder() - 1
128
+ )
132
129
 
133
130
  # Add error bars
134
131
  if errorbars and (line_data['stddevs'] is not None):
@@ -137,7 +134,7 @@ class Line:
137
134
  line_data['stddevs']['y'],
138
135
  yerr=line_data['stddevs']['e'],
139
136
  color=self._line.get_color(),
140
- zorder=10,
137
+ zorder=self._line.get_zorder(),
141
138
  fmt="none",
142
139
  )
143
140
 
@@ -153,7 +150,6 @@ class Line:
153
150
  check_ndim(new_values, ndim=1, origin='Line')
154
151
  self._data = new_values
155
152
  line_data = make_line_data(data=self._data, dim=self._dim)
156
- self.line_mask = sc.array(dims=['x'], values=~np.isnan(line_data['mask']['y']))
157
153
 
158
154
  self._line.set_data(line_data['values']['x'], line_data['values']['y'])
159
155
  self._mask.set_data(line_data['mask']['x'], line_data['mask']['y'])
@@ -60,7 +60,7 @@ class Line:
60
60
  artist_number: int = 0,
61
61
  errorbars: bool = True,
62
62
  mask_color: str = 'black',
63
- mode: str = 'markers',
63
+ mode: str | None = None,
64
64
  marker: str | None = None,
65
65
  **kwargs,
66
66
  ):
@@ -87,14 +87,17 @@ class Line:
87
87
  'color': default_colors[artist_number % len(default_colors)]
88
88
  }
89
89
  default_marker_style = {
90
- 'symbol': artist_number % 53
91
- } # Plotly has 52 marker styles
90
+ 'symbol': artist_number % 52 # Plotly has 52 marker styles
91
+ }
92
92
 
93
93
  line_shape = None
94
94
 
95
- if line_data["hist"]:
96
- line_shape = 'vh'
97
- mode = 'lines'
95
+ if mode is None:
96
+ if line_data["hist"]:
97
+ line_shape = 'vh'
98
+ mode = 'lines'
99
+ else:
100
+ mode = 'markers'
98
101
 
99
102
  marker_style = default_marker_style if marker is None else marker
100
103
  line_style = {**default_line_style, **line_args}
@@ -130,7 +133,7 @@ class Line:
130
133
  line_style['width'] *= 5
131
134
  else:
132
135
  line_style['width'] = 5
133
- if line_data["hist"]:
136
+ if 'lines' in mode:
134
137
  line_style['color'] = mask_color
135
138
 
136
139
  self._mask = go.Scatter(
@@ -149,7 +152,7 @@ class Line:
149
152
  # that ends up in the figure is a copy of the one above.
150
153
  # Plotly has no concept of zorder, so we need to add the traces in a specific
151
154
  # order
152
- if line_data["hist"]:
155
+ if 'lines' in mode:
153
156
  self._fig.add_trace(self._mask)
154
157
  self._mask = self._fig.data[-1]
155
158
  self._fig.add_trace(self._line)
@@ -165,9 +168,8 @@ class Line:
165
168
  self._error = self._fig.data[-1]
166
169
  self._fig.add_trace(self._mask)
167
170
  self._mask = self._fig.data[-1]
168
- self._line._plopp_id = self.uid
169
- self.line_mask = sc.array(dims=['x'], values=~np.isnan(line_data['mask']['y']))
170
171
 
172
+ self._line._plopp_id = self.uid
171
173
  self._mask._plopp_id = self.uid
172
174
  if self._error is not None:
173
175
  self._error._plopp_id = self.uid
@@ -184,7 +186,6 @@ class Line:
184
186
  check_ndim(new_values, ndim=1, origin='Line')
185
187
  self._data = new_values
186
188
  line_data = make_line_data(data=self._data, dim=self._dim)
187
- self.line_mask = sc.array(dims=['x'], values=~np.isnan(line_data['mask']['y']))
188
189
 
189
190
  with self._fig.batch_update():
190
191
  self._line.update(
@@ -21,6 +21,15 @@ def _none_if_not_finite(x: float | None) -> float | int | None:
21
21
  return x if np.isfinite(x) else None
22
22
 
23
23
 
24
+ def _make_range(
25
+ old: tuple[float, float], new: tuple[float, float]
26
+ ) -> tuple[float | None, float | None]:
27
+ new = (_none_if_not_finite(new[0]), _none_if_not_finite(new[1]))
28
+ if (old is not None) and (None not in old) and (old[0] > old[1]):
29
+ new = (new[1], new[0])
30
+ return new
31
+
32
+
24
33
  class GraphicalView(View):
25
34
  """
26
35
  Base class for graphical 1d and 2d views.
@@ -113,18 +122,15 @@ class GraphicalView(View):
113
122
  bbox = bbox.union(artist.bbox(**scales))
114
123
  self.bbox = bbox
115
124
  self.bbox = self.bbox.override(self.canvas.bbox)
116
- self.canvas.xrange = (
117
- _none_if_not_finite(self.bbox.xmin),
118
- _none_if_not_finite(self.bbox.xmax),
125
+ self.canvas.xrange = _make_range(
126
+ old=self.canvas.xrange, new=(self.bbox.xmin, self.bbox.xmax)
119
127
  )
120
- self.canvas.yrange = (
121
- _none_if_not_finite(self.bbox.ymin),
122
- _none_if_not_finite(self.bbox.ymax),
128
+ self.canvas.yrange = _make_range(
129
+ old=self.canvas.yrange, new=(self.bbox.ymin, self.bbox.ymax)
123
130
  )
124
131
  if hasattr(self.canvas, 'zrange'):
125
- self.canvas.zrange = (
126
- _none_if_not_finite(self.bbox.zmin),
127
- _none_if_not_finite(self.bbox.zmax),
132
+ self.canvas.zrange = _make_range(
133
+ old=self.canvas.zrange, new=(self.bbox.zmin, self.bbox.zmax)
128
134
  )
129
135
 
130
136
  def update(self, *args, **kwargs) -> None:
plopp/plotting/common.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
3
 
4
4
  import warnings
5
- from collections.abc import Callable
5
+ from collections.abc import Callable, Iterable
6
6
  from typing import Any
7
7
 
8
8
  import numpy as np
@@ -76,8 +76,30 @@ def to_variable(obj) -> sc.Variable:
76
76
  return out
77
77
 
78
78
 
79
+ def _ensure_data_array_coords(
80
+ da: sc.DataArray, coords: list[str] | None
81
+ ) -> sc.DataArray:
82
+ if coords is None:
83
+ coords = list(da.dims)
84
+ elif missing := set(coords) - set(da.coords.keys()):
85
+ raise ValueError(f"Specified coords do not exist: {missing}")
86
+
87
+ # Remove unused coords
88
+ da = da.drop_coords(list(set(da.coords) - set(coords)))
89
+ # Assign dim coords where missing. The above checks ensure that all missing
90
+ # coords are dim coords, i.e., that `name in out.dims`.
91
+ da = da.assign_coords(
92
+ {
93
+ name: sc.arange(name, da.sizes[name], unit=None)
94
+ for name in set(coords) - set(da.coords)
95
+ }
96
+ )
97
+ return da
98
+
99
+
79
100
  def to_data_array(
80
101
  obj: Plottable | list,
102
+ coords: list[str] | None = None,
81
103
  ) -> sc.DataArray:
82
104
  """
83
105
  Convert an input to a DataArray, potentially adding fake coordinates if they are
@@ -87,6 +109,8 @@ def to_data_array(
87
109
  ----------
88
110
  obj:
89
111
  The input object to be converted.
112
+ coords:
113
+ If supplied, use these coords instead of the input's dimension coordinates.
90
114
  """
91
115
  out = _maybe_to_variable(obj)
92
116
  if isinstance(out, sc.Variable):
@@ -94,15 +118,13 @@ def to_data_array(
94
118
  out = from_compatible_lib(out)
95
119
  if not isinstance(out, sc.DataArray):
96
120
  raise TypeError(f"Cannot convert input of type {type(obj)} to a DataArray.")
97
- out = out.copy(deep=False)
98
- for dim, size in out.sizes.items():
99
- if dim not in out.coords:
100
- out.coords[dim] = sc.arange(dim, size, unit=None)
101
- if not out.coords[dim].dims:
121
+ out = _ensure_data_array_coords(out, coords)
122
+ for name, coord in out.coords.items():
123
+ if not coord.dims:
102
124
  raise ValueError(
103
125
  "Input data cannot be plotted: it has a scalar coordinate along "
104
- f"dimension {dim}. Consider dropping this coordinate before plotting. "
105
- f"Use ``data.drop_coords('{dim}').plot()``."
126
+ f"dimension {name}. Consider dropping this coordinate before plotting. "
127
+ f"Use ``data.drop_coords('{name}').plot()``."
106
128
  )
107
129
  for name in out.coords:
108
130
  other_dims = [dim for dim in out.coords[name].dims if dim not in out.dims]
@@ -171,7 +193,7 @@ def preprocess(
171
193
  obj: Plottable | list,
172
194
  name: str | None = None,
173
195
  ignore_size: bool = False,
174
- coords: list[str] | None = None,
196
+ coords: Iterable[str] | str | None = None,
175
197
  ) -> sc.DataArray:
176
198
  """
177
199
  Pre-process input data for plotting.
@@ -192,7 +214,12 @@ def preprocess(
192
214
  coords:
193
215
  If supplied, use these coords instead of the input's dimension coordinates.
194
216
  """
195
- out = to_data_array(obj)
217
+ if isinstance(coords, str):
218
+ coords = [coords]
219
+ elif coords is not None:
220
+ coords = list(coords)
221
+
222
+ out = to_data_array(obj, coords)
196
223
  check_not_binned(out)
197
224
  check_allowed_dtypes(out)
198
225
  if name is not None:
@@ -201,8 +228,6 @@ def preprocess(
201
228
  _check_size(out)
202
229
  if coords is not None:
203
230
  renamed_dims = {}
204
- if isinstance(coords, str):
205
- coords = [coords]
206
231
  for dim in coords:
207
232
  underlying = out.coords[dim].dims[-1]
208
233
  if underlying in renamed_dims:
plopp/plotting/plot.py CHANGED
@@ -85,6 +85,7 @@ def plot(
85
85
  """
86
86
 
87
87
  common_args = {
88
+ 'aspect': aspect,
88
89
  'grid': grid,
89
90
  'norm': norm,
90
91
  'scale': scale,
@@ -119,12 +120,7 @@ def plot(
119
120
  elif ndim == 2:
120
121
  if len(nodes) > 1:
121
122
  raise_multiple_inputs_for_2d_plot_error(origin='plot')
122
- return imagefigure(
123
- *nodes,
124
- aspect=aspect,
125
- cbar=cbar,
126
- **common_args,
127
- )
123
+ return imagefigure(*nodes, cbar=cbar, **common_args)
128
124
  else:
129
125
  raise ValueError(
130
126
  'The plot function can only plot 1d and 2d data, got input '
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plopp
3
- Version: 25.4.0
3
+ Version: 25.5.0
4
4
  Summary: Visualization library for Scipp
5
5
  Author: Scipp contributors
6
6
  License: BSD 3-Clause License
@@ -8,7 +8,7 @@ plopp/backends/matplotlib/canvas.py,sha256=aAiDC2PfirZlffX671Xzs7GswtOfJjywf_nCh
8
8
  plopp/backends/matplotlib/fast_image.py,sha256=1tF4G8kTmgmiybdD-KPIatU2dWwv0dgv4r8IMDQTTGE,6532
9
9
  plopp/backends/matplotlib/figure.py,sha256=Emj8KCIFvesEfAoKIWn4M4TcgZhq6zFTfRTFnLZHGxE,5515
10
10
  plopp/backends/matplotlib/image.py,sha256=YnczwdxsGmh0Nvrk1A8xL93ap2rzKI-0G428OCQmSCc,974
11
- plopp/backends/matplotlib/line.py,sha256=5umUmPU-7yJVHRGd4WCddWrw197asJc4RmVCmcxQDyM,8982
11
+ plopp/backends/matplotlib/line.py,sha256=xWZx_3j7_O1IoNjVOu-KM4Ue9haQ5IqHjRsY-VhyKak,8779
12
12
  plopp/backends/matplotlib/mesh_image.py,sha256=4ndrauA71asWJdA6ZDkh6iPnQPk07kNd3m1h0_bTM6U,8542
13
13
  plopp/backends/matplotlib/scatter.py,sha256=NuYi9G4csQTklUjB7WXSjothrH77C0NY0KHiMPHBqcw,6739
14
14
  plopp/backends/matplotlib/tiled.py,sha256=BfFHNQ-or19X44N-XaaUf9A3trdSSaCfC2CIAR1WTPg,6127
@@ -16,7 +16,7 @@ plopp/backends/matplotlib/utils.py,sha256=24gmT2sBHS_wUitUThSLavwSK95uqbLAhadNdx
16
16
  plopp/backends/plotly/__init__.py,sha256=QNPZgWV3wO8psaMkSB-GtTOP-OIe9jSfwDdEt2xgbZg,107
17
17
  plopp/backends/plotly/canvas.py,sha256=JQXl8c23Ju-DTame2rZ4T_lgrArgH1WElUGJIaGyEbU,8943
18
18
  plopp/backends/plotly/figure.py,sha256=60QsXUFjr3CqXjxVpAbvd1c-wtq7T5fptotwybgUEcI,1356
19
- plopp/backends/plotly/line.py,sha256=JkguZatKpsJVxXkw2C_sGzfpHvByBkBhRvbK8Hbv4Tw,9623
19
+ plopp/backends/plotly/line.py,sha256=yVpJW-xWa0Wy_oMdmvDn2ESIJymT9Fg6wN7RhIRK6Dw,9533
20
20
  plopp/backends/pythreejs/__init__.py,sha256=XvSD58Tj5WBrrOjkePcCrRW6RbbyrvhhWI_S8-AR92U,107
21
21
  plopp/backends/pythreejs/canvas.py,sha256=yn6iz4BcaNpJZa-lUlyQ5BnYTThb3zYTUv7zWohhaMo,11942
22
22
  plopp/backends/pythreejs/figure.py,sha256=n9R1YokZMRPGA2XP9qeMIGGe-wcTt91vAiexVf7YRnc,2022
@@ -43,14 +43,14 @@ plopp/graphics/bbox.py,sha256=3WeMgu5LgWIXLJTYVT7_USwaAcS7cQPNCk6B0gvuNGo,3596
43
43
  plopp/graphics/camera.py,sha256=fXc1YH7Tp-rwKkcYeE-mHrxMz3SKauj5xJCRuKv-QPs,5323
44
44
  plopp/graphics/colormapper.py,sha256=u5cADKU9lrRkJ_a969i_5z-mdT0-lBnEonc0PW_xSXA,9643
45
45
  plopp/graphics/figures.py,sha256=PLWQLnQNWz8epubYlK7HLSkvPGJmTAmHjJM2DqpvLe8,2735
46
- plopp/graphics/graphicalview.py,sha256=uX6KLMy5r0yqbFVSE3y0T7kW7oAg8CVuioIBOtTNVTc,9183
46
+ plopp/graphics/graphicalview.py,sha256=u5sz3CebhVLoEeKPpzlBlPfRrRORxDmruyfhLXDbH00,9436
47
47
  plopp/graphics/tiled.py,sha256=gXYZVAs6wRFKezzN3VlEvm7_z2zx3IDYfGZQZqrpL80,1386
48
48
  plopp/plotting/__init__.py,sha256=s25RIbKplHSRn0jjtLADPQl72JLf_KLRMRCfeMDI_UA,205
49
49
  plopp/plotting/__init__.pyi,sha256=95wYGfM5PT0Y0Ov_ue7rBrHvHxrtex-2WEYtfFzBvE0,475
50
- plopp/plotting/common.py,sha256=ZEFJ8dZC0aQ_Ucrvu7JXiwaKZ6YT7qfdg8pMZVpX62Y,8696
50
+ plopp/plotting/common.py,sha256=7xR2aWUWzKyxshlPn8B-OWQ5Hy8wiMn-qtPywkLsNRs,9515
51
51
  plopp/plotting/inspector.py,sha256=fT4v342pqTzihKaweoGD4WaQ5eDdyngK7W451Mh2Ffw,3586
52
52
  plopp/plotting/mesh3d.py,sha256=KjAtlVlLYslwgP_uE067WtJRgNURkhaz0PPUuYLlJyw,2778
53
- plopp/plotting/plot.py,sha256=S3Af6PQb7Eu0_t7qoKMMkS6hyt6iah-Hm1RWGi5PnEA,3934
53
+ plopp/plotting/plot.py,sha256=WQzw1vHGljWY1tQU1InQWe2-M-vCW2IRiL-v7cnw46w,3886
54
54
  plopp/plotting/scatter.py,sha256=ybPWFHFwxt_Bzv3Dy-yAFCRHW5HQEggcNihpzWduH7A,3161
55
55
  plopp/plotting/scatter3d.py,sha256=oizd-BCgmvNu_fSV6FQt9oe7lPn4h2Zc1ohKmor-d78,3819
56
56
  plopp/plotting/slicer.py,sha256=A3g26czD6GM3vBlVS-IBOnCOlpaERqUhjT-_POYJEHQ,5877
@@ -68,8 +68,8 @@ plopp/widgets/slice.py,sha256=ihiGEGGva_2WZIug-kizg1I5SFdMzu4_8DDzuHWIKeA,4212
68
68
  plopp/widgets/style.py,sha256=Fw4S8te0xDyT8-kWu4Ut35aLgyr98qMlWZRbXbd1-dk,184
69
69
  plopp/widgets/toolbar.py,sha256=ueNeOZSC2suAG7nCJzqwl8DmtWD5c2J8VkuP-XzJRwI,4683
70
70
  plopp/widgets/tools.py,sha256=9l7LmB8qG0OTt5ZJihJzqRna1ouxJthO_Ahnq7WKTtY,7172
71
- plopp-25.4.0.dist-info/licenses/LICENSE,sha256=fCqnkzCwkGneGtgOidkO2b3ed6SGZT0yhuworuJG0K0,1553
72
- plopp-25.4.0.dist-info/METADATA,sha256=cqHue5Jw4_iSbJaip6MORBBRqbOOHbFqyiBpaZfNDT0,4533
73
- plopp-25.4.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
74
- plopp-25.4.0.dist-info/top_level.txt,sha256=Lk_GLFh37eX-3PO3c6bPkDpir7GjJmbQHYza3IpIphc,6
75
- plopp-25.4.0.dist-info/RECORD,,
71
+ plopp-25.5.0.dist-info/licenses/LICENSE,sha256=fCqnkzCwkGneGtgOidkO2b3ed6SGZT0yhuworuJG0K0,1553
72
+ plopp-25.5.0.dist-info/METADATA,sha256=bFuzQ8XlAfiKyqMeiONKwEdMhN1te45ZHTGETPx8CtE,4533
73
+ plopp-25.5.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
74
+ plopp-25.5.0.dist-info/top_level.txt,sha256=Lk_GLFh37eX-3PO3c6bPkDpir7GjJmbQHYza3IpIphc,6
75
+ plopp-25.5.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.7.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5