vidavis 0.0.5__tar.gz → 0.0.6__tar.gz

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.
Files changed (35) hide show
  1. {vidavis-0.0.5 → vidavis-0.0.6}/PKG-INFO +1 -23
  2. {vidavis-0.0.5 → vidavis-0.0.6}/pyproject.toml +3 -1
  3. {vidavis-0.0.5 → vidavis-0.0.6}/readme.rst +0 -22
  4. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/apps/_ms_raster.py +6 -3
  5. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_ms_plot.py +73 -50
  6. {vidavis-0.0.5 → vidavis-0.0.6}/LICENSE +0 -0
  7. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/LICENSE.rst +0 -0
  8. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/__init__.py +0 -0
  9. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/apps/__init__.py +0 -0
  10. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/bokeh/__init__.py +0 -0
  11. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/bokeh/_palette.py +0 -0
  12. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/__init__.py +0 -0
  13. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/__init__.py +0 -0
  14. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/_ms_data.py +0 -0
  15. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/__init__.py +0 -0
  16. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_concat.py +0 -0
  17. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_coords.py +0 -0
  18. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_data.py +0 -0
  19. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_io.py +0 -0
  20. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_raster_data.py +0 -0
  21. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_select.py +0 -0
  22. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_ps_stats.py +0 -0
  23. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/data/measurement_set/processing_set/_xds_data.py +0 -0
  24. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/__init__.py +0 -0
  25. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/__init__.py +0 -0
  26. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_ms_plot_constants.py +0 -0
  27. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_ms_plot_selectors.py +0 -0
  28. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_raster_plot.py +0 -0
  29. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_raster_plot_inputs.py +0 -0
  30. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_time_ticks.py +0 -0
  31. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/plot/ms_plot/_xds_plot_axes.py +0 -0
  32. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/toolbox/__init__.py +0 -0
  33. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/toolbox/_app_context.py +0 -0
  34. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/toolbox/_logging.py +0 -0
  35. {vidavis-0.0.5 → vidavis-0.0.6}/src/vidavis/toolbox/_static.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vidavis
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Radio astronomy visibility data visualization
5
5
  License: LGPL
6
6
  Author-email: Darrell Schiebel <darrell@schiebel.us>,Pam Harris <pharris@nrao.edu>
@@ -43,9 +43,6 @@ Requirements
43
43
  - Optionally `python-casacore <https://pypi.org/project/python-casacore/>`_ or
44
44
  `casatools <https://pypi.org/project/casatools/>`_ for MSv2 conversion
45
45
 
46
- - Optionally `Selenium <https://www.selenium.dev/documentation/en/>`_ along with
47
- a web driver to export to file using ``save()``
48
-
49
46
  Install
50
47
  ```````
51
48
 
@@ -62,25 +59,6 @@ On macOS it is required to pre-install `python-casacore` using:
62
59
 
63
60
  - :code:`conda install -c conda-forge python-casacore`
64
61
 
65
- Exporting Plots
66
- ^^^^^^^^^^^^^^^
67
-
68
- To enable exporting plots to file without showing the plot, using preferred web
69
- driver:
70
-
71
- **Selenium** with **geckodriver** and **Firefox** (to ensure compatible versions):
72
-
73
- - :code:`conda install -c conda-forge selenium firefox geckodriver`
74
-
75
- **Selenium** with **ChromeDriver** (Chrome), with the executable
76
- **chromedriver** in your PATH:
77
-
78
- - :code:`conda install -c conda-forge selenium python-chromedriver-binary`
79
-
80
- or:
81
-
82
- - :code:`pip install selenium chromedriver-binary`
83
-
84
62
  Simple MsRaster Usage Example
85
63
  `````````````````````````````
86
64
 
@@ -8,12 +8,14 @@ authors = [
8
8
  ]
9
9
  dependencies = [
10
10
  "bokeh==3.6.1",
11
+ "matplotlib",
11
12
  "hvplot",
12
13
  "graphviper",
14
+ "selenium",
13
15
  ]
14
16
  requires-python = ">=3.11, <3.14"
15
17
  readme = "readme.rst"
16
- version = "0.0.5"
18
+ version = "0.0.6"
17
19
 
18
20
  [project.license]
19
21
  text = "LGPL"
@@ -34,9 +34,6 @@ Requirements
34
34
  - Optionally `python-casacore <https://pypi.org/project/python-casacore/>`_ or
35
35
  `casatools <https://pypi.org/project/casatools/>`_ for MSv2 conversion
36
36
 
37
- - Optionally `Selenium <https://www.selenium.dev/documentation/en/>`_ along with
38
- a web driver to export to file using ``save()``
39
-
40
37
  Install
