add placeholder for rename in sidebar

1123
ZhangGe6 4 years ago
parent aa2541f6e3
commit 872c1409b4

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@ -0,0 +1,50 @@
<img src="./docs/onnx_modifier_logo_1.png" style="zoom: 67%;" />
# Introduction
To edit an ONNX model, One common way is to visualize the model graph, and edit it using ONNX Python API. This works fine. However, we have to code to edit, then visualize to check. The two processes may iterate for many times, which is time-consuming.
What if we have a tool, which allow us **edit and preview the editing effect in a totally visualization fashion**? Then `onnx-modifier` comes. With it, we can focus on editing the model graph in the visualization pannel. Finally, all editing information will be summarized and processed by Python ONNX automatically. Most importantly, our time will be saved!
`onnx-modifier` is built based on the popular network viewer [netron](https://github.com/lutzroeder/netron) and the lightweight web application framework [flask](https://github.com/pallets/flask).
Currently, the following editing operations are supported:
- Delete a single node.
- Delete a node and all the nodes rooted with it.
- Recover/Reset a node.
Hope it helps!
# Get started
Install the require Python packages by
```bash
pip install onnx
pip install flask
```
Then run
```bash
python app.py
```
Click the url in the output info generated by flask (`http://127.0.0.1:5000/` for example), then `onnx-modifier` will be launched in the web browser.
Click `Open Model...` to upload the onnx model to edit. The model will be parsed and show on the page.
# Edit
On the left-top of the page,
All the editing

@ -17,6 +17,8 @@ grapher.Graph = class {
this._modelNodeName2ViewNode = new Map();
this._modelNodeName2State = new Map();
this._namedEdges = new Map();
this._pathArgumentNames = new Set(); // the name of arguments which occurs in both sides of an edge
}
get options() {
@ -82,6 +84,7 @@ grapher.Graph = class {
this._namedEdges.get(from_node_name).push(to_node_name);
}
setParent(node, parent) {
if (!this._isCompound) {
throw new Error("Cannot set parent in a non-compound graph");

@ -129,16 +129,11 @@ sidebar.NodeSidebar = class {
this._node = node;
this._modelNodeName = modelNodeName;
this._elements = [];
this._renameAuxelements = [] // auxilary elements for input/output renaming
this._attributes = [];
this._inputs = [];
this._outputs = [];
this._addButton('Delete With Children');
this.add_span('between-delete')
this._addButton('Delete Single Node');
this.add_separator('line_DR')
this._addButton('Reset Node');
if (node.type) {
let showDocumentation = null;
const type = node.type;
@ -188,22 +183,35 @@ sidebar.NodeSidebar = class {
}
const inputs = node.inputs;
// console.log(inputs)
if (inputs && inputs.length > 0) {
this._addHeader('Inputs');
for (const input of inputs) {
this._addInput(input.name, input);
this._addInput(input.name, input); // 这里的input.name是小白格前面的名称不是方格内的
this.add_rename_aux_element(input.arguments);
}
}
// console.log(this._renameAuxelements)
const outputs = node.outputs;
if (outputs && outputs.length > 0) {
this._addHeader('Outputs');
for (const output of outputs) {
this._addOutput(output.name, output);
this.add_rename_aux_element(output.arguments);
}
}
this.add_separator('sidebar-view-separator')
this._addButton('Delete With Children');
this.add_span()
this._addButton('Delete Single Node');
this.add_span()
this._addButton('Reset Node');
this.add_separator('sidebar-view-separator');
this._addHeader('Rename helper');
}
@ -215,13 +223,31 @@ sidebar.NodeSidebar = class {
add_span(className) {
const span = this._host.document.createElement('span');
span.innerHTML = "&nbsp;"; // (if this doesn't work, try " ")
span.innerHTML = "&nbsp;&nbsp;&nbsp;"; // (if this doesn't work, try " ")
span.className = className;
this._elements.push(span);
}
add_rename_aux_element (arguments_) {
if (arguments_.length > 0) {
for (const argument of arguments_) {
if (this._host._view._graph._pathArgumentNames.has(argument.name)) {
const buttonElement = this._host.document.createElement('button');
buttonElement.className = 'sidebar-view-button';
buttonElement.innerText = argument.name;
this._renameAuxelements.push(buttonElement);
}
}
}
}
render() {
return this._elements;
console.log(this._elements)
console.log(this._renameAuxelements)
// return this._elements;
return this._elements.concat(this._renameAuxelements);
}
_addHeader(title) {
@ -258,6 +284,7 @@ sidebar.NodeSidebar = class {
const item = new sidebar.NameValueView(this._host, name, view);
this._inputs.push(item);
this._elements.push(item.render());
}
}
@ -290,7 +317,7 @@ sidebar.NodeSidebar = class {
if (title === 'Reset Node') {
// console.log('pressed')
buttonElement.addEventListener('click', () => {
this._host._view._graph.recover_node(this._modelNodeName)
this._host._view._graph.reset_node(this._modelNodeName)
});
}
@ -424,13 +451,16 @@ sidebar.NameValueView = class {
const nameElement = this._host.document.createElement('div');
nameElement.className = 'sidebar-view-item-name';
// ===> 这一段是input框前的名称如attributte的pad不包含后面的小白块太有误导性了。。。
// console.log(name)
const nameInputElement = this._host.document.createElement('input');
nameInputElement.setAttribute('type', 'text');
nameInputElement.setAttribute('value', name);
nameInputElement.setAttribute('title', name);
nameInputElement.setAttribute('readonly', 'true');
nameInputElement.setAttribute('readonly', 'false');
nameElement.appendChild(nameInputElement);
// <=== 这一段是input框前的名称如attributte的pad
const valueElement = this._host.document.createElement('div');
valueElement.className = 'sidebar-view-item-value-list';
@ -507,7 +537,7 @@ sidebar.ValueTextView = class {
this._host = host;
this._elements = [];
const element = this._host.document.createElement('div');
element.className = 'sidebar-view-item-value';
element.className = 'sidebar-view-item-value'; // 这个渲染出后面一个长白格
this._elements.push(element);
if (action) {
@ -532,6 +562,7 @@ sidebar.ValueTextView = class {
}
render() {
console.log(this._elements)
return this._elements;
}
@ -665,10 +696,15 @@ class NodeAttributeView {
sidebar.ParameterView = class {
constructor(host, list) {
this._host = host;
this._list = list;
this._elements = [];
this._items = [];
// console.log('new ParameterView')
// console.log(list.arguments) // Array(1)
for (const argument of list.arguments) {
// console.log(argument)
const item = new sidebar.ArgumentView(host, argument);
item.on('export-tensor', (sender, tensor) => {
this._raise('export-tensor', tensor);
@ -766,6 +802,10 @@ sidebar.ArgumentView = class {
return this._element;
}
render_rename_aux() {
return this._renameAuxelements;
}
toggle() {
if (this._expander) {
if (this._expander.innerText == '+') {

@ -947,17 +947,7 @@ view.Graph = class extends grapher.Graph {
}
for (const node of graph.nodes) {
// console.log(node)
// if (this._modelNodeName2State.get(node.name) == 'Deleted') {
// // console.log(this._modelNodeName2State.get(node.name))
// continue;
// }
const viewNode = this.createNode(node);
// My code
// if (this._modelNodeName2State.get(viewNode.modelNodeName) == 'Deleted') {
// // console.log(this._modelNodeName2State.get(node.name))
// continue;
// }
const inputs = node.inputs;
for (const input of inputs) {
@ -1098,7 +1088,9 @@ view.Graph = class extends grapher.Graph {
for (const argument of this._arguments.values()) {
argument.build();
}
console.log(this._namedEdges)
// console.log("this._pathArgumentNames");
// console.log(this._pathArgumentNames);
// console.log(this._namedEdges)
super.build(document, origin);
}
};
@ -1366,6 +1358,9 @@ view.Argument = class {
this.context.setEdge(edge);
this._edges.push(edge);
// console.log(this.context._namedEdges);
// this argument occurs in both sides of the edge, so it is a `path` argument
this.context._pathArgumentNames.add(this._argument.name);
}
}
}

Loading…
Cancel
Save