Skip to content

Commit 389525b

Browse files
Add data behavior (#95)
* Add data feature * Only retain video on failure Co-authored-by: Duc Trung Le <[email protected]> * Fix comment Co-authored-by: Duc Trung Le <[email protected]> --------- Co-authored-by: Duc Trung Le <[email protected]>
1 parent df1a1ca commit 389525b

File tree

14 files changed

+210
-19
lines changed

14 files changed

+210
-19
lines changed

examples/session.glu

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@
318318
"y_axislabel_weight": "st__normal",
319319
"y_log": false,
320320
"y_max": 1168792.8,
321-
"y_min": 0.0,
321+
"y_min": 0,
322322
"y_ticklabel_size": 8
323323
}
324324
}
@@ -339,7 +339,7 @@
339339
"bias": 0.5,
340340
"cmap": "LinearSegmentedColormap_0",
341341
"color": "st__#595959",
342-
"contrast": 1.0,
342+
"contrast": 1,
343343
"global_sync": false,
344344
"layer": "w5",
345345
"percentile": 100,
@@ -515,7 +515,7 @@
515515
"cmap_vmax": 3151.745849609375,
516516
"cmap_vmin": 438.1081848144531,
517517
"color": "st__#595959",
518-
"density_contrast": 1.0,
518+
"density_contrast": 1,
519519
"density_map": true,
520520
"fill": true,
521521
"layer": "w5",
@@ -556,7 +556,7 @@
556556
"cmap_vmax": 3744.811767578125,
557557
"cmap_vmin": 438.5635070800781,
558558
"color": "st__#e31a1c",
559-
"density_contrast": 1.0,
559+
"density_contrast": 1,
560560
"density_map": true,
561561
"fill": true,
562562
"layer": "Subset 1_0",
@@ -597,7 +597,7 @@
597597
"cmap_vmax": 17766,
598598
"cmap_vmin": 2,
599599
"color": "st__#595959",
600-
"density_contrast": 1.0,
600+
"density_contrast": 1,
601601
"density_map": false,
602602
"fill": true,
603603
"layer": "w5_psc",
@@ -638,7 +638,7 @@
638638
"cmap_vmax": 17771,
639639
"cmap_vmin": 4,
640640
"color": "st__#e31a1c",
641-
"density_contrast": 1.0,
641+
"density_contrast": 1,
642642
"density_map": false,
643643
"fill": true,
644644
"layer": "Subset 1_1",
@@ -679,7 +679,7 @@
679679
"cmap_vmax": 3151.745849609375,
680680
"cmap_vmin": 438.1081848144531,
681681
"color": "st__#595959",
682-
"density_contrast": 1.0,
682+
"density_contrast": 1,
683683
"density_map": true,
684684
"fill": true,
685685
"layer": "w5",
@@ -720,7 +720,7 @@
720720
"cmap_vmax": 3744.811767578125,
721721
"cmap_vmin": 438.5635070800781,
722722
"color": "st__#e31a1c",
723-
"density_contrast": 1.0,
723+
"density_contrast": 1,
724724
"density_map": true,
725725
"fill": true,
726726
"layer": "Subset 1_0",
@@ -1120,7 +1120,7 @@
11201120
"st__CRVAL2": 60.38,
11211121
"st__CTYPE1": "st__RA---TAN",
11221122
"st__CTYPE2": "st__DEC--TAN",
1123-
"st__EQUINOX": 2000.0,
1123+
"st__EQUINOX": 2000,
11241124
"st__HISTORY": [
11251125
"",
11261126
" Settings used in processing:",

gluepyter/glue_session.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
import os
2+
import json
13
import warnings
24
from pathlib import Path
35
from typing import TYPE_CHECKING, Dict, Optional, Tuple
46

7+
from glue.core.link_helpers import LinkSame
8+
from glue.core.state import GlueSerializer
59
import glue_jupyter as gj
610
from glue_jupyter.view import IPyWidgetView
711
from glue_jupyter.widgets.layer_options import LayerOptionsWidget
12+
813
import y_py as Y
9-
from glue.core.link_helpers import LinkSame
14+
1015
from IPython.display import display
16+
1117
from ipywidgets import Output
18+
1219
from jupyter_ydoc import ydocs
1320
from ypywidgets import Widget
1421

@@ -140,6 +147,13 @@ def render_viewer(self) -> None:
140147
)
141148

142149
saved_viewer["widget"] = widget
150+
151+
# This may be the error widget
152+
if widget is None or not hasattr(widget, "viewer_options"):
153+
with output:
154+
display(widget)
155+
return
156+
143157
viewer_options = widget.viewer_options
144158
try:
145159
layer_options = LayerOptionsWidget(widget)
@@ -156,6 +170,10 @@ def render_viewer(self) -> None:
156170
viewer_state=state,
157171
)
158172

