xarray-graph 0.2.1__tar.gz → 0.2.2__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.
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/PKG-INFO +3 -3
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/pyproject.toml +3 -3
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/src/xarray_graph/XarrayGraph.py +64 -74
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/LICENSE +0 -0
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/README.md +0 -0
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/src/xarray_graph/__init__.py +0 -0
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/src/xarray_graph/__main__.py +0 -0
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/src/xarray_graph/tmp/RegionsManager.py +0 -0
- {xarray_graph-0.2.1 → xarray_graph-0.2.2}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: xarray-graph
|
|
3
|
-
Version: 0.2.
|
|
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
|
|
@@ -22,9 +22,9 @@ Requires-Dist: numpy>=1.26.2
|
|
|
22
22
|
Requires-Dist: xarray>=2023.12.0
|
|
23
23
|
Requires-Dist: qtpy>=2.4.1
|
|
24
24
|
Requires-Dist: qtawesome>=1.3.0
|
|
25
|
-
Requires-Dist: pyqt-ext>=1.2.
|
|
25
|
+
Requires-Dist: pyqt-ext>=1.2.1
|
|
26
26
|
Requires-Dist: pyqtgraph-ext>=1.2.0
|
|
27
|
-
Requires-Dist: xarray-treeview>=1.2.
|
|
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
|
|
@@ -11,9 +11,9 @@ dependencies = [
|
|
|
11
11
|
"xarray>=2023.12.0",
|
|
12
12
|
"qtpy>=2.4.1",
|
|
13
13
|
"qtawesome>=1.3.0",
|
|
14
|
-
"pyqt-ext>=1.2.
|
|
14
|
+
"pyqt-ext>=1.2.1",
|
|
15
15
|
"pyqtgraph-ext>=1.2.0",
|
|
16
|
-
"xarray-treeview>=1.2.
|
|
16
|
+
"xarray-treeview>=1.2.2",
|
|
17
17
|
"scipy>=1.11.4",
|
|
18
18
|
"lmfit>=1.2.2",
|
|
19
19
|
]
|
|
@@ -35,7 +35,7 @@ classifiers = [
|
|
|
35
35
|
"Programming Language :: Python :: 3.12",
|
|
36
36
|
"Programming Language :: Python :: 3.13",
|
|
37
37
|
]
|
|
38
|
-
version = "0.2.
|
|
38
|
+
version = "0.2.2"
|
|
39
39
|
|
|
40
40
|
[project.license]
|
|
41
41
|
text = "MIT"
|
|
@@ -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(
|
|
118
|
+
data = DataTree(data=data)
|
|
124
119
|
elif isinstance(data, xr.DataArray):
|
|
125
|
-
data = DataTree(
|
|
120
|
+
data = DataTree(data=xr.Dataset(data_vars={data.name: data}))
|
|
126
121
|
elif isinstance(data, np.ndarray):
|
|
127
|
-
data = DataTree(
|
|
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(
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
|
|
@@ -1054,7 +1044,8 @@ class XarrayGraph(QMainWindow):
|
|
|
1054
1044
|
button.released.connect(lambda i=self._control_panel.count(): self._toggle_control_panel_at(i))
|
|
1055
1045
|
self._control_panel_toolbar.addWidget(button)
|
|
1056
1046
|
|
|
1057
|
-
self.
|
|
1047
|
+
self._data_treeviewer = XarrayTreeViewer()
|
|
1048
|
+
self._data_treeview = self._data_treeviewer.view()
|
|
1058
1049
|
self._data_treeview.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
|
1059
1050
|
root: XarrayTreeItem = XarrayTreeItem(node=self.data, key=None)
|
|
1060
1051
|
model: XarrayTreeModel = XarrayTreeModel(root)
|
|
@@ -1062,6 +1053,7 @@ class XarrayGraph(QMainWindow):
|
|
|
1062
1053
|
self._data_treeview.setShowCoords(False)
|
|
1063
1054
|
self._data_treeview.setModel(model)
|
|
1064
1055
|
self._data_treeview.selectionWasChanged.connect(self._on_tree_selection_changed)
|
|
1056
|
+
self._data_treeviewer.setSizes([100, 1])
|
|
1065
1057
|
|
|
1066
1058
|
self._xdim_combobox = QComboBox()
|
|
1067
1059
|
self._xdim_combobox.currentTextChanged.connect(self.set_xdim)
|
|
@@ -1071,7 +1063,7 @@ class XarrayGraph(QMainWindow):
|
|
|
1071
1063
|
vbox.setContentsMargins(0, 0, 0, 0)
|
|
1072
1064
|
vbox.setSpacing(0)
|
|
1073
1065
|
|
|
1074
|
-
vbox.addWidget(self.
|
|
1066
|
+
vbox.addWidget(self._data_treeviewer)
|
|
1075
1067
|
|
|
1076
1068
|
form = QFormLayout()
|
|
1077
1069
|
form.setContentsMargins(5, 3, 0, 3)
|
|
@@ -2207,43 +2199,41 @@ def permutations(coords: dict) -> list[dict]:
|
|
|
2207
2199
|
return permutations
|
|
2208
2200
|
|
|
2209
2201
|
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
#
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
# ds.attrs['notes'] = matdict['notes']
|
|
2246
|
-
# 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
|
|
2247
2237
|
|
|
2248
2238
|
|
|
2249
2239
|
def test_live():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|