dotdata_widgets 0.1.0 → 0.1.1
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.
- package/README.md +19 -7
- package/css/colors.css +120 -0
- package/css/typography.css +35 -0
- package/css/widget.css +53 -3
- package/dist/index.js +2 -2
- package/lib/components/accordion/Accordion.js +18 -0
- package/lib/components/accordion/index.js +1 -0
- package/lib/components/input/index.js +1 -0
- package/lib/components/input/input.js +6 -0
- package/lib/extension.js +1 -14
- package/lib/feature-descriptor/feature-details/FeatureCorrelatedFeaturesTable.js +14 -0
- package/lib/feature-descriptor/feature-details/FeatureDistributionChart.js +190 -0
- package/lib/feature-descriptor/feature-details/FeatureStatisticsTable.js +36 -0
- package/lib/feature-descriptor/feature-details/index.js +3 -0
- package/lib/feature-descriptor/feature-explanation/FeatureExplanation.js +40 -0
- package/lib/feature-descriptor/feature-explanation/components/ColoredExplanationBlock.js +28 -0
- package/lib/feature-descriptor/feature-explanation/components/ColumnExplanationBlock.js +4 -0
- package/lib/feature-descriptor/feature-explanation/components/DataSlotExplanationBlock.js +4 -0
- package/lib/feature-descriptor/feature-explanation/components/PetExplanationBlock.js +3 -0
- package/lib/feature-descriptor/feature-explanation/components/TextExplanationBlock.js +2 -0
- package/lib/feature-descriptor/feature-explanation/components/TextWithDataSlotContextExplanationBlock.js +2 -0
- package/lib/feature-descriptor/feature-explanation/components/TopicExplanationBlock.js +2 -0
- package/lib/feature-descriptor/feature-explanation/components/UnknownExplanationBlock.js +2 -0
- package/lib/feature-descriptors-domain/exploration-path/exploration-path-header.js +13 -0
- package/lib/feature-descriptors-domain/exploration-path/exploration-path-join-list.js +8 -0
- package/lib/feature-descriptors-domain/exploration-path/index.js +2 -0
- package/lib/feature-descriptors-domain/grouped-domains-descriptions-list.js +47 -0
- package/lib/index.js +2 -15
- package/lib/models/column/column.js +1 -0
- package/lib/models/column/index.js +1 -0
- package/lib/models/feature/feature-histogram.js +16 -0
- package/lib/models/feature/feature-leaderboard.js +1 -0
- package/lib/models/feature/feature.js +12 -0
- package/lib/models/feature/index.js +2 -0
- package/lib/models/feature-descriptors-domain/fd-domain-description.js +1 -0
- package/lib/models/feature-descriptors-domain/fd-grouped-domain-descriptions.js +1 -0
- package/lib/models/feature-descriptors-domain/index.js +2 -0
- package/lib/models/feature-explanation/feature-explanation.model.js +26 -0
- package/lib/models/feature-explanation/index.js +1 -0
- package/lib/models/feature-leaderboard/feature-leaderboard.js +1 -0
- package/lib/models/feature-leaderboard/index.js +1 -0
- package/lib/models/feature-space/feature-space.js +1 -0
- package/lib/models/feature-space/index.js +1 -0
- package/lib/models/index.js +1 -0
- package/lib/plugin.js +7 -29
- package/lib/utils/asserations.js +5 -0
- package/lib/utils/index.js +3 -0
- package/lib/utils/localize.js +14 -0
- package/lib/utils/object/extract-property.js +6 -0
- package/lib/utils/object/index.js +2 -0
- package/lib/utils/object/is-set.js +6 -0
- package/lib/version.js +2 -6
- package/lib/widgets/FeatureLeaderboardWidget.js +63 -0
- package/lib/widgets/FeatureSpaceWidget.js +50 -0
- package/lib/widgets/feature-leaderboard/FeatureLeaderboardEntries.js +10 -0
- package/lib/widgets/feature-leaderboard/FeatureLeaderboardOverview.js +20 -0
- package/lib/widgets/feature-leaderboard/FeatureLeaderboardView.js +19 -0
- package/lib/widgets/feature-leaderboard/entry-item/FeatureLeaderboardEntryDetails.js +15 -0
- package/lib/widgets/feature-leaderboard/entry-item/FeatureLeaderboardEntryItem.js +20 -0
- package/lib/widgets/feature-space/FeatureExplorationPaths.js +37 -0
- package/lib/widgets/feature-space/FeatureSpaceDomainsDescriptions.js +53 -0
- package/lib/widgets/feature-space/FeatureSpaceView.js +9 -0
- package/lib/widgets/index.js +4 -0
- package/package.json +60 -37
package/lib/plugin.js
CHANGED
|
@@ -1,50 +1,28 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// Copyright (c) dotdata
|
|
3
2
|
// Distributed under the terms of the Modified BSD License.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}) : (function(o, m, k, k2) {
|
|
8
|
-
if (k2 === undefined) k2 = k;
|
|
9
|
-
o[k2] = m[k];
|
|
10
|
-
}));
|
|
11
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
12
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
13
|
-
}) : function(o, v) {
|
|
14
|
-
o["default"] = v;
|
|
15
|
-
});
|
|
16
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
17
|
-
if (mod && mod.__esModule) return mod;
|
|
18
|
-
var result = {};
|
|
19
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
20
|
-
__setModuleDefault(result, mod);
|
|
21
|
-
return result;
|
|
22
|
-
};
|
|
23
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
const base_1 = require("@jupyter-widgets/base");
|
|
25
|
-
const widgetExports = __importStar(require("./widget"));
|
|
26
|
-
const version_1 = require("./version");
|
|
3
|
+
import { IJupyterWidgetRegistry } from '@jupyter-widgets/base';
|
|
4
|
+
import * as widgetExports from './widgets';
|
|
5
|
+
import { MODULE_NAME, MODULE_VERSION } from './version';
|
|
27
6
|
const EXTENSION_ID = 'dotdata_widgets:plugin';
|
|
28
7
|
/**
|
|
29
8
|
* The example plugin.
|
|
30
9
|
*/
|
|
31
10
|
const examplePlugin = {
|
|
32
11
|
id: EXTENSION_ID,
|
|
33
|
-
requires: [
|
|
12
|
+
requires: [IJupyterWidgetRegistry],
|
|
34
13
|
activate: activateWidgetExtension,
|
|
35
14
|
autoStart: true,
|
|
36
15
|
};
|
|
37
16
|
// the "as unknown as ..." typecast above is solely to support JupyterLab 1
|
|
38
17
|
// and 2 in the same codebase and should be removed when we migrate to Lumino.
|
|
39
|
-
|
|
18
|
+
export default examplePlugin;
|
|
40
19
|
/**
|
|
41
20
|
* Activate the widget extension.
|
|
42
21
|
*/
|
|
43
22
|
function activateWidgetExtension(app, registry) {
|
|
44
23
|
registry.registerWidget({
|
|
45
|
-
name:
|
|
46
|
-
version:
|
|
24
|
+
name: MODULE_NAME,
|
|
25
|
+
version: MODULE_VERSION,
|
|
47
26
|
exports: widgetExports,
|
|
48
27
|
});
|
|
49
28
|
}
|
|
50
|
-
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { isSet } from './object';
|
|
2
|
+
const numberDefaultFormatter = new Intl.NumberFormat(navigator.language, {
|
|
3
|
+
maximumFractionDigits: 3,
|
|
4
|
+
useGrouping: false,
|
|
5
|
+
});
|
|
6
|
+
export var Localize;
|
|
7
|
+
(function (Localize) {
|
|
8
|
+
function formatNumber(value, unsetSymbol) {
|
|
9
|
+
return isSet(value)
|
|
10
|
+
? numberDefaultFormatter.format(value)
|
|
11
|
+
: unsetSymbol ?? '';
|
|
12
|
+
}
|
|
13
|
+
Localize.formatNumber = formatNumber;
|
|
14
|
+
})(Localize || (Localize = {}));
|
package/lib/version.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// Copyright (c) dotdata
|
|
3
2
|
// Distributed under the terms of the Modified BSD License.
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.MODULE_NAME = exports.MODULE_VERSION = void 0;
|
|
6
3
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
7
4
|
// @ts-ignore
|
|
8
5
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
@@ -13,9 +10,8 @@ const data = require('../package.json');
|
|
|
13
10
|
* The html widget manager assumes that this is the same as the npm package
|
|
14
11
|
* version number.
|
|
15
12
|
*/
|
|
16
|
-
|
|
13
|
+
export const MODULE_VERSION = data.version;
|
|
17
14
|
/*
|
|
18
15
|
* The current package name.
|
|
19
16
|
*/
|
|
20
|
-
|
|
21
|
-
//# sourceMappingURL=version.js.map
|
|
17
|
+
export const MODULE_NAME = data.name;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) dotdata
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { ReactWidget, UseSignal } from '@jupyterlab/apputils';
|
|
5
|
+
import { DOMWidgetModel, DOMWidgetView, } from '@jupyter-widgets/base';
|
|
6
|
+
import { Signal } from '@lumino/signaling';
|
|
7
|
+
import { MODULE_NAME, MODULE_VERSION } from '../version';
|
|
8
|
+
import { FeatureLeaderboardView } from './feature-leaderboard/FeatureLeaderboardView';
|
|
9
|
+
export class FeatureLeaderboardWidgetModel extends DOMWidgetModel {
|
|
10
|
+
defaults() {
|
|
11
|
+
return {
|
|
12
|
+
...super.defaults(),
|
|
13
|
+
_model_name: FeatureLeaderboardWidgetModel.model_name,
|
|
14
|
+
_model_module: FeatureLeaderboardWidgetModel.model_module,
|
|
15
|
+
_model_module_version: FeatureLeaderboardWidgetModel.model_module_version,
|
|
16
|
+
_view_name: FeatureLeaderboardWidgetModel.view_name,
|
|
17
|
+
_view_module: FeatureLeaderboardWidgetModel.view_module,
|
|
18
|
+
_view_module_version: FeatureLeaderboardWidgetModel.view_module_version,
|
|
19
|
+
value: { allEntries: [] },
|
|
20
|
+
confidence: 0.95,
|
|
21
|
+
max_collinearity: 0.95,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
FeatureLeaderboardWidgetModel.serializers = {
|
|
26
|
+
...DOMWidgetModel.serializers,
|
|
27
|
+
};
|
|
28
|
+
FeatureLeaderboardWidgetModel.model_name = 'FeatureLeaderboardWidgetModel';
|
|
29
|
+
FeatureLeaderboardWidgetModel.model_module = MODULE_NAME;
|
|
30
|
+
FeatureLeaderboardWidgetModel.model_module_version = MODULE_VERSION;
|
|
31
|
+
FeatureLeaderboardWidgetModel.view_name = 'FeatureLeaderboardWidgetView'; // Set to null if no view
|
|
32
|
+
FeatureLeaderboardWidgetModel.view_module = MODULE_NAME; // Set to null if no view
|
|
33
|
+
FeatureLeaderboardWidgetModel.view_module_version = MODULE_VERSION;
|
|
34
|
+
export class FeatureLeaderboardWidgetView extends DOMWidgetView {
|
|
35
|
+
constructor() {
|
|
36
|
+
super(...arguments);
|
|
37
|
+
this.signal = new Signal(this);
|
|
38
|
+
this.luminoWidget = ReactWidget.create(React.createElement("div", { className: "dotdata-widget" },
|
|
39
|
+
React.createElement(UseSignal, { signal: this.signal }, (_, signalData) => signalData?.value ? (React.createElement(FeatureLeaderboardView, { featureLeaderboard: signalData.value, maxCollinearity: signalData.max_collinearity, confidence: signalData.confidence, setConfidence: this.onValueChange('confidence'), setMaxCollinearity: this.onValueChange('max_collinearity') })) : null)));
|
|
40
|
+
}
|
|
41
|
+
render() {
|
|
42
|
+
this.model.on('change:confidence', this.onModelChange, this);
|
|
43
|
+
this.model.on('change:max_collinearity', this.onModelChange, this);
|
|
44
|
+
this.model.on('change:value', this.onModelChange, this);
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
this.onModelChange();
|
|
47
|
+
}, 1000);
|
|
48
|
+
}
|
|
49
|
+
onModelChange() {
|
|
50
|
+
const { value, confidence, max_collinearity } = this.model.get_state(false);
|
|
51
|
+
this.signal.emit({
|
|
52
|
+
value,
|
|
53
|
+
confidence,
|
|
54
|
+
max_collinearity,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
onValueChange(propName) {
|
|
58
|
+
return (value) => {
|
|
59
|
+
this.model.set(propName, value);
|
|
60
|
+
this.model.save_changes();
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright (c) dotdata
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { ReactWidget, UseSignal } from '@jupyterlab/apputils';
|
|
5
|
+
import { DOMWidgetModel, DOMWidgetView, } from '@jupyter-widgets/base';
|
|
6
|
+
import { Signal } from '@lumino/signaling';
|
|
7
|
+
import { MODULE_NAME, MODULE_VERSION } from '../version';
|
|
8
|
+
import { FeatureSpaceView } from './feature-space/FeatureSpaceView';
|
|
9
|
+
export class FeatureSpaceWidgetModel extends DOMWidgetModel {
|
|
10
|
+
defaults() {
|
|
11
|
+
return {
|
|
12
|
+
...super.defaults(),
|
|
13
|
+
_model_name: FeatureSpaceWidgetModel.model_name,
|
|
14
|
+
_model_module: FeatureSpaceWidgetModel.model_module,
|
|
15
|
+
_model_module_version: FeatureSpaceWidgetModel.model_module_version,
|
|
16
|
+
_view_name: FeatureSpaceWidgetModel.view_name,
|
|
17
|
+
_view_module: FeatureSpaceWidgetModel.view_module,
|
|
18
|
+
_view_module_version: FeatureSpaceWidgetModel.view_module_version,
|
|
19
|
+
value: undefined,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
FeatureSpaceWidgetModel.serializers = {
|
|
24
|
+
...DOMWidgetModel.serializers,
|
|
25
|
+
};
|
|
26
|
+
FeatureSpaceWidgetModel.model_name = 'FeatureSpaceWidgetModel';
|
|
27
|
+
FeatureSpaceWidgetModel.model_module = MODULE_NAME;
|
|
28
|
+
FeatureSpaceWidgetModel.model_module_version = MODULE_VERSION;
|
|
29
|
+
FeatureSpaceWidgetModel.view_name = 'FeatureSpaceWidgetView'; // Set to null if no view
|
|
30
|
+
FeatureSpaceWidgetModel.view_module = MODULE_NAME; // Set to null if no view
|
|
31
|
+
FeatureSpaceWidgetModel.view_module_version = MODULE_VERSION;
|
|
32
|
+
export class FeatureSpaceWidgetView extends DOMWidgetView {
|
|
33
|
+
constructor() {
|
|
34
|
+
super(...arguments);
|
|
35
|
+
this.signal = new Signal(this);
|
|
36
|
+
this.luminoWidget = ReactWidget.create(React.createElement("div", { className: "dotdata-widget" },
|
|
37
|
+
React.createElement(UseSignal, { signal: this.signal }, (_, signalData) => signalData?.value ? (React.createElement(FeatureSpaceView, { featureSpace: signalData?.value })) : null)));
|
|
38
|
+
}
|
|
39
|
+
render() {
|
|
40
|
+
this.model.on('change:value', this.onModelChange, this);
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
this.onModelChange();
|
|
43
|
+
}, 1000);
|
|
44
|
+
}
|
|
45
|
+
onModelChange() {
|
|
46
|
+
this.signal.emit({
|
|
47
|
+
value: this.model.get('value'),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Accordion, AccordionHeader, AccordionDetails, } from '../../components/accordion';
|
|
3
|
+
import { FeatureExplanation } from '../../feature-descriptor/feature-explanation/FeatureExplanation';
|
|
4
|
+
import { FeatureLeaderboardEntryItem } from './entry-item/FeatureLeaderboardEntryItem';
|
|
5
|
+
export const FeatureLeaderboardEntries = ({ entriesGroups }) => {
|
|
6
|
+
return (React.createElement(React.Fragment, null, entriesGroups.map((entriesGroup, groupIdx) => (React.createElement(Accordion, { key: groupIdx, collapsedDetailsStyle: { padding: '0' }, expandedDetailsStyle: { padding: '0' }, expandedHeaderStyle: { background: '#F0F0F0' }, initialState: true },
|
|
7
|
+
React.createElement(AccordionHeader, null,
|
|
8
|
+
React.createElement(FeatureExplanation, { explanationBlocks: entriesGroup[0].feature.explanation.tokens })),
|
|
9
|
+
React.createElement(AccordionDetails, null, entriesGroup.map(entry => (React.createElement(FeatureLeaderboardEntryItem, { key: entry.feature.id, featureEntry: entry })))))))));
|
|
10
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Input } from '../../components/input';
|
|
3
|
+
const sliderRowStyle = {
|
|
4
|
+
display: 'flex',
|
|
5
|
+
alignItems: 'center',
|
|
6
|
+
gap: '6px',
|
|
7
|
+
};
|
|
8
|
+
const maxCollinearityTooltip = 'Maximum correlation of any two features on the list';
|
|
9
|
+
const confidenceTooltip = 'The probability that a feature is better than a random feature';
|
|
10
|
+
export const FeatureLeaderboardOverview = ({ confidence, setConfidence, maxCollinearity, setMaxCollinearity }) => {
|
|
11
|
+
return (React.createElement("div", { style: { display: 'flex', gap: '40px', flexWrap: 'wrap' } },
|
|
12
|
+
React.createElement("label", { style: sliderRowStyle, htmlFor: "maxCollinearitySlider" },
|
|
13
|
+
React.createElement("span", { className: "grey-label label-bold", title: maxCollinearityTooltip }, "Max collinearity:"),
|
|
14
|
+
React.createElement(Input, { id: "maxCollinearitySlider", type: "range", min: 0.0, max: 1.0, step: 0.01, list: "sliderEdgeValues", value: maxCollinearity, onValueChange: v => setMaxCollinearity(Number(v)) }),
|
|
15
|
+
React.createElement(Input, { inputSize: "small", type: "number", min: 0.0, max: 1.0, step: 0.01, value: maxCollinearity, onValueChange: v => setMaxCollinearity(Number(v)) })),
|
|
16
|
+
React.createElement("label", { style: sliderRowStyle, htmlFor: "confidenceSlider" },
|
|
17
|
+
React.createElement("span", { className: "grey-label label-bold", title: confidenceTooltip }, "Confidence:"),
|
|
18
|
+
React.createElement(Input, { id: "confidenceSlider", type: "range", min: 0.0, max: 1.0, step: 0.01, list: "sliderEdgeValues", value: confidence, onValueChange: v => setConfidence(Number(v)) }),
|
|
19
|
+
React.createElement(Input, { inputSize: "small", type: "number", min: 0.0, max: 1.0, step: 0.01, value: confidence, onValueChange: v => setConfidence(Number(v)) }))));
|
|
20
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FeatureLeaderboardOverview } from './FeatureLeaderboardOverview';
|
|
3
|
+
import { FeatureLeaderboardEntryItem } from './entry-item/FeatureLeaderboardEntryItem';
|
|
4
|
+
export const FeatureLeaderboardView = ({ featureLeaderboard, setConfidence, confidence, maxCollinearity, setMaxCollinearity, }) => {
|
|
5
|
+
const featureEntries = React.useMemo(() => filterFeatures(featureLeaderboard, maxCollinearity, confidence), [maxCollinearity, confidence, featureLeaderboard]);
|
|
6
|
+
return (React.createElement(React.Fragment, null,
|
|
7
|
+
React.createElement("h2", { className: "grey-label" }, "Feature Pipeline Overview:"),
|
|
8
|
+
React.createElement(FeatureLeaderboardOverview, { confidence: confidence, setConfidence: setConfidence, maxCollinearity: maxCollinearity, setMaxCollinearity: setMaxCollinearity }),
|
|
9
|
+
React.createElement("br", null),
|
|
10
|
+
featureEntries.map(featureEntry => (React.createElement(FeatureLeaderboardEntryItem, { key: featureEntry.feature.id, featureEntry: featureEntry })))));
|
|
11
|
+
};
|
|
12
|
+
function filterFeatures(featureLeaderboard, maxCollinearity, confidence) {
|
|
13
|
+
const fulfillCollinearity = (entry) => entry.maxAbsCorrelationOfSimplerFeature < maxCollinearity;
|
|
14
|
+
const fulfillNoise = (entry) => entry.signalConfidence >= confidence;
|
|
15
|
+
return featureLeaderboard.allEntries
|
|
16
|
+
.flat()
|
|
17
|
+
.filter(fulfillCollinearity)
|
|
18
|
+
.filter(fulfillNoise);
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FeatureStatisticsTable, FeatureDistributionChart, FeatureCorrelatedFeaturesTable, } from '../../../feature-descriptor/feature-details';
|
|
3
|
+
export const FeatureLeaderboardEntryDetails = ({ entry }) => {
|
|
4
|
+
return (React.createElement("div", null,
|
|
5
|
+
React.createElement("div", { style: { display: 'flex', gap: '50px' } },
|
|
6
|
+
React.createElement("div", { className: "feature-metrics", style: { flex: 3 } },
|
|
7
|
+
React.createElement("h3", { className: "grey-label" }, "Feature Statistics:"),
|
|
8
|
+
React.createElement(FeatureStatisticsTable, { statistics: entry.stats })),
|
|
9
|
+
React.createElement("div", { className: "feature-histogram", style: { flex: 1 } },
|
|
10
|
+
React.createElement("h3", { className: "grey-label" }, "Feature Distribution:"),
|
|
11
|
+
React.createElement(FeatureDistributionChart, { histogram: entry.histogram }))),
|
|
12
|
+
React.createElement("div", { className: "correlated-features" },
|
|
13
|
+
React.createElement("h3", { className: "grey-label" }, "Correlated Features:"),
|
|
14
|
+
React.createElement(FeatureCorrelatedFeaturesTable, { correlatedFeatures: entry.topCorrelatedFeatures }))));
|
|
15
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Accordion, AccordionHeader, AccordionDetails, } from '../../../components/accordion';
|
|
3
|
+
import { FeatureExplanation } from '../../../feature-descriptor/feature-explanation/FeatureExplanation';
|
|
4
|
+
import { FeatureLeaderboardEntryDetails } from './FeatureLeaderboardEntryDetails';
|
|
5
|
+
const featureNameLabelStyle = {
|
|
6
|
+
color: 'var(--c-grey-600)',
|
|
7
|
+
display: 'inline-block',
|
|
8
|
+
minWidth: '5rem',
|
|
9
|
+
};
|
|
10
|
+
export const FeatureLeaderboardEntryItem = ({ featureEntry }) => {
|
|
11
|
+
return (React.createElement(Accordion, { expandedDetailsStyle: {
|
|
12
|
+
borderBottom: '1px solid var(--c-grey-500)',
|
|
13
|
+
paddingBlockEnd: '30px',
|
|
14
|
+
} },
|
|
15
|
+
React.createElement(AccordionHeader, null,
|
|
16
|
+
React.createElement("span", { className: "label-bold", style: featureNameLabelStyle }, featureEntry.feature.id),
|
|
17
|
+
React.createElement(FeatureExplanation, { key: featureEntry.feature.id, explanationBlocks: featureEntry.feature.explanation.tokens })),
|
|
18
|
+
React.createElement(AccordionDetails, null,
|
|
19
|
+
React.createElement(FeatureLeaderboardEntryDetails, { entry: featureEntry }))));
|
|
20
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
const FeatureExplorationPathItem = props => {
|
|
3
|
+
return (React.createElement("div", null,
|
|
4
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'baseline' } },
|
|
5
|
+
React.createElement("h3", { className: "grey-label", style: { minWidth: '185px' } },
|
|
6
|
+
"Exploration Path [#",
|
|
7
|
+
props.explorationPathIndex,
|
|
8
|
+
"]"),
|
|
9
|
+
React.createElement("div", null,
|
|
10
|
+
props.explorationPath.targetTable,
|
|
11
|
+
"[",
|
|
12
|
+
React.createElement("span", { style: {
|
|
13
|
+
color: 'var(--c-blue-700)',
|
|
14
|
+
fontWeight: '500',
|
|
15
|
+
} }, props.explorationPath.targetColumns.join(', ')),
|
|
16
|
+
"] - ",
|
|
17
|
+
props.explorationPath.sourceTable,
|
|
18
|
+
"[",
|
|
19
|
+
React.createElement("span", { style: {
|
|
20
|
+
color: 'var(--c-blue-700)',
|
|
21
|
+
fontWeight: '500',
|
|
22
|
+
} }, props.explorationPath.sourceColumns.join(', ')),
|
|
23
|
+
"]")),
|
|
24
|
+
React.createElement("div", { style: { paddingLeft: '16px' } },
|
|
25
|
+
React.createElement("p", { className: "grey-label" }, "Joins:"),
|
|
26
|
+
props.explorationPath.joins.map(join => (React.createElement("div", { key: join.joinId },
|
|
27
|
+
"[",
|
|
28
|
+
join.joinId,
|
|
29
|
+
"] ",
|
|
30
|
+
join.description,
|
|
31
|
+
" (",
|
|
32
|
+
join.numFeatures,
|
|
33
|
+
" features)"))))));
|
|
34
|
+
};
|
|
35
|
+
export const FeatureExplorationPaths = props => {
|
|
36
|
+
return (React.createElement(React.Fragment, null, props.explorationPaths.map((explorationPath, idx) => (React.createElement(FeatureExplorationPathItem, { key: idx, explorationPathIndex: idx, explorationPath: explorationPath })))));
|
|
37
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Accordion, AccordionDetails, AccordionHeader, } from '../../components/accordion';
|
|
3
|
+
import { Input } from '../../components/input';
|
|
4
|
+
import { GroupedDomainsDescriptionsList } from '../../feature-descriptors-domain/grouped-domains-descriptions-list';
|
|
5
|
+
const searchInputStyle = {
|
|
6
|
+
width: '70%',
|
|
7
|
+
marginTop: '4px',
|
|
8
|
+
marginBottom: '16px',
|
|
9
|
+
};
|
|
10
|
+
export const FeatureSpaceDomainsDescriptions = props => {
|
|
11
|
+
const [aggregationSearch, setAggregationSearch] = useState(() => '');
|
|
12
|
+
const [filterSearch, setFilterSearch] = useState(() => '');
|
|
13
|
+
const [searchedAggregation, setSearchedAggregation] = useState(() => props.aggregations);
|
|
14
|
+
const [searchedFilters, setSearchedFilters] = useState(() => props.filters);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const aggregations = filterDomainDescriptions(props.aggregations, aggregationSearch);
|
|
17
|
+
setSearchedAggregation(aggregations);
|
|
18
|
+
}, [aggregationSearch]);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const filters = filterDomainDescriptions(props.filters, filterSearch);
|
|
21
|
+
setSearchedFilters(filters);
|
|
22
|
+
}, [filterSearch]);
|
|
23
|
+
return (React.createElement("div", null,
|
|
24
|
+
React.createElement(Accordion, null,
|
|
25
|
+
React.createElement(AccordionHeader, null,
|
|
26
|
+
React.createElement("h3", { className: "grey-label" }, "Filters and Aggregations")),
|
|
27
|
+
React.createElement(AccordionDetails, null,
|
|
28
|
+
React.createElement("div", { style: { display: 'flex', marginBottom: '0.5rem' } },
|
|
29
|
+
React.createElement("div", { style: { width: '50%' } },
|
|
30
|
+
React.createElement("div", { className: "grey-label" }, "Filters"),
|
|
31
|
+
React.createElement(Input, { style: searchInputStyle, value: filterSearch, placeholder: "Search:", onValueChange: setFilterSearch }),
|
|
32
|
+
React.createElement(GroupedDomainsDescriptionsList, { groupedDomain: searchedFilters })),
|
|
33
|
+
React.createElement("div", { style: { width: '50%' } },
|
|
34
|
+
React.createElement("div", { className: "grey-label" }, "Aggregations"),
|
|
35
|
+
React.createElement(Input, { style: searchInputStyle, value: aggregationSearch, placeholder: "Search:", onValueChange: setAggregationSearch }),
|
|
36
|
+
React.createElement(GroupedDomainsDescriptionsList, { groupedDomain: searchedAggregation })))))));
|
|
37
|
+
};
|
|
38
|
+
const isNotEmpty = (arr) => arr.length > 0;
|
|
39
|
+
function filterDomainDescriptions(domains, searchPhrase) {
|
|
40
|
+
return {
|
|
41
|
+
types: domains.types
|
|
42
|
+
.map(({ summary, columns }) => ({
|
|
43
|
+
summary,
|
|
44
|
+
columns: columns
|
|
45
|
+
.map(column => ({
|
|
46
|
+
summary: column.summary,
|
|
47
|
+
descriptions: column.descriptions.filter(({ description }) => description.toLowerCase().includes(searchPhrase.toLowerCase())),
|
|
48
|
+
}))
|
|
49
|
+
.filter(({ descriptions }) => isNotEmpty(descriptions)),
|
|
50
|
+
}))
|
|
51
|
+
.filter(({ columns }) => isNotEmpty(columns)),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FeatureSpaceDomainsDescriptions } from './FeatureSpaceDomainsDescriptions';
|
|
3
|
+
import { FeatureExplorationPaths } from './FeatureExplorationPaths';
|
|
4
|
+
export const FeatureSpaceView = props => {
|
|
5
|
+
return (React.createElement(React.Fragment, null,
|
|
6
|
+
React.createElement("h2", { className: "grey-label" }, "Feature Space Overview:"),
|
|
7
|
+
props.featureSpace.explorationPaths ? (React.createElement(FeatureExplorationPaths, { explorationPaths: props.featureSpace.explorationPaths })) : null,
|
|
8
|
+
props.featureSpace.filters ? (React.createElement(FeatureSpaceDomainsDescriptions, { filters: props.featureSpace.filters, aggregations: props.featureSpace.aggregations })) : null));
|
|
9
|
+
};
|
package/package.json
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotdata_widgets",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "A dotdata widget",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"dotdata",
|
|
7
|
+
"widgets",
|
|
6
8
|
"jupyter",
|
|
7
9
|
"jupyterlab",
|
|
8
|
-
"jupyterlab-extension"
|
|
9
|
-
"widgets"
|
|
10
|
+
"jupyterlab-extension"
|
|
10
11
|
],
|
|
11
12
|
"files": [
|
|
12
13
|
"lib/**/*.js",
|
|
13
14
|
"dist/*.js",
|
|
14
15
|
"css/*.css"
|
|
15
16
|
],
|
|
16
|
-
"homepage": "https://github.com/dotdata
|
|
17
|
+
"homepage": "https://github.com/ramencloud/dotdata-core",
|
|
17
18
|
"bugs": {
|
|
18
|
-
"url": "https://github.com/dotdata/
|
|
19
|
+
"url": "https://github.com/ramencloud/dotdata-core/issues"
|
|
19
20
|
},
|
|
20
21
|
"license": "BSD-3-Clause",
|
|
21
22
|
"author": {
|
|
@@ -26,14 +27,14 @@
|
|
|
26
27
|
"types": "./lib/index.d.ts",
|
|
27
28
|
"repository": {
|
|
28
29
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/dotdata
|
|
30
|
+
"url": "https://github.com/ramencloud/dotdata-core"
|
|
30
31
|
},
|
|
31
32
|
"scripts": {
|
|
32
33
|
"build": "yarn run build:lib && yarn run build:nbextension && yarn run build:labextension:dev",
|
|
33
34
|
"build:prod": "yarn run build:lib && yarn run build:nbextension && yarn run build:labextension",
|
|
34
35
|
"build:labextension": "jupyter labextension build .",
|
|
35
36
|
"build:labextension:dev": "jupyter labextension build --development True .",
|
|
36
|
-
"build:lib": "tsc",
|
|
37
|
+
"build:lib": "tsc && tsc-alias",
|
|
37
38
|
"build:nbextension": "webpack",
|
|
38
39
|
"clean": "yarn run clean:lib && yarn run clean:nbextension && yarn run clean:labextension",
|
|
39
40
|
"clean:lib": "rimraf lib",
|
|
@@ -44,43 +45,65 @@
|
|
|
44
45
|
"prepack": "yarn run build:lib",
|
|
45
46
|
"test": "jest",
|
|
46
47
|
"watch": "npm-run-all -p watch:*",
|
|
47
|
-
"watch:lib": "tsc -w",
|
|
48
|
+
"watch:lib": "concurrently \"tsc -w\" \"tsc-alias -w\"",
|
|
48
49
|
"watch:nbextension": "webpack --watch --mode=development",
|
|
49
50
|
"watch:labextension": "jupyter labextension watch ."
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
52
|
-
"@
|
|
53
|
+
"@fontsource/roboto": "^4.5.8",
|
|
54
|
+
"@jupyter-widgets/base": "^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6",
|
|
55
|
+
"@jupyterlab/application": "^3.5.2",
|
|
56
|
+
"react": "18.2.0",
|
|
57
|
+
"react-dom": "18.2.0",
|
|
58
|
+
"vega": "^5.22.1"
|
|
53
59
|
},
|
|
54
60
|
"devDependencies": {
|
|
55
|
-
"@babel/core": "^7.
|
|
56
|
-
"@babel/preset-env": "^7.
|
|
57
|
-
"@
|
|
58
|
-
"@
|
|
59
|
-
"@
|
|
60
|
-
"@
|
|
61
|
-
"@
|
|
62
|
-
"@
|
|
63
|
-
"@
|
|
64
|
-
"@
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"eslint": "^
|
|
68
|
-
"eslint
|
|
69
|
-
"
|
|
70
|
-
"
|
|
61
|
+
"@babel/core": "^7.20.12",
|
|
62
|
+
"@babel/preset-env": "^7.20.2",
|
|
63
|
+
"@babel/preset-react": "^7.18.6",
|
|
64
|
+
"@babel/preset-typescript": "^7.18.6",
|
|
65
|
+
"@jupyter-widgets/base-manager": "^1.0.3",
|
|
66
|
+
"@jupyterlab/builder": "^3.0.9",
|
|
67
|
+
"@lumino/application": "^1.31.3",
|
|
68
|
+
"@lumino/widgets": "^1.37.1",
|
|
69
|
+
"@types/jest": "^26.0.24",
|
|
70
|
+
"@types/react": "^18.0.27",
|
|
71
|
+
"@types/react-dom": "18.0.10",
|
|
72
|
+
"@types/webpack-env": "^1.18.0",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "^3.10.1",
|
|
74
|
+
"@typescript-eslint/parser": "^3.10.1",
|
|
75
|
+
"acorn": "^7.4.1",
|
|
76
|
+
"babel-loader": "^9.1.2",
|
|
77
|
+
"concurrently": "^7.6.0",
|
|
78
|
+
"css-loader": "^3.6.0",
|
|
79
|
+
"eslint": "^7.32.0",
|
|
80
|
+
"eslint-config-prettier": "^6.15.0",
|
|
81
|
+
"eslint-plugin-prettier": "^3.4.1",
|
|
82
|
+
"file-loader": "^6.2.0",
|
|
83
|
+
"fs-extra": "^7.0.1",
|
|
71
84
|
"identity-obj-proxy": "^3.0.0",
|
|
72
|
-
"jest": "^26.
|
|
73
|
-
"mkdirp": "^0.5.
|
|
74
|
-
"npm-run-all": "^4.1.
|
|
75
|
-
"prettier": "^2.
|
|
76
|
-
"rimraf": "^2.6.
|
|
85
|
+
"jest": "^26.6.3",
|
|
86
|
+
"mkdirp": "^0.5.6",
|
|
87
|
+
"npm-run-all": "^4.1.5",
|
|
88
|
+
"prettier": "^2.8.4",
|
|
89
|
+
"rimraf": "^2.6.3",
|
|
77
90
|
"source-map-loader": "^1.1.3",
|
|
78
|
-
"style-loader": "^1.
|
|
79
|
-
"ts-jest": "^26.
|
|
80
|
-
"ts-loader": "^8.
|
|
81
|
-
"
|
|
82
|
-
"webpack": "^
|
|
83
|
-
"
|
|
91
|
+
"style-loader": "^1.3.0",
|
|
92
|
+
"ts-jest": "^26.5.6",
|
|
93
|
+
"ts-loader": "^8.4.0",
|
|
94
|
+
"tsc-alias": "^1.8.2",
|
|
95
|
+
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
|
96
|
+
"typescript": "~4.9.5",
|
|
97
|
+
"url-loader": "^4.1.1",
|
|
98
|
+
"webpack": "^5.69.1",
|
|
99
|
+
"webpack-cli": "^4.10.0"
|
|
100
|
+
},
|
|
101
|
+
"babel": {
|
|
102
|
+
"presets": [
|
|
103
|
+
"@babel/preset-env",
|
|
104
|
+
"@babel/preset-react",
|
|
105
|
+
"@babel/preset-typescript"
|
|
106
|
+
]
|
|
84
107
|
},
|
|
85
108
|
"jupyterlab": {
|
|
86
109
|
"extension": "lib/plugin",
|