xarray-graph 0.2.0__py3-none-any.whl → 0.2.2__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.
@@ -42,11 +42,6 @@ from xarray_treeview import *
42
42
  # version info (stored in metadata in case needed later)
43
43
  from importlib.metadata import version
44
44
  XARRAY_GRAPH_VERSION = version('xarray-graph')
45
- try:
46
- i = re.search(r'[a-zA-Z]', XARRAY_GRAPH_VERSION).start()
47
- XARRAY_GRAPH_VERSION = XARRAY_GRAPH_VERSION[:i].rstrip('.')
48
- except Exception:
49
- pass
50
45
 
51
46
 
52
47
  # Currently, color is handled by the widgets themselves.
@@ -120,16 +115,16 @@ class XarrayGraph(QMainWindow):
120
115
  if data is None:
121
116
  data = DataTree()
122
117
  elif isinstance(data, xr.Dataset):
123
- data = DataTree(ds=data)
118
+ data = DataTree(data=data)
124
119
  elif isinstance(data, xr.DataArray):
125
- data = DataTree(ds=xr.Dataset(data_vars={data.name: data}))
120
+ data = DataTree(data=xr.Dataset(data_vars={data.name: data}))
126
121
  elif isinstance(data, np.ndarray):
127
- data = DataTree(ds=xr.Dataset(data_vars={'data': data}))
122
+ data = DataTree(data=xr.Dataset(data_vars={'data': data}))
128
123
  else:
129
124
  # assume list or tuple of two np.ndarrays (x, y)
130
125
  try:
131
126
  x, y = data
132
- data = DataTree(ds=xr.Dataset(data_vars={'y': ('x', y)}, coords={'x': ('x', x)}))
127
+ data = DataTree(data=xr.Dataset(data_vars={'y': ('x', y)}, coords={'x': ('x', x)}))
133
128
  except Exception:
134
129
  raise ValueError('XarrayGraph.data.setter: Invalid input.')
135
130
 
@@ -151,6 +146,12 @@ class XarrayGraph(QMainWindow):
151
146
  # metadata
152
147
  self.attrs['xarray-graph-version'] = XARRAY_GRAPH_VERSION
153
148
 
149
+ # regions tree view
150
+ self._region_treeview.model().setRoot(AxisRegionTreeItem(self.regions))
151
+
152
+ # notes
153
+ self._notes_edit.setPlainText(self.attrs.get('notes', ''))
154
+
154
155
  # populate array math selections
155
156
  # self._update_array_math_comboboxes()
156
157
 
@@ -277,7 +278,7 @@ class XarrayGraph(QMainWindow):
277
278
  filepath = QFileDialog.getExistingDirectory(self, 'Open from Xarray data store...')
278
279
  if filepath == '':
279
280
  return None
280
- self.data = open_datatree(filepath)
281
+ self.data = open_datatree(filepath, 'zarr')
281
282
  self._filepath = filepath
282
283
  self.setWindowTitle(os.path.split(filepath)[1])
283
284
 
@@ -297,31 +298,20 @@ class XarrayGraph(QMainWindow):
297
298
  self.setWindowTitle(os.path.split(filepath)[1])
298
299
 
299
300
  def import_data(self, filepath: str = '', filetype: str = '') -> None:
300
- # ds: xr.Dataset | None = None
301
- # if filetype == 'pCLAMP':
302
- # # TODO: implement
303
- # QMessageBox.warning(self, 'Import pCLAMP', 'Importing pCLAMP files is not yet implemented.')
304
- # return
305
- # elif filetype == 'HEKA':
306
- # # TODO: implement
307
- # QMessageBox.warning(self, 'Import HEKA', 'Importing HEKA files is not yet implemented.')
308
- # return
309
- # elif filetype == 'GOLab TEVC':
310
- # ds, filepath = import_golab_tevc(filepath)
311
- # if ds is None:
312
- # return
313
- # self.set_data(ds)
314
- # if 'regions' in ds.attrs:
315
- # self.metadata['regions'] = ds.attrs['regions']
316
- # del ds.attrs['regions']
317
- # region_labels = [region['label'] for region in self.metadata['regions']]
318
- # self._region_label_list.clear()
319
- # self._region_label_list.addItems(region_labels)
320
- # self.set_selected_region_labels(region_labels)
321
- # if 'notes' in ds.attrs:
322
- # self.metadata['notes'] = ds.attrs['notes']
323
- # del ds.attrs['notes']
324
- # self.load_notes(self.metadata['notes'])
301
+ ds: xr.Dataset | None = None
302
+ if filetype == 'pCLAMP':
303
+ # TODO: implement
304
+ QMessageBox.warning(self, 'Import pCLAMP', 'Importing pCLAMP files is not yet implemented.')
305
+ return
306
+ elif filetype == 'HEKA':
307
+ # TODO: implement
308
+ QMessageBox.warning(self, 'Import HEKA', 'Importing HEKA files is not yet implemented.')
309
+ return
310
+ elif filetype == 'GOLab TEVC':
311
+ ds, filepath = import_golab_tevc(filepath)
312
+ if ds is None:
313
+ return
314
+ self.data = ds
325
315
  self._filepath = os.path.splitext(filepath)[0]
326
316
  self.setWindowTitle(os.path.split(filepath)[1])
327
317
 
@@ -1034,6 +1024,17 @@ class XarrayGraph(QMainWindow):
1034
1024
  if i != index:
1035
1025
  button.setChecked(False)
1036
1026
 
1027
+ def _show_control_panel_at(self, index: int) -> None:
1028
+ actions = self._control_panel_toolbar.actions()
1029
+ widgets = [self._control_panel_toolbar.widgetForAction(action) for action in actions]
1030
+ buttons = [widget for widget in widgets if isinstance(widget, QToolButton)]
1031
+ buttons[index].setChecked(True)
1032
+ self._control_panel.setCurrentIndex(index)
1033
+ self._control_panel.setVisible(True)
1034
+ for i, button in enumerate(buttons):
1035
+ if i != index:
1036
+ button.setChecked(False)
1037
+
1037
1038
  def _setup_data_control_panel(self) -> None:
1038
1039
  button = QToolButton()
1039
1040
  button.setIcon(qta.icon('ph.eye', options=[{'opacity': 0.5}]))
@@ -1043,7 +1044,8 @@ class XarrayGraph(QMainWindow):
1043
1044
  button.released.connect(lambda i=self._control_panel.count(): self._toggle_control_panel_at(i))
1044
1045
  self._control_panel_toolbar.addWidget(button)
1045
1046
 
1046
- self._data_treeview = XarrayTreeView()
1047
+ self._data_treeviewer = XarrayTreeViewer()
1048
+ self._data_treeview = self._data_treeviewer.view()
1047
1049
  self._data_treeview.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
1048
1050
  root: XarrayTreeItem = XarrayTreeItem(node=self.data, key=None)
1049
1051
  model: XarrayTreeModel = XarrayTreeModel(root)
@@ -1051,6 +1053,7 @@ class XarrayGraph(QMainWindow):
1051
1053
  self._data_treeview.setShowCoords(False)
1052
1054
  self._data_treeview.setModel(model)
1053
1055
  self._data_treeview.selectionWasChanged.connect(self._on_tree_selection_changed)
1056
+ self._data_treeviewer.setSizes([100, 1])
1054
1057
 
1055
1058
  self._xdim_combobox = QComboBox()
1056
1059
  self._xdim_combobox.currentTextChanged.connect(self.set_xdim)
@@ -1060,7 +1063,7 @@ class XarrayGraph(QMainWindow):
1060
1063
  vbox.setContentsMargins(0, 0, 0, 0)
1061
1064
  vbox.setSpacing(0)
1062
1065
 
1063
- vbox.addWidget(self._data_treeview)
1066
+ vbox.addWidget(self._data_treeviewer)
1064
1067
 
1065
1068
  form = QFormLayout()