41
38
  ```````
42
39
 
@@ -53,25 +50,6 @@ On macOS it is required to pre-install `python-casacore` using:
53
50
 
54
51
  - :code:`conda install -c conda-forge python-casacore`
55
52
 
56
- Exporting Plots
57
- ^^^^^^^^^^^^^^^
58
-
59
- To enable exporting plots to file without showing the plot, using preferred web
60
- driver:
61
-
62
- **Selenium** with **geckodriver** and **Firefox** (to ensure compatible versions):
63
-
64
- - :code:`conda install -c conda-forge selenium firefox geckodriver`
65
-
66
- **Selenium** with **ChromeDriver** (Chrome), with the executable
67
- **chromedriver** in your PATH:
68
-
69
- - :code:`conda install -c conda-forge selenium python-chromedriver-binary`
70
-
71
- or:
72
-
73
- - :code:`pip install selenium chromedriver-binary`
74
-
75
53
  Simple MsRaster Usage Example
76
54
  `````````````````````````````
77
55
 
@@ -244,10 +244,13 @@ class MsRaster(MsPlot):
244
244
  Args:
245
245
  filename (str): Name of file to save. Default '': the plot will be saved as {ms}_raster.{ext}.
246
246
  If fmt is not set for extension, plot will be saved as .png.
247
- fmt (str): Format of file to save ('png', 'html', or 'gif').
247
+ fmt (str): Format of file to save ('png', 'svg', or 'html').
248
248
  Default 'auto': inferred from filename extension.
249
- width (int): width of exported plot.
250
- height (int): height of exported plot.
249
+ width (int): width of exported plot in pixels.
250
+ height (int): height of exported plot in pixels.
251
+
252
+ If subplots defines a grid layout, width and height describe the size of each plot in the layout.
253
+ The layout plot size will be (width * columns, height * rows) pixels.
251
254
 
252
255
  If iteration plots were created:
253
256
  If subplots is a grid, the layout plot will be saved to a single file.
@@ -5,11 +5,13 @@ Base class for ms plots
5
5
  import os
6
6
  import time
7
7
 
8
- from bokeh.plotting import show
8
+ from bokeh.io import export_png, export_svg
9
+ from bokeh.plotting import save, show
9
10
  import hvplot
10
11
  import holoviews as hv
11
12
  import numpy as np
12
13
  import panel as pn
14
+ from selenium import webdriver
13
15
 
14
16
  try:
15
17
  from toolviper.utils.logger import get_logger, setup_logger
@@ -140,27 +142,21 @@ class MsPlot:
140
142
  self._plots_locked = True
141
143
 
142
144
  # Single plot or combine plots into layout using subplots (rows, columns)
143
- # Not layout if subplots is single plot (default if None) or if only one plot saved
144
- subplots = self._plot_inputs['subplots']
145
- layout_plot, is_layout = self._layout_plots(subplots)
146
-
147
- # Render to bokeh figure
148
- if is_layout:
149
- # Show plots in columns
150
- plot = hv.render(layout_plot.cols(subplots[1]))
151
- else:
152
- # Show single plot
153
- plot = hv.render(layout_plot)
145
+ layout_plot = self._layout_plots(self._plot_inputs['subplots'])
146
+
147
+ # Render plot as Bokeh Figure or GridPlot
148
+ bokeh_fig = hv.render(layout_plot)
154
149
 
155
150
  self._plots_locked = False
156
151
  if self._plot_params:
152
+ # Show plot and plot inputs in tabs
157
153
  column = pn.Column()
158
154
  for param in self._plot_params:
159
155
  column.append(pn.pane.Str(param))
160
- tabs = pn.Tabs(('Plot', plot), ('Plot Inputs', column))
156
+ tabs = pn.Tabs(('Plot', bokeh_fig), ('Plot Inputs', column))
161
157
  tabs.show(title=self._app_name, threaded=True)
162
158
  else:
163
- show(plot)
159
+ show(bokeh_fig)
164
160
 
165
161
  def save(self, filename='ms_plot.png', fmt='auto', width=900, height=600):