173+
# This may be the error widget
174+
if widget is None or not hasattr(widget, "viewer_options"):
175+
return
176+
159177
viewer_options = widget.viewer_options
160178
try:
161179
layer_options = LayerOptionsWidget(widget)
@@ -309,6 +327,37 @@ def _init_ydoc(self) -> None:
309327
ydoc=self._sessionYDoc,
310328
)
311329

330+
def add_data(self, file_path: str) -> None:
331+
"""Add a new data file to the session"""
332+
relative_path = Path(file_path).relative_to(Path(self._path).parent)
333+
assert os.path.exists(relative_path)
334+
335+
data = self.app.load_data(str(relative_path))
336+
self._data[data.label] = data
337+
338+
# We generate the data representation and merge it into our ycontent
339+
serializer = GlueSerializer(data)
340+
serialized_data = serializer.dumpo()
341+
342+
contents = self._document.contents
343+
344+
# Inject the main data repr
345+
contents[data.label] = serialized_data["__main__"]
346+
# Inject all components
347+
for key, value in serialized_data.items():
348+
if key != "__main__":
349+
contents[key] = value
350+
# Inject the label in the data collection
351+
contents["DataCollection"]["data"].append(data.label)
352+
contents["DataCollection"]["cids"].extend(
353+
cid for cid, comp in serialized_data["__main__"]["components"]
354+
)
355+
contents["DataCollection"]["components"].extend(
356+
comp for cid, comp in serialized_data["__main__"]["components"]
357+
)
358+
359+
self._document.set(json.dumps(contents))
360+
312361
def _load_data(self) -> None:
313362
"""Load data defined in the glue session"""
314363
data_paths = {}

