UNPKG

@webwriter/neural-network

Version:

Deep learning visualization for feed-forward networks with custom datasets, training and prediction.

437 lines (384 loc) 15.9 kB
import { LitElementWw } from '@webwriter/lit' import { CSSResult, TemplateResult, html, css, PropertyDeclarations, PropertyValues } from 'lit' import { customElement, property /* , query */, state } from 'lit/decorators.js' import { ContextRoot, provide } from '@lit/context' import '@shoelace-style/shoelace/dist/themes/light.css' import '@shoelace-style/shoelace/dist/themes/dark.css' import { globalStyles } from '@/global_styles' import { ConfigurationController } from '@/controllers/configuration_controller' import type { SetupStatus } from '@/types/setup_status' import { setupStatusContext } from '@/contexts/setup_status_context' import { SetupController } from '@/controllers/setup_controller' import { SetupUtils } from '@/utils/setup_utils' import { editableContext } from '@/contexts/editable_context' import type { Settings } from '@/types/settings' import { settingsContext } from '@/contexts/settings_context' import { SettingsController } from '@/controllers/settings_controller' import { SettingsUtils } from '@/utils/settings_utils' import type { QAndAEntry } from '@/types/q_and_a_entry' import { qAndAContext } from '@/contexts/q_and_a_context' import { QAndAController } from '@/controllers/q_and_a_controller' import { QAndAUtils } from '@/utils/q_and_a_utils' import type { CCanvas } from '@/components/canvas' import { canvasContext } from '@/contexts/canvas_context' import type { CLayerConf } from '@/types/c_layer_conf' import type { CLayerConnectionConf } from '@/types/c_layer_connection_conf' import { CNetwork } from '@/components/network/network' import { networkContext } from '@/contexts/network_context' import { layerConfsContext } from '@/contexts/layer_confs_context' import { layerConnectionConfsContext } from '@/contexts/layer_con_confs_context' import { NetworkController } from '@/controllers/network_controller' import type { DataSet } from '@/types/data_set' import { dataSetContext } from '@/contexts/data_set_context' import { availableDataSetsContext } from '@/contexts/available_data_sets_context' import { DataSetController } from '@/controllers/data_set_controller' import { DataSetUtils } from '@/utils/data_set_utils' import type { TrainOptions } from '@/types/train_options' import type { ModelConf } from '@/types/model_conf' import { trainOptionsContext } from '@/contexts/train_options_context' import { modelConfContext } from '@/contexts/model_conf_context' import { ModelController } from '@/controllers/model_controller' import { ModelUtils } from '@/utils/model_utils' import type { Selected } from '@/types/selected' import type { SelectedEle } from '@/types/selected_ele' import { selectedContext } from '@/contexts/selected_context' import { selectedEleContext } from '@/contexts/selected_ele_context' import { SelectionController } from '@/controllers/selection_controller' import { panelContext } from '@/contexts/panels_context' import { PanelController } from '@/controllers/panel_controller' /* import { AlertController } from '@/controllers/alert_controller' import { AlertUtils } from '@/utils/alert_utils'*/ import type { Theme } from '@/types/theme' import { themeContext } from '@/contexts/theme_context' import { ThemeController } from '@/controllers/theme_controller' import { ThemeUtils } from '@/utils/theme_utils' import { CCanvasArea } from '@/components/canvas_area' import { MenuArea } from '@/components/menu_area' import { ThemeSwitch } from './components/theme_switch' import { ContextProvider } from '@lit/context' import '@webcomponents/scoped-custom-element-registry'; export class NeuralNetwork extends LitElementWw { static properties: PropertyDeclarations = { setupStatus: { attribute: false }, editable: { attribute: true, type: Boolean, reflect: true }, settings: { attribute: true, type: Object, reflect: true }, qAndA: { attribute: true, type: Object, reflect: true }, canvas: {attribute: false}, network: {attribute: false}, layerConfs: { attribute: true, type: Array, reflect: true }, layerConnectionConfs: { attribute: true, type: Array, reflect: true }, dataSet: { attribute: true, type: Object, reflect: true }, availableDataSets: { attribute: true, type: Array, reflect: true }, trainOptions: { attribute: true, type: Object, reflect: true }, modelConf: { attribute: false }, selected: { attribute: false }, selectedEle: { attribute: false }, panel: { attribute: false }, theme: { attribute: false } } constructor() { super() this.setupStatusProvider = new ContextProvider(this, {context: setupStatusContext, initialValue: SetupUtils.defaultSetupStatus}) this.editableProvider = new ContextProvider(this, {context: editableContext, initialValue: false}) this.settingsProvider = new ContextProvider(this, {context: settingsContext, initialValue: JSON.parse(JSON.stringify(SettingsUtils.defaultSettings))}) this.qAndAProvider = new ContextProvider(this, {context: qAndAContext, initialValue: [...QAndAUtils.defaultQAndA]}) this.canvasProvider = new ContextProvider(this, {context: canvasContext}) this.networkProvider = new ContextProvider(this, {context: networkContext}) this.layerConfsProvider = new ContextProvider(this, {context: layerConfsContext, initialValue: []}) this.layerConnectionConfsProvider = new ContextProvider(this, {context: layerConnectionConfsContext, initialValue: []}) this.dataSetProvider = new ContextProvider(this, {context: dataSetContext, initialValue: DataSetUtils.defaultDataSet}) this.availableDataSetsProvider = new ContextProvider(this, {context: availableDataSetsContext, initialValue: DataSetUtils.defaultAvailableDataSets}) this.trainOptionsProvider = new ContextProvider(this, {context: trainOptionsContext, initialValue: <TrainOptions>(JSON.parse(JSON.stringify(ModelUtils.defaultTrainOptions)))}) this.modelConfProvider = new ContextProvider(this, {context: modelConfContext, initialValue: <ModelConf>(JSON.parse(JSON.stringify(ModelUtils.defaultModelConf)))}) this.selectedProvider = new ContextProvider(this, {context: selectedContext, initialValue: {}}) this.selectedEleProvider = new ContextProvider(this, {context: selectedEleContext}) this.panelProvider = new ContextProvider(this, {context: panelContext}) this.themeProvider = new ContextProvider(this, {context: themeContext, initialValue: ThemeUtils.lightTheme}) } setupStatusProvider: ContextProvider<any, NeuralNetwork> editableProvider: ContextProvider<any, NeuralNetwork> settingsProvider: ContextProvider<any, NeuralNetwork> qAndAProvider: ContextProvider<any, NeuralNetwork> canvasProvider: ContextProvider<any, NeuralNetwork> networkProvider: ContextProvider<any, NeuralNetwork> layerConfsProvider: ContextProvider<any, NeuralNetwork> layerConnectionConfsProvider: ContextProvider<any, NeuralNetwork> dataSetProvider: ContextProvider<any, NeuralNetwork> availableDataSetsProvider: ContextProvider<any, NeuralNetwork> trainOptionsProvider: ContextProvider<any, NeuralNetwork> modelConfProvider: ContextProvider<any, NeuralNetwork> selectedProvider: ContextProvider<any, NeuralNetwork> selectedEleProvider: ContextProvider<any, NeuralNetwork> panelProvider: ContextProvider<any, NeuralNetwork> themeProvider: ContextProvider<any, NeuralNetwork> connectedCallback(): void { super.connectedCallback() const root = new ContextRoot(); root.attach(document.body); } protected firstUpdated(_changedProperties: PropertyValues): void { super.firstUpdated(_changedProperties) setTimeout(() => { const dim: DOMRect = this.getBoundingClientRect() this.style.height = dim.height - 4 +"px" this.style.width = dim.width - 4 +"px" }); } static scopedElements = { "canvas-area": CCanvasArea, "menu-area": MenuArea, "c-network": CNetwork, "theme-switch": ThemeSwitch } // DATA PROVIDERS AND CONTROLLERS - - - - - - - - - - - - - - - - - - - - - - configurationController = new ConfigurationController(this) // -> SETUP STATUS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get setupStatus() { return this.setupStatusProvider.value } set setupStatus(value) { this.setupStatusProvider.setValue(value) this.requestUpdate("setupStatus") } setupController = new SetupController(this) // -> EDITABLE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get editable() { return this.editableProvider.value } set editable(value) { this.editableProvider.setValue(value) this.requestUpdate("editable") } // -> SETTINGS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get settings() { return this.settingsProvider.value } set settings(value) { this.settingsProvider.setValue(value) this.requestUpdate("settings") } settingsController = new SettingsController(this) // -> HELP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get qAndA() { return this.qAndAProvider.value } set qAndA(value) { this.qAndAProvider.setValue(value) this.requestUpdate("qAndA") } qAndAController = new QAndAController(this) // -> CANVAS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get canvas() { return this.canvasProvider.value } set canvas(value) { this.canvasProvider.setValue(value) this.requestUpdate("canvas") } // -> NETWORK - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get network() { return this.networkProvider.value } set network(value) { this.networkProvider.setValue(value) this.requestUpdate("network") } get layerConfs() { return this.layerConfsProvider.value } set layerConfs(value) { this.layerConfsProvider.setValue(value) this.requestUpdate("layerConfs") } get layerConnectionConfs() { return this.layerConnectionConfsProvider.value } set layerConnectionConfs(value) { this.layerConnectionConfsProvider.setValue(value) this.requestUpdate("layerConnectionConfs") } networkController = new NetworkController(this) // -> DATA SET - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get dataSet() { return this.dataSetProvider.value } set dataSet(value) { this.dataSetProvider.setValue(value) this.requestUpdate("dataSet") } get availableDataSets() { return this.availableDataSetsProvider.value } set availableDataSets(value) { this.availableDataSetsProvider.setValue(value) this.requestUpdate("availableDataSets") } dataSetController = new DataSetController(this) // -> MODEL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get trainOptions() { return this.trainOptionsProvider.value } set trainOptions(value) { this.trainOptionsProvider.setValue(value) this.requestUpdate("trainOptions") } get modelConf() { return this.modelConfProvider.value } set modelConf(value) { this.modelConfProvider.setValue(value) this.requestUpdate("modelConf") } trainMetricsContainer: HTMLDivElement modelController = new ModelController(this) // -> SELECTED - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get selected() { return this.selectedProvider.value } set selected(value) { this.selectedProvider.setValue(value) this.requestUpdate("selected") } get selectedEle() { return this.selectedEleProvider.value } set selectedEle(value) { this.selectedEleProvider.setValue(value) this.requestUpdate("selectedEle") } selectionController = new SelectionController(this) // -> PANELS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get panel() { return this.panelProvider.value } set panel(value) { this.panelProvider.setValue(value) this.requestUpdate("panel") } panelController = new PanelController(this) // -> THEME - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get theme() { return this.themeProvider.value } set theme(value) { this.themeProvider.setValue(value) this.requestUpdate("theme") } themeController = new ThemeController(this) // STYLES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static styles: CSSResult[] = [ globalStyles, css` :host { display: flex!important; flex-direction: row; overflow: hidden; background-color: var(--sl-color-neutral-0); height: 100%; } :host.embedded { /* min-height: 400px; height: 100%; */ display: flex!important; flex-direction: row; overflow: hidden; background-color: var(--sl-color-neutral-0); } #loadingPage { position: absolute; left: 0; top: 0; right: 0; bottom: 0; background-color: var(--sl-color-neutral-0); } #loadingDiv { position: absolute; left: 50%; top: 50%; -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; } canvas-area { width: calc(100% - 350px); height: 100%; } canvas-area.right-collapsed { width: 100%; } menu-area { width: 100%; } menu-area.right-collapsed { width: 0; } #divider { position: absolute; right: 350px; width: 2px; top: 10px; bottom: 10px; background-color: var(--sl-color-neutral-50); } theme-switch { position: absolute; bottom: 10px; left: 10px; } /* .sl-toast-stack { top: 300 !important; width: 50rem !important; } */ `, ] // RENDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -F render(): TemplateResult<1>[] { const renderedHTML: TemplateResult<1>[] = [] /* renderedHTML.push(html`<div class="sl-toast-stack"></div>`) */ renderedHTML.push( html`<style> ${(this.theme as any).styles} :host{ border-width: 2px; border-style: solid; border-radius: 5px; border-color: #6a6a6a; } </style>` ) renderedHTML.push(html` <canvas-area class="${!this.panel ? 'right-collapsed' : ''}" @click=${()=>{this.dispatchEvent(new Event("focus"))}} @canvas-created="${(e: CustomEvent<CCanvas>) => { this.canvas = e.detail }}" > </canvas-area>`) if ((this.setupStatus as any).loading) { renderedHTML.push(html` <div id="loadingPage"> <div id="loadingDiv"> <h1>Loading</h1> <sl-spinner style="font-size: 3rem;"></sl-spinner> </div> </div> `) } else { renderedHTML.push(html` <div id="divider" class="${!this.panel ? 'hidden' : ''}"></div> <menu-area class="${!this.panel ? 'right-collapsed' : ''}" @set-train-metrics-container="${(e: CustomEvent<HTMLDivElement>) => this.modelController.setTrainMetricsContainer(e.detail)}" ></menu-area> <c-network></c-network> `) } // renderedHTML.push(html`<theme-switch></theme-switch>`) return renderedHTML } } customElements.define("webwriter-neural-network", NeuralNetwork)