1066
1069
  form.setContentsMargins(5, 3, 0, 3)
@@ -2196,43 +2199,41 @@ def permutations(coords: dict) -> list[dict]:
2196
2199
  return permutations
2197
2200
 
2198
2201
 
2199
- # def import_golab_tevc(filepath: str = '', parent: QWidget = None) -> tuple[xr.Dataset, str]:
2200
- # if filepath == '':
2201
- # filepath, _filter = QFileDialog.getOpenFileName(parent, 'Import GoLab TEVC', '', 'GoLab TEVC (*.mat)')
2202
- # if filepath == '':
2203
- # return None
2204
- # matdict = sp.io.loadmat(filepath, simplify_cells=True)
2205
- # # print(matdict)
2206
- # current = matdict['current']
2207
- # current_units = matdict['current_units']
2208
- # if len(current_units) > 1:
2209
- # prefix = current_units[0]
2210
- # if prefix in metric_scale_factors:
2211
- # current *= metric_scale_factors[prefix]
2212
- # current_units = current_units[1:]
2213
- # time = np.arange(len(current)) * matdict['time_interval_sec']
2214
- # ds = xr.Dataset(
2215
- # data_vars={
2216
- # 'current': (['time'], current, {'units': current_units}),
2217
- # },
2218
- # coords={
2219
- # 'time': (['time'], time, {'units': 's'}),
2220
- # },
2221
- # )
2222
- # if 'events' in matdict and matdict['events']:
2223
- # ds.attrs['regions'] = []
2224
- # for event in matdict['events']:
2225
- # time = event['time_sec']
2226
- # text = event['text']
2227
- # ds.attrs['regions'].append({
2228
- # 'dim': 'time',
2229
- # 'label': f'{time:.6f}',
2230
- # 'region': [time, time],
2231
- # 'text': text,
2232
- # })
2233
- # if 'notes' in matdict:
2234
- # ds.attrs['notes'] = matdict['notes']
2235
- # return ds, filepath
2202
+ def import_golab_tevc(filepath: str = '', parent: QWidget = None) -> tuple[xr.Dataset, str]:
2203
+ if filepath == '':
2204
+ filepath, _filter = QFileDialog.getOpenFileName(parent, 'Import GoLab TEVC', '', 'GoLab TEVC (*.mat)')
2205
+ if filepath == '':
2206
+ return None
2207
+ matdict = sp.io.loadmat(filepath, simplify_cells=True)
2208
+ # print(matdict)
2209
+ current = matdict['current']
2210
+ current_units = matdict['current_units']
2211
+ if len(current_units) > 1:
2212
+ prefix = current_units[0]
2213
+ if prefix in metric_scale_factors:
2214
+ current *= metric_scale_factors[prefix]
2215
+ current_units = current_units[1:]
2216
+ time = np.arange(len(current)) * matdict['time_interval_sec']
2217
+ ds = xr.Dataset(
2218
+ data_vars={
2219
+ 'current': (['time'], current, {'units': current_units}),
2220
+ },
2221
+ coords={
2222
+ 'time': (['time'], time, {'units': 's'}),
2223
+ },
2224
+ )
2225
+ if 'events' in matdict and matdict['events']:
2226
+ ds.attrs['regions'] = []
2227
+ for event in matdict['events']:
2228
+ time = event['time_sec']
2229
+ text = event['text']
2230
+ ds.attrs['regions'].append({
2231
+ 'region': {'time': [time, time]},
2232
+ 'text': text,
2233
+ })
2234
+ if 'notes' in matdict:
2235
+ ds.attrs['notes'] = matdict['notes']
2236
+ return ds, filepath
2236
2237
 
2237
2238
 
2238
2239
  def test_live():
xarray_graph/__main__.py CHANGED
@@ -1,14 +1,76 @@
1
1
  from xarray_graph.XarrayGraph import XarrayGraph
2
+ from qtpy.QtCore import QTimer
2
3
  from qtpy.QtWidgets import QApplication