166
162
  '''
@@ -175,51 +171,78 @@ class MsPlot:
175
171
 
176
172
  start_time = time.time()
177
173
 
178
- # Save single plot or combine plots into layout using subplots (rows, columns).
179
- # Not layout if subplots is single plot or if only one plot saved.
180
- subplots = self._plot_inputs['subplots']
181
- layout_plot, is_layout = self._layout_plots(subplots)
182
-
183
- if is_layout:
184
- # Save plots combined into one layout
185
- hvplot.save(layout_plot.cols(subplots[1]), filename=filename, fmt=fmt)
186
- self._logger.info("Saved plot to %s.", filename)
187
- else:
188
- # Save plots individually, with index appended if exprange='all' and multiple plots.
189
- if self._plot_inputs['iter_axis'] is None:
190
- hvplot.save(layout_plot.opts(width=width, height=height), filename=filename, fmt=fmt)
191
- self._logger.info("Saved plot to %s.", filename)
192
- else:
193
- name, ext = os.path.splitext(filename)
194
- iter_range = self._plot_inputs['iter_range'] # None or (start, end)
195
- plot_idx = 0 if iter_range is None else iter_range[0]
174
+ name, ext = os.path.splitext(filename)
175
+ fmt = ext[1:] if fmt=='auto' else fmt
196
176
 
197
- for plot in self._plots:
198
- exportname = f"{name}_{plot_idx}{ext}"
199
- hvplot.save(plot.opts(width=width, height=height), filename=exportname, fmt=fmt)
200
- self._logger.info("Saved plot to %s.", exportname)
201
- plot_idx += 1
177
+ # Combine plots into layout using subplots (rows, columns) if not single plot.
178
+ # Set fixed size for export.
179
+ layout_plot = self._layout_plots(self._plot_inputs['subplots'], (width, height))
202
180
 
181
+ if not isinstance(layout_plot, hv.Layout) and self._plot_inputs['iter_axis']:
182
+ # Save iterated plots individually, with index appended to filename
183
+ plot_idx = 0 if self._plot_inputs['iter_range'] is None else self._plot_inputs['iter_range'][0]
184
+ for plot in self._plots:
185
+ exportname = f"{name}_{plot_idx}{ext}"
186
+ self._save_plot(plot, exportname, fmt)
187
+ plot_idx += 1
188
+ else:
189
+ self._save_plot(layout_plot, filename, fmt)
203
190
  self._logger.debug("Save elapsed time: %.2fs.", time.time() - start_time)
204
191
 
205
- def _layout_plots(self, subplots):
192
+ def _layout_plots(self, subplots, fixed_size=None):
193
+ ''' Combine plots in a layout, using fixed size for the layout if given '''
206
194
  subplots = (1, 1) if subplots is None else subplots
207
- num_plots = len(self._plots)
208
- num_layout_plots = min(num_plots, np.prod(subplots))
195
+ num_plots = min(len(self._plots), np.prod(subplots))
196
+ plot_width = fixed_size[0] if fixed_size else None
197
+ plot_height = fixed_size[1] if fixed_size else None
209
198
 
210
- if num_layout_plots == 1:
211
- return self._plots[0], False
199
+ if num_plots == 1:
200
+ # Single plot, not layout
201
+ plot = self._plots[0]
202
+ if fixed_size:
203
+ plot = plot.opts(responsive=False, width=plot_width, height=plot_height, clone=True)
204
+ return plot
212
205
 
213
206
  # Set plots in layout
214
- plot_count = 0
215
- layout = None
216
- for i in range(num_layout_plots):
207
+ layout_plot = None
208
+ for i in range(num_plots):
217
209
  plot = self._plots[i]
218
- layout = plot if layout is None else layout + plot
219
- plot_count += 1
220
-
221
- is_layout = plot_count > 1
222
- return layout, is_layout
210
+ if fixed_size:
211
+ plot = plot.opts(responsive=False, width=plot_width, height=plot_height, clone=True)
212
+ layout_plot = plot if layout_plot is None else layout_plot + plot
213
+
214
+ # Layout in columns
215
+ return layout_plot.cols(subplots[1])
216
+
217
+ def _save_plot(self, plot, filename, fmt):
218
+ ''' Save plot using hvplot, else bokeh '''
219
+ # Remove toolbar unless html
220
+ toolbar = 'right' if fmt=='html' else None
221
+ plot = plot.opts(toolbar=toolbar, clone=True)
222
+
223
+ try:
224
+ hvplot.save(plot, filename=filename, fmt=fmt)
225
+ except (Exception, RuntimeError) as exc:
226
+ # Fails if hvplot cannot find web driver or fmt is svg.
227
+ # Render a Bokeh Figure or GridPlot, create webdriver, then use Bokeh to export.
228
+ fig = hv.render(plot)
229
+ if fmt=='html':
230
+ save(fig, filename)
231
+ elif fmt in ['png', 'svg']:
232
+ # Use Chrome web driver
233
+ service = webdriver.ChromeService()
234
+ options = webdriver.ChromeOptions()
235
+ options.add_argument('--headless')
236
+ options.add_argument('--no-sandbox')
237
+
238
+ with webdriver.Chrome(service=service, options=options) as driver:
239
+ if fmt=='png':
240
+ export_png(fig, filename=filename, webdriver=driver)
241
+ elif fmt=='svg':
242
+ export_svg(fig, filename=filename, webdriver=driver)
243
+ else:
244
+ raise ValueError(f"Invalid fmt or filename extension {fmt} for save()") from exc
245
+ self._logger.info("Saved plot to %s.", filename)
223
246
 
224
247
  def _set_ms(self, ms_path):
225
248
  ''' Set MsData and update ms info for input ms filepath (MSv2 or zarr), if set.
File without changes
File without changes
File without changes