Lutz Roeder 10 месяцев назад
Родитель
Сommit
2e755a5915
2 измененных файлов с 97 добавлено и 57 удалено
  1. 96 57
      source/view.js
  2. 1 0
      test/worker.js

+ 96 - 57
source/view.js

@@ -4,7 +4,7 @@ import * as grapher from './grapher.js';
 
 const view = {};
 const markdown = {};
-const metrics = {};
+const metadata = {};
 
 view.View = class {
 
@@ -19,7 +19,6 @@ view.View = class {
         };
         this._options = { ...this._defaultOptions };
         this._model = null;
-        this._metrics = new metrics.Metrics();
         this._stack = [];
         this._selection = [];
         this._sidebar = new view.Sidebar(this._host);
@@ -288,10 +287,6 @@ view.View = class {
         return this._model;
     }
 
-    get metrics() {
-        return this._metrics;
-    }
-
     get options() {
         return this._options;
     }
@@ -721,8 +716,12 @@ view.View = class {
     }
 
     async attach(context) {
-        if (this._model && await this._metrics.open(context)) {
-            return true;
+        if (this._model) {
+            const attachment = new metadata.Attachment();
+            if (await attachment.open(context)) {
+                this._model.attachment = attachment;
+                return true;
+            }
         }
         return false;
     }
@@ -767,12 +766,16 @@ view.View = class {
         }
     }
 
-    async _updateStack(model, stack) {
+    update(model) {
         this._model = model;
+    }
+
+    async _updateStack(model, stack) {
+        this.update(model);
         this._stack = stack;
         const status = await this.renderGraph(this._model, this.activeTarget, this.activeSignature, this._options);
         if (status !== '') {
-            this._model = null;
+            this.update(null);
             this._stack = [];
             this._activeTarget = null;
         }
@@ -2856,14 +2859,14 @@ view.NodeSidebar = class extends view.ObjectSidebar {
                 this.addArgument(name, output);
             }
         }
-        const metadata = node.metadata;
+        const metadata = this._view.model.attachment.metadata.node(node);
         if (Array.isArray(metadata) && metadata.length > 0) {
             this.addSection('Metadata');
             for (const argument of metadata) {
                 this.addArgument(argument.name, argument);
             }
         }
-        const metrics = this._view.metrics.node(node);
+        const metrics = this._view.model.attachment.metrics.node(node);
         if (Array.isArray(metrics) && metrics.length > 0) {
             this.addSection('Metrics');
             for (const argument of metrics) {
@@ -3502,13 +3505,14 @@ view.ConnectionSidebar = class extends view.ObjectSidebar {
             this.addSection('Outputs');
             this.addNodeList('to', to);
         }
-        if (Array.isArray(value.metadata) && value.metadata.length > 0) {
+        const metadata = this._view.model.attachment.metadata.value(value);
+        if (Array.isArray(metadata) && metadata.length > 0) {
             this.addSection('Metadata');
             for (const argument of value.metadata) {
                 this.addArgument(argument.name, argument);
             }
         }
-        const metrics = this._view.metrics.value(value);
+        const metrics = this._view.model.attachment.metrics.value(value);
         if (Array.isArray(metrics) && metrics.length > 0) {
             this.addSection('Metrics');
             for (const argument of metrics) {
@@ -3601,7 +3605,7 @@ view.TensorSidebar = class extends view.ObjectSidebar {
             }
             const value = new view.TensorView(this._view, tensor, this._tensor);
             this.addEntry('value', value);
-            const metadata = tensor.metadata;
+            const metadata = this._view.model.attachment.metadata.tensor(tensor);
             if (Array.isArray(metadata) && metadata.length > 0) {
                 this.addSection('Metadata');
                 for (const argument of tensor.metadata) {
@@ -3617,8 +3621,8 @@ view.TensorSidebar = class extends view.ObjectSidebar {
                 this._tensor = new base.Tensor(tensor);
                 if (!this._tensor.empty) {
                     if (!this._metrics) {
-                        const tensor = new metrics.Tensor(this._tensor);
-                        this._metrics = this._view.metrics.tensor(tensor);
+                        const tensor = new metadata.Tensor(this._tensor);
+                        this._metrics = this._view.model.attachment.metrics.tensor(tensor);
                     }
                     if (this._metrics.length > 0) {
                         this.addSection('Metrics');
@@ -3681,14 +3685,14 @@ view.ModelSidebar = class extends view.ObjectSidebar {
         if (model.source) {
             this.addProperty('source', model.source);
         }
-        const metadata = model.metadata;
+        const metadata = this._view.model.attachment.metadata.model(model);
         if (Array.isArray(metadata) && metadata.length > 0) {
             this.addSection('Metadata');
             for (const argument of metadata) {
                 this.addArgument(argument.name, argument);
             }
         }
-        const metrics = this._view.metrics.model(model);
+        const metrics = this._view.model.attachment.metrics.model(model);
         if (Array.isArray(metrics) && metrics.length > 0) {
             this.addSection('Metrics');
             for (const argument of metrics) {
@@ -3747,14 +3751,14 @@ view.TargetSidebar = class extends view.ObjectSidebar {
                 this.addArgument(output.name, output);
             }
         }
-        const metadata = target.metadata;
+        const metadata = this._view.model.attachment.metadata.graph(target);
         if (Array.isArray(metadata) && metadata.length > 0) {
             this.addSection('Metadata');
             for (const argument of metadata) {
                 this.addArgument(argument.name, argument);
             }
         }
-        const metrics = this._view.metrics.graph(target);
+        const metrics = this._view.model.attachment.metrics.graph(target);
         if (Array.isArray(metrics) && metrics.length > 0) {
             this.addSection('Metrics');
             for (const argument of metrics) {
@@ -5315,27 +5319,21 @@ markdown.Generator = class {
     }
 };
 
-metrics.Metrics = class {
+metadata.Attachment = class {
 
     constructor() {
-        this._metrics = new Map();
+        this.metadata = new metadata.Attachment.Container('metadata');
+        this.metrics = new metadata.Attachment.Container('metrics');
     }
 
     async open(context) {
-        const content = new view.Context(context);
-        if (content.identifier.toLowerCase().endsWith('.metrics.json')) {
-            const data = await content.peek('json');
-            if (data && data.signature === 'metrics' && Array.isArray(data.metrics)) {
-                this._metrics.clear();
-                for (const metric of data.metrics) {
-                    if (metric.kind && ('target' in metric || 'identifier' in metric)) {
-                        const key = 'target' in metric ? `${metric.kind}::${metric.target}` : `${metric.kind}[${metric.identifier}]`;
-                        if (!this._metrics.has(key)) {
-                            this._metrics.set(key, new Map());
-                        }
-                        const entries = this._metrics.get(key);
-                        entries.set(metric.name, { value: metric.value, type: metric.type });
-                    }
+        context = new view.Context(context);
+        if (context.identifier.toLowerCase().endsWith('.json')) {
+            const data = await context.peek('json');
+            if (data && data.signature === 'netron:attachment') {
+                const containers = [this.metadata, this.metrics];
+                for (const container of containers) {
+                    container.open(data[container.name]);
                 }
                 return true;
             }
@@ -5343,40 +5341,80 @@ metrics.Metrics = class {
         return false;
     }
 
-    metrics(entries, kind, value) {
-        const result = new Map(entries.map((metric) => [metric.name, metric]));
-        const name = value.identifier === undefined ? `::${(value.name || '').split('\n').shift()}` : `[${value.identifier}]`;
-        const key = `${kind}${name}`;
-        if (this._metrics.has(key)) {
-            for (const [name, metric] of this._metrics.get(key)) {
-                result.set(name, new metrics.Argument(name, metric.value, metric.type || 'attribute'));
+};
+
+metadata.Attachment.Container = class {
+
+    constructor(name) {
+        this._name = name;
+        this._entries = new Map();
+    }
+
+    get name() {
+        return this._name;
+    }
+
+    open(data) {
+        this._entries.clear();
+        if (Array.isArray(data)) {
+            for (const item of data) {
+                if (item.kind && ('target' in item || 'identifier' in item)) {
+                    const key = 'target' in item ? `${item.kind}::${item.target}` : `${item.kind}[${item.identifier}]`;
+                    if (!this._entries.has(key)) {
+                        this._entries.set(key, new Map());
+                    }
+                    const entries = this._entries.get(key);
+                    entries.set(item.name, { value: item.value, type: item.type });
+                }
             }
         }
-        return Array.from(result.values());
     }
 
     model(value) {
-        return this.metrics(value.metrics || [], 'model', '');
+        return this._list(value, 'model');
     }
 
     graph(value) {
-        return this.metrics(value.metrics || [], 'graph', value);
+        return this._list(value, 'graph');
     }
 
     node(value) {
-        return this.metrics(value.metrics || [], 'node', value);
+        return this._list(value, 'node');
     }
 
     value(value) {
-        return this.metrics(value.metrics || [], 'value', value);
+        return this._list(value, 'value');
     }
 
     tensor(value) {
-        return this.metrics(value.metrics || [], 'tensor', value);
+        return this._list(value, 'tensor');
+    }
+
+    _list(value, kind) {
+        const category = this._name;
+        const entries = value[category] || [];
+        const result = new Map(entries.map((entry) => [entry.name, entry]));
+        if (value.name || kind === 'model') {
+            const key = `${kind}::${(value.name || '').split('\n').shift()}`;
+            if (this._entries.has(key)) {
+                for (const [name, entry] of this._entries.get(key)) {
+                    result.set(name, { name, value: entry.value, type: entry.type || 'attribute' });
+                }
+            }
+        }
+        if (value.identifier) {
+            const key = `${kind}[${value.identifier}]`;
+            if (this._entries.has(key)) {
+                for (const [name, entry] of this._entries.get(key)) {
+                    result.set(name, { name, value: entry.value, type: entry.type || 'attribute' });
+                }
+            }
+        }
+        return Array.from(result.values());
     }
 };
 
-metrics.Argument = class {
+metadata.Argument = class {
 
     constructor(name, value, type) {
         this.name = name;
@@ -5385,7 +5423,7 @@ metrics.Argument = class {
     }
 };
 
-metrics.Tensor = class {
+metadata.Tensor = class {
 
     constructor(tensor) {
         this._tensor = tensor;
@@ -5430,13 +5468,13 @@ metrics.Tensor = class {
                 }
                 const mean = sum / count;
                 if (!keys.has('sparsity')) {
-                    this._metrics.push(new metrics.Argument('min', min, type.dataType));
+                    this._metrics.push(new metadata.Argument('min', min, type.dataType));
                 }
                 if (!keys.has('max')) {
-                    this._metrics.push(new metrics.Argument('max', max, type.dataType));
+                    this._metrics.push(new metadata.Argument('max', max, type.dataType));
                 }
                 if (!keys.has('mean')) {
-                    this._metrics.push(new metrics.Argument('mean', mean, type.dataType));
+                    this._metrics.push(new metadata.Argument('mean', mean, type.dataType));
                 }
                 if (!keys.has('std')) {
                     let variance = 0;
@@ -5451,10 +5489,10 @@ metrics.Tensor = class {
                             variance += Math.pow(data - mean, 2);
                         }
                     }
-                    this._metrics.push(new metrics.Argument('std', Math.sqrt(variance / count)));
+                    this._metrics.push(new metadata.Argument('std', Math.sqrt(variance / count)));
                 }
                 if (!keys.has('sparsity')) {
-                    this._metrics.push(new metrics.Argument('sparsity', count > 0 ? zeros / count : 0, 'percentage'));
+                    this._metrics.push(new metadata.Argument('sparsity', count > 0 ? zeros / count : 0, 'percentage'));
                 }
             }
         }
@@ -6386,6 +6424,7 @@ view.ModelFactoryService = class {
                     if (!model.identifier) {
                         model.identifier = context.identifier;
                     }
+                    model.attachment = new metadata.Attachment();
                     return model;
                 } catch (error) {
                     delete context.type;

+ 1 - 0
test/worker.js

@@ -578,6 +578,7 @@ export class Target {
         }
         const modelFactoryService = new view.ModelFactoryService(this.host);
         this.model = await modelFactoryService.open(context);
+        this.view.update(this.model);
     }
 
     async validate() {