3
4
 
4
5
 
5
6
  def main():
6
7
  app = QApplication()
7
8
  ui = XarrayGraph()
8
- ui.setWindowTitle(ui.__class__.__name__)
9
+ # ui.setWindowTitle(ui.__class__.__name__)
10
+ ui.setWindowTitle('xarray-graph')
9
11
  ui.show()
12
+ QTimer.singleShot(100, lambda: ask_for_example(ui))
10
13
  app.exec()
11
14
 
12
15
 
16
+ def ask_for_example(ui: XarrayGraph):
17
+ from qtpy.QtWidgets import QMessageBox
18
+
19
+ example = QMessageBox.question(ui, 'Example?', 'Load example data?')
20
+ if example == QMessageBox.StandardButton.Yes:
21
+ load_example(ui)
22
+
23
+
24
+ def load_example(ui: XarrayGraph):
25
+ import numpy as np
26
+ import xarray as xr
27
+ from datatree import DataTree
28
+
29
+ n = 100
30
+ raw_ds = xr.Dataset(
31
+ data_vars={
32
+ 'current': (['series', 'sweep', 'time'], np.random.rand(3, 10, n) * 1e-9, {'units': 'A'}),
33
+ 'voltage': (['series', 'sweep', 'time'], np.random.rand(3, 10, n) * 10000, {'units': 'V'}),
34
+ },
35
+ coords={
36
+ 'series': ('series', np.arange(3)),
37
+ 'sweep': ('sweep', np.arange(10)),
38
+ 'time': ('time', np.arange(n) * 0.01, {'units': 's'}),
39
+ },
40
+ )
41
+
42
+ baselined_ds = xr.Dataset(
43
+ data_vars={
44
+ 'current': (['series', 'sweep', 'time'], np.random.rand(3, 10, n) * 1e-9, {'units': 'A'}),
45
+ },
46
+ coords={
47
+ 'series': ('series', np.arange(3)),
48
+ 'sweep': ('sweep', np.arange(10)),
49
+ 'time': ('time', np.arange(n) * 0.01, {'units': 's'}),
50
+ },
51
+ )
52
+
53
+ scaled_ds = xr.Dataset(
54
+ data_vars={
55
+ 'current': (['series', 'sweep', 'time'], np.random.rand(1, 2, n) * 1e-9, {'units': 'A'}),
56
+ },
57
+ coords={
58
+ 'series': ('series', [1]),
59
+ 'sweep': ('sweep', [5,8]),
60
+ 'time': ('time', np.arange(n) * 0.01, {'units': 's'}),
61
+ },
62
+ )
63
+
64
+ root_node = DataTree()
65
+ raw_node = DataTree(name='raw', data=raw_ds, parent=root_node)
66
+ baselined_node = DataTree(name='baselined', data=baselined_ds, parent=raw_node)
67
+ scaled_node = DataTree(name='scaled', data=scaled_ds, parent=baselined_node)
68
+
69
+ ui.data = root_node
70
+
71
+ ui._show_control_panel_at(0)
72
+ ui._data_treeview.expandAll()
73
+
74
+
13
75
  if __name__ == '__main__':
14
76
  main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xarray-graph
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: PyQt/PySide UI for graphing (x,y) slices of Xarray datasets.
5
5
  Keywords: PyQt,PySide,xarray,graph
6
6
  Home-page: https://github.com/marcel-goldschen-ohm/xarray-graph
@@ -20,11 +20,11 @@ Project-URL: Repository, https://github.com/marcel-goldschen-ohm/xarray-graph
20
20
  Requires-Python: >=3.9
21
21
  Requires-Dist: numpy>=1.26.2
22
22
  Requires-Dist: xarray>=2023.12.0
23
- Requires-Dist: xarray-tree>=0.1.0
24
23
  Requires-Dist: qtpy>=2.4.1
25
24
  Requires-Dist: qtawesome>=1.3.0