src/leftPanel/data/dataPanel.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { CommandRegistry } from '@lumino/commands';
2+
23
import { SidePanel, ToolbarButton } from '@jupyterlab/ui-components';
4+
5+
import { FileDialog } from '@jupyterlab/filebrowser';
6+
import { IDocumentManager } from '@jupyterlab/docmanager';
7+
38
import { DatasetsWidget } from './datasetsWidget';
49
import { SubsetsWidget } from './subsetsWidget';
510
import { IControlPanelModel } from '../../types';
@@ -8,6 +13,7 @@ export class DataPanel extends SidePanel {
813
constructor(options: {
914
model: IControlPanelModel;
1015
commands: CommandRegistry;
16+
manager: IDocumentManager;
1117
}) {
1218
super();
1319

@@ -17,7 +23,39 @@ export class DataPanel extends SidePanel {
1723
new ToolbarButton({
1824
tooltip: 'Add Data',
1925
label: 'Add Data',
20-
onClick: () => console.log('clicked')
26+
onClick: async () => {
27+
if (!options.model.currentSessionPath) {
28+
// TODO Show an error dialog, or disable the button?
29+
return;
30+
}
31+
32+
const output = await FileDialog.getOpenFiles({
33+
title: 'Load Data Files Into Glue Session',
34+
manager: options.manager
35+
});
36+
37+
if (!output.value) {
38+
return;
39+
}
40+
41+
const kernel = this._model.currentSessionKernel();
42+
if (kernel === undefined) {
43+
// TODO Show an error dialog
44+
return;
45+
}
46+
47+
for (const file of output.value) {
48+
const filePath = file.path.includes(':')
49+
? file.path.split(':')[1]
50+
: file.path;
51+
const code = `
52+
GLUE_SESSION.add_data("${filePath}")
53+
`;
54+
55+
const future = kernel.requestExecute({ code }, false);
56+
await future.done;
57+
}
58+
}
2159
})
2260
);
2361
this._model = options.model;

src/leftPanel/model.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { IGlueSessionTracker } from '../token';
1111
import { IGlueSessionTabs } from '../_interface/glue.schema';
1212
import { ISessionContext } from '@jupyterlab/apputils';
13+
import { IKernelConnection } from '@jupyterlab/services/lib/kernel/kernel';
1314

1415
export class ControlPanelModel implements IControlPanelModel {
1516
constructor(options: ControlPanelModel.IOptions) {
@@ -22,6 +23,7 @@ export class ControlPanelModel implements IControlPanelModel {
2223
);
2324
}
2425
this._sessionModel = changed?.context.model;
26+
this._currentSessionPath = changed?.context.path;
2527
this._tabs = this._sessionModel?.sharedModel.tabs ?? {};
2628
this._sessionModel?.sharedModel.tabsChanged.connect(
2729
this._onTabsChanged,
@@ -53,6 +55,10 @@ export class ControlPanelModel implements IControlPanelModel {
5355
return this._clearConfigRequested;
5456
}
5557

58+
get currentSessionPath(): string | undefined {
59+
return this._currentSessionPath;
60+
}
61+
5662
get selectedDataset(): string | null {
5763
return this._selectedDataset;
5864
}
@@ -80,6 +86,10 @@ export class ControlPanelModel implements IControlPanelModel {
8086
return this._tracker.currentWidget?.context.sessionContext;
8187
}
8288

89+
currentSessionKernel(): IKernelConnection | undefined {
90+
return this._tracker.currentWidget?.sessionWidget.kernel;
91+
}
92+
8393
displayConfig(args: IRequestConfigDisplay): void {
8494
this._displayConfigRequested.emit(args);
8595
}
@@ -97,6 +107,7 @@ export class ControlPanelModel implements IControlPanelModel {
97107
IGlueSessionWidget | null
98108
>(this);
99109
private _tabs: IGlueSessionTabs = {};
110+
private _currentSessionPath: string | undefined = undefined;
100111
private _tabsChanged = new Signal<IControlPanelModel, void>(this);
101112
private _selectedDataset: string | null = null;
102113
private _selectedDatasetChanged = new Signal<IControlPanelModel, void>(this);

src/leftPanel/plugin.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { UUID } from '@lumino/coreutils';
1212
import { CommandRegistry } from '@lumino/commands';
1313
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
1414
import { GridStackItem } from '../viewPanel/gridStackItem';
15+
import { DocumentRegistry } from '@jupyterlab/docregistry';
16+
import { DocumentManager } from '@jupyterlab/docmanager';
1517

1618
const NAME_SPACE = 'gluepyter';
1719

@@ -183,11 +185,19 @@ export const controlPanel: JupyterFrontEndPlugin<void> = {
183185

184186
const controlModel = new ControlPanelModel({ tracker });
185187

188+
const docRegistry = new DocumentRegistry();
189+
const docManager = new DocumentManager({
190+
registry: docRegistry,
191+
manager: app.serviceManager,
192+
opener
193+
});
194+
186195
const controlPanel = new ControlPanelWidget({
187196
model: controlModel,
188197
tracker,
189198
commands,
190-
rendermime
199+
rendermime,
200+
manager: docManager
191201
});
192202

193203
controlPanel.id = 'gluepyter::controlPanel';

src/leftPanel/widget.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { SidePanel } from '@jupyterlab/ui-components';
22
import { CommandRegistry } from '@lumino/commands';
33
import { Message } from '@lumino/messaging';
44
import { BoxPanel } from '@lumino/widgets';
5+
import { IDocumentManager } from '@jupyterlab/docmanager';
56

67
import { HTabPanel } from '../common/tabPanel';
78
import { IGlueSessionTracker } from '../token';
@@ -17,7 +18,7 @@ export class ControlPanelWidget extends SidePanel {
1718
const content = new BoxPanel();
1819
super({ content });
1920
this.addClass('glue-sidepanel-widget');
20-
const { model, rendermime, commands } = options;
21+
const { model, rendermime, commands, manager } = options;
2122
this._model = model;
2223
const header = new ControlPanelHeader();
2324
this.header.addWidget(header);
@@ -28,7 +29,8 @@ export class ControlPanelWidget extends SidePanel {
2829
});
2930
const data = new DataPanel({
3031
model: this._model,
31-
commands
32+
commands,
33+
manager
3234
});
3335
const canvas = new ConfigPanel({ model, rendermime });
3436

@@ -69,5 +71,6 @@ export namespace LeftPanelWidget {
6971
tracker: IGlueSessionTracker;
7072
commands: CommandRegistry;
7173
rendermime: IRenderMimeRegistry;
74+
manager: IDocumentManager;
7275
}
7376
}

src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import { ISessionContext } from '@jupyterlab/apputils';
1414
import { SessionWidget } from './viewPanel/sessionWidget';
1515
import { GridStackItem } from './viewPanel/gridStackItem';
16+
import { IKernelConnection } from '@jupyterlab/services/lib/kernel/kernel';
1617

1718
export const DATASET_MIME = 'application/x-gluejupyter-dataset';
1819

@@ -99,6 +100,7 @@ export interface IRequestConfigDisplay {
99100
export interface IControlPanelModel {
100101
sharedModel: IGlueSessionSharedModel | undefined;
101102
glueSessionChanged: ISignal<IControlPanelModel, IGlueSessionWidget | null>;
103+
currentSessionPath: string | undefined;
102104
selectedDataset: string | null;
103105
selectedDatasetChanged: ISignal<IControlPanelModel, void>;
104106
tabsChanged: ISignal<IControlPanelModel, void>;
@@ -109,6 +111,7 @@ export interface IControlPanelModel {
109111
displayConfig(args: IRequestConfigDisplay): void;
110112
clearConfig(): void;
111113
currentSessionContext(): ISessionContext | undefined;
114+
currentSessionKernel(): IKernelConnection | undefined;
112115
}
113116

114117
export type IGlueSessionViewerTypes = ValueOf<IGlueSessionTabs>[0];

0 commit comments

Comments
 (0)