26
- Requires-Dist: pyqt-ext>=1.1.0
27
- Requires-Dist: pyqtgraph-ext>=1.0.0
25
+ Requires-Dist: pyqt-ext>=1.2.1
26
+ Requires-Dist: pyqtgraph-ext>=1.2.0
27
+ Requires-Dist: xarray-treeview>=1.2.2
28
28
  Requires-Dist: scipy>=1.11.4
29
29
  Requires-Dist: lmfit>=1.2.2
30
30
  Description-Content-Type: text/markdown
@@ -38,6 +38,11 @@ Should work with PySide6, PyQt6, or PyQt5.
38
38
  pip install PySide6 xarray-graph
39
39
  ```
40
40
 
41
+ # Run
42
+ ```shell
43
+ xarray-graph
44
+ ```
45
+
41
46
  # TODO
42
47
  - i/o
43
48
  - tests
@@ -0,0 +1,9 @@
1
+ xarray_graph-0.2.2.dist-info/METADATA,sha256=YnbvMx6HyGmM7juG94B0Gad3GQnBs0ecGrBdCkAmRsE,1488
2
+ xarray_graph-0.2.2.dist-info/WHEEL,sha256=vnE8JVcI2Wz7GRKorsPArnBdnW2SWKWGow5gu5tHlRU,90
3
+ xarray_graph-0.2.2.dist-info/entry_points.txt,sha256=aW9CKuCZREtN_3Mtg4dKrysPMmHc-tQdUCNmzQYE_vA,61
4
+ xarray_graph-0.2.2.dist-info/licenses/LICENSE,sha256=OE7VkhwkLeFeY8LXi86O-nMXC9B3WsBSILLfPmYGd-8,1077
5
+ xarray_graph/XarrayGraph.py,sha256=nYBqXwW92Jjsb7g4M1zq7ROttf--Pe4rGAOHrx7NT_E,100555
6
+ xarray_graph/__init__.py,sha256=1aAM-Fcno60-ou3AnSqt5HKm6UmZrtULGzg2LF34IJE,48
7
+ xarray_graph/__main__.py,sha256=8c74k8lpaqOuMeKlcBahOKfgo08O7xmJs_htvKKKpck,2274
8
+ xarray_graph/tmp/RegionsManager.py,sha256=0nnrO1e1mqvrs88doO51SJ3JvMNW5wXBKOp2nLQcUFs,1841
9
+ xarray_graph-0.2.2.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ xarray-graph = xarray_graph.__main__:main
3
+
@@ -1,9 +0,0 @@
1
- xarray_graph-0.2.0.dist-info/METADATA,sha256=PlV0f9GGnKYWLqFqs13wQBL1mZsBHs93TztzG4tRhPo,1451
2
- xarray_graph-0.2.0.dist-info/WHEEL,sha256=vnE8JVcI2Wz7GRKorsPArnBdnW2SWKWGow5gu5tHlRU,90
3
- xarray_graph-0.2.0.dist-info/entry_points.txt,sha256=8qLdEjfVtm86FytoAItpsjvgDEUDj2e7Z2ekiTkUsQs,52
4
- xarray_graph-0.2.0.dist-info/licenses/LICENSE,sha256=OE7VkhwkLeFeY8LXi86O-nMXC9B3WsBSILLfPmYGd-8,1077
5
- xarray_graph/RegionsManager.py,sha256=0nnrO1e1mqvrs88doO51SJ3JvMNW5wXBKOp2nLQcUFs,1841
6
- xarray_graph/XarrayGraph.py,sha256=7hAiKNx0UcLT9rQfGX-vvfeVz0FcjCMVw5o7PL2fRvU,100581
7
- xarray_graph/__init__.py,sha256=1aAM-Fcno60-ou3AnSqt5HKm6UmZrtULGzg2LF34IJE,48
8
- xarray_graph/__main__.py,sha256=TMeudufLyynSMYS3WuLpHxUjr0ijfb_-a3vnZgEomgQ,265
9
- xarray_graph-0.2.0.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- xrg = xarray_graph.__main__:main
3
-