AIManage/public/onnx/onnx_view/grapher.js

1 line
18 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

var grapher=grapher||{};var dagre=window.dagre;grapher.Graph=class{constructor(compound,layout){this._layout=layout;this._isCompound=compound;this._nodes=new Map;this._edges=new Map;this._children={};this._children["\0"]={};this._parent={}}setNode(node){const key=node.name;const value=this._nodes.get(key);if(value){value.label=node}else{this._nodes.set(key,{v:key,label:node});if(this._isCompound){this._parent[key]="\0";this._children[key]={};this._children["\0"][key]=true}}}setEdge(edge){if(!this._nodes.has(edge.v)){throw new grapher.Error("Invalid edge '"+JSON.stringify(edge.v)+"'.")}if(!this._nodes.has(edge.w)){throw new grapher.Error("Invalid edge '"+JSON.stringify(edge.w)+"'.")}const key=edge.v+":"+edge.w;if(!this._edges.has(key)){this._edges.set(key,{v:edge.v,w:edge.w,label:edge})}}setParent(node,parent){if(!this._isCompound){throw new Error("Cannot set parent in a non-compound graph")}parent+="";for(let ancestor=parent;ancestor;ancestor=this.parent(ancestor)){if(ancestor===node){throw new Error("Setting "+parent+" as parent of "+node+" would create a cycle")}}delete this._children[this._parent[node]][node];this._parent[node]=parent;this._children[parent][node]=true;return this}get nodes(){return this._nodes}hasNode(key){return this._nodes.has(key)}node(key){return this._nodes.get(key)}get edges(){return this._edges}parent(key){if(this._isCompound){const parent=this._parent[key];if(parent!=="\0"){return parent}}return null}children(key){key=key===undefined?"\0":key;if(this._isCompound){const children=this._children[key];if(children){return Object.keys(children)}}else if(key==="\0"){return this.nodes.keys()}else if(this.hasNode(key)){return[]}return null}build(document,origin){const createGroup=name=>{const element=document.createElementNS("http://www.w3.org/2000/svg","g");element.setAttribute("id",name);element.setAttribute("class",name);origin.appendChild(element);return element};const clusterGroup=createGroup("clusters");const edgePathGroup=createGroup("edge-paths");const edgeLabelGroup=createGroup("edge-labels");const nodeGroup=createGroup("nodes");const edgePathGroupDefs=document.createElementNS("http://www.w3.org/2000/svg","defs");edgePathGroup.appendChild(edgePathGroupDefs);const marker=id=>{const element=document.createElementNS("http://www.w3.org/2000/svg","marker");element.setAttribute("id",id);element.setAttribute("viewBox","0 0 10 10");element.setAttribute("refX",9);element.setAttribute("refY",5);element.setAttribute("markerUnits","strokeWidth");element.setAttribute("markerWidth",8);element.setAttribute("markerHeight",6);element.setAttribute("orient","auto");const markerPath=document.createElementNS("http://www.w3.org/2000/svg","path");markerPath.setAttribute("d","M 0 0 L 10 5 L 0 10 L 4 5 z");markerPath.style.setProperty("stroke-width",1);element.appendChild(markerPath);return element};edgePathGroupDefs.appendChild(marker("arrowhead"));edgePathGroupDefs.appendChild(marker("arrowhead-select"));edgePathGroupDefs.appendChild(marker("arrowhead-hover"));for(const nodeId of this.nodes.keys()){const entry=this.node(nodeId);const node=entry.label;if(this.children(nodeId).length==0){node.build(document,nodeGroup)}else{node.rectangle=document.createElementNS("http://www.w3.org/2000/svg","rect");if(node.rx){node.rectangle.setAttribute("rx",entry.rx)}if(node.ry){node.rectangle.setAttribute("ry",entry.ry)}node.element=document.createElementNS("http://www.w3.org/2000/svg","g");node.element.setAttribute("class","cluster");node.element.appendChild(node.rectangle);clusterGroup.appendChild(node.element)}}for(const edge of this.edges.values()){edge.label.build(document,edgePathGroup,edgeLabelGroup)}}measure(){for(const key of this.nodes.keys()){const entry=this.node(key);if(this.children(key).length==0){const node=entry.label;node.measure()}}}layout(){dagre.layout(this,this._layout);for(const key of this.nodes.keys()){const entry=this.node(key);if(this.children(key).length==0){const node=entry.label;node.layout()}}}update(){for(const nodeId of this.nodes.keys()){if(this.children(nodeId).length==0){const entry=this.node(nodeId);const node=entry.label;node.update()}else{const entry=this.node(nodeId);const node=entry.label;node.element.setAttribute("transform","translate("+node.x+","+node.y+")");node.rectangle.setAttribute("x",-node.width/2);node.rectangle.setAttribute("y",-node.height/2);node.rectangle.setAttribute("width",node.width);node.rectangle.setAttribute("height",node.height)}}for(const edge of this.edges.values()){edge.label.update()}}};grapher.Node=class{constructor(){this._blocks=[]}header(){const block=new grapher.Node.Header;this._blocks.push(block);return block}list(){const block=new grapher.Node.List;this._blocks.push(block);return block}canvas(){const block=new grapher.Node.Canvas;this._blocks.push(block);return block}build(document,parent){this.element=document.createElementNS("http://www.w3.org/2000/svg","g");if(this.id){this.element.setAttribute("id",this.id)}this.element.setAttribute("class",this.class?"node "+this.class:"node");this.element.style.opacity=0;parent.appendChild(this.element);this.border=document.createElementNS("http://www.w3.org/2000/svg","path");this.border.setAttribute("class","node node-border");for(let i=0;i<this._blocks.length;i++){const block=this._blocks[i];block.first=i===0;block.last=i===this._blocks.length-1;block.build(document,this.element)}this.element.appendChild(this.border)}measure(){this.height=0;for(const block of this._blocks){block.measure();this.height=this.height+block.height}this.width=Math.max(...this._blocks.map(block=>block.width));for(const block of this._blocks){block.width=this.width}}layout(){let y=0;for(const block of this._blocks){block.x=0;block.y=y;block.width=this.width;block.layout();y+=block.height}}update(){for(const block of this._blocks){block.update()}this.border.setAttribute("d",grapher.Node.roundedRect(0,0,this.width,this.height,true,true,true,true));this.element.setAttribute("transform","translate("+(this.x-this.width/2)+","+(this.y-this.height/2)+")");this.element.style.removeProperty("opacity")}select(){if(this.element){this.element.classList.add("select");return[this.element]}return[]}deselect(){if(this.element){this.element.classList.remove("select")}}static roundedRect(x,y,width,height,r1,r2,r3,r4){const radius=5;r1=r1?radius:0;r2=r2?radius:0;r3=r3?radius:0;r4=r4?radius:0;return"M"+(x+r1)+","+y+"h"+(width-r1-r2)+"a"+r2+","+r2+" 0 0 1 "+r2+","+r2+"v"+(height-r2-r3)+"a"+r3+","+r3+" 0 0 1 "+-r3+","+r3+"h"+(r3+r4-width)+"a"+r4+","+r4+" 0 0 1 "+-r4+","+-r4+"v"+(-height+r4+r1)+"a"+r1+","+r1+" 0 0 1 "+r1+","+-r1+"z"}};grapher.Node.Header=class{constructor(){this._entries=[]}add(id,classList,content,tooltip,handler){const entry=new grapher.Node.Header.Entry(id,classList,content,tooltip,handler);this._entries.push(entry);return entry}build(document,parent){this._document=document;for(const entry of this._entries){entry.build(document,parent)}if(!this.first){this.line=document.createElementNS("http://www.w3.org/2000/svg","line");parent.appendChild(this.line)}for(let i=0;i<this._entries.length;i++){const entry=this._entries[i];if(i!=0){entry.line=document.createElementNS("http://www.w3.org/2000/svg","line");parent.appendChild(entry.line)}}}measure(){this.width=0;this.height=0;for(const entry of this._entries){entry.measure();this.height=Math.max(this.height,entry.height);this.width+=entry.width}}layout(){let x=this.width;for(let i=this._entries.length-1;i>=0;i--){const entry=this._entries[i];if(i>0){x-=entry.width;entry.x=x}else{entry.x=0;entry.width=x}}}update(){for(let i=0;i<this._entries.length;i++){const entry=this._entries[i];entry.element.setAttribute("transform","translate("+entry.x+","+this.y+")");const r1=i==0&&this.first;const r2=i==this._entries.length-1&&this.first;const r3=i==this._entries.length-1&&this.last;const r4=i==0&&this.last;entry.path.setAttribute("d",grapher.Node.roundedRect(0,0,entry.width,entry.height,r1,r2,r3,r4));entry.text.setAttribute("x",6);entry.text.setAttribute("y",entry.ty)}for(let i=1;i<this._entries.length;i++){const entry=this._entries[i];const line=entry.line;line.setAttribute("class","node");line.setAttribute("x1",entry.x);line.setAttribute("x2",entry.x);line.setAttribute("y1",this.y);line.setAttribute("y2",this.y+this.height)}if(this.line){this.line.setAttribute("class","node");this.line.setAttribute("x1",0);this.line.setAttribute("x2",this.width);this.line.setAttribute("y1",this.y);this.line.setAttribute("y2",this.y)}}};grapher.Node.Header.Entry=class{constructor(id,classList,content,tooltip,handler){this.id=id;this.classList=classList;this.content=content;this.tooltip=tooltip;this.handler=handler;this._events={}}on(event,callback){this._events[event]=this._events[event]||[];this._events[event].push(callback)}emit(event,data){if(this._events&&this._events[event]){for(const callback of this._events[event]){callback(this,data)}}}build(document,parent){this.element=document.createElementNS("http://www.w3.org/2000/svg","g");parent.appendChild(this.element);this.path=document.createElementNS("http://www.w3.org/2000/svg","path");this.text=document.createElementNS("http://www.w3.org/2000/svg","text");this.element.appendChild(this.path);this.element.appendChild(this.text);const classList=["node-item"];if(this.classList){classList.push(...this.classList)}this.element.setAttribute("class",classList.join(" "));if(this.id){this.element.setAttribute("id",this.id)}if(this._events.click){this.element.addEventListener("click",e=>{e.stopPropagation();this.emit("click")})}if(this.tooltip){const title=document.createElementNS("http://www.w3.org/2000/svg","title");title.textContent=this.tooltip;this.element.appendChild(title)}this.text.textContent=this.content||" "}measure(){const yPadding=4;const xPadding=7;const boundingBox=this.text.getBBox();this.width=boundingBox.width+xPadding+xPadding;this.height=boundingBox.height+yPadding+yPadding;this.tx=xPadding;this.ty=yPadding-boundingBox.y}layout(){}};grapher.Node.List=class{constructor(){this._items=[];this._events={}}add(name,value,tooltip,separator){const item=new grapher.Node.List.Item(name,value,tooltip,separator);this._items.push(item);return item}on(event,callback){this._events[event]=this._events[event]||[];this._events[event].push(callback)}emit(event,data){if(this._events&&this._events[event]){for(const callback of this._events[event]){callback(this,data)}}}build(document,parent){this._document=document;this.element=document.createElementNS("http://www.w3.org/2000/svg","g");this.element.setAttribute("class","node-attribute-list");if(this._events.click){this.element.addEventListener("click",e=>{e.stopPropagation();this.emit("click")})}this.background=document.createElementNS("http://www.w3.org/2000/svg","path");this.element.appendChild(this.background);parent.appendChild(this.element);for(const item of this._items){const group=document.createElementNS("http://www.w3.org/2000/svg","g");group.setAttribute("class","node-attribute");const text=document.createElementNS("http://www.w3.org/2000/svg","text");text.setAttribute("xml:space","preserve");if(item.tooltip){const title=document.createElementNS("http://www.w3.org/2000/svg","title");title.textContent=item.tooltip;text.appendChild(title)}const colon=item.type==="node"||item.type==="node[]";const name=document.createElementNS("http://www.w3.org/2000/svg","tspan");name.textContent=colon?item.name+":":item.name;if(item.separator.trim()!=="="&&!colon){name.style.fontWeight="bold"}text.appendChild(name);group.appendChild(text);this.element.appendChild(group);item.group=group;item.text=text;if(item.type==="node"){const node=item.value;node.build(document,item.group)}else if(item.type==="node[]"){for(const node of item.value){node.build(document,item.group)}}else{const tspan=document.createElementNS("http://www.w3.org/2000/svg","tspan");tspan.textContent=item.separator+item.value;item.text.appendChild(tspan)}}if(!this.first){this.line=document.createElementNS("http://www.w3.org/2000/svg","line");this.line.setAttribute("class","node");this.element.appendChild(this.line)}}measure(){this.width=75;this.height=3;const yPadding=1;const xPadding=6;for(let i=0;i<this._items.length;i++){const item=this._items[i];const size=item.text.getBBox();item.width=xPadding+size.width+xPadding;item.height=yPadding+size.height+yPadding;item.offset=size.y;this.height+=item.height;if(item.type==="node"){const node=item.value;node.measure();this.width=Math.max(150,this.width,node.width+2*xPadding);this.height+=node.height+yPadding+yPadding+yPadding+yPadding;if(i===this._items.length-1){this.height+=3}}else if(item.type==="node[]"){for(const node of item.value){node.measure();this.width=Math.max(150,this.width,node.width+2*xPadding);this.height+=node.height+yPadding+yPadding+yPadding+yPadding}if(i===this._items.length-1){this.height+=3}}this.width=Math.max(this.width,item.width)}this.height+=3}layout(){const yPadding=1;const xPadding=6;let y=3;for(const item of this._items){item.x=this.x+xPadding;item.y=y+yPadding-item.offset;y+=item.height;if(item.type==="node"){const node=item.value;node.width=this.width-xPadding-xPadding;node.layout();node.x=this.x+xPadding+node.width/2;node.y=y+node.height/2+yPadding+yPadding;y+=node.height+yPadding+yPadding+yPadding+yPadding}else if(item.type==="node[]"){for(const node of item.value){node.width=this.width-xPadding-xPadding;node.layout();node.x=this.x+xPadding+node.width/2;node.y=y+node.height/2+yPadding+yPadding;y+=node.height+yPadding+yPadding+yPadding+yPadding}}}}update(){this.element.setAttribute("transform","translate("+this.x+","+this.y+")");this.background.setAttribute("d",grapher.Node.roundedRect(0,0,this.width,this.height,this.first,this.first,this.last,this.last));for(const item of this._items){const text=item.text;text.setAttribute("x",item.x);text.setAttribute("y",item.y);if(item.type==="node"){const node=item.value;node.update()}else if(item.type==="node[]"){for(const node of item.value){node.update()}}}if(this.line){this.line.setAttribute("x1",0);this.line.setAttribute("x2",this.width);this.line.setAttribute("y1",0);this.line.setAttribute("y2",0)}for(const item of this._items){if(item.value instanceof grapher.Node){const node=item.value;node.update()}}}};grapher.Node.List.Item=class{constructor(name,value,tooltip,separator){this.name=name;this.value=value;this.tooltip=tooltip;this.separator=separator;if(value instanceof grapher.Node){this.type="node"}else if(Array.isArray(value)&&value.every(value=>value instanceof grapher.Node)){this.type="node[]"}}};grapher.Node.Canvas=class{constructor(){this.width=0;this.height=80}build(){}update(){}};grapher.Edge=class{constructor(from,to){this.from=from;this.to=to}build(document,edgePathGroupElement,edgeLabelGroupElement){const createElement=name=>{return document.createElementNS("http://www.w3.org/2000/svg",name)};this.element=createElement("path");if(this.id){this.element.setAttribute("id",this.id)}this.element.setAttribute("class",this.class?"edge-path "+this.class:"edge-path");edgePathGroupElement.appendChild(this.element);this.hitTest=createElement("path");this.hitTest.setAttribute("class","edge-path-hit-test");this.hitTest.addEventListener("pointerover",()=>this.emit("pointerover"));this.hitTest.addEventListener("pointerleave",()=>this.emit("pointerleave"));this.hitTest.addEventListener("click",()=>this.emit("click"));edgePathGroupElement.appendChild(this.hitTest);if(this.label){const tspan=createElement("tspan");tspan.setAttribute("xml:space","preserve");tspan.setAttribute("dy","1em");tspan.setAttribute("x","1");tspan.appendChild(document.createTextNode(this.label));this.labelElement=createElement("text");this.labelElement.appendChild(tspan);this.labelElement.style.opacity=0;this.labelElement.setAttribute("class","edge-label");if(this.id){this.labelElement.setAttribute("id","edge-label-"+this.id)}edgeLabelGroupElement.appendChild(this.labelElement);const edgeBox=this.labelElement.getBBox();this.width=edgeBox.width;this.height=edgeBox.height}}update(){const intersectRect=(node,point)=>{const x=node.x;const y=node.y;const dx=point.x-x;const dy=point.y-y;let h=node.height/2;let w=node.width/2;if(Math.abs(dy)*w>Math.abs(dx)*h){if(dy<0){h=-h}return{x:x+(dy===0?0:h*dx/dy),y:y+h}}if(dx<0){w=-w}return{x:x+w,y:y+(dx===0?0:w*dy/dx)}};const curvePath=(edge,tail,head)=>{const points=edge.points.slice(1,edge.points.length-1);points.unshift(intersectRect(tail,points[0]));points.push(intersectRect(head,points[points.length-1]));return new grapher.Edge.Curve(points).path.data};const edgePath=curvePath(this,this.from,this.to);this.element.setAttribute("d",edgePath);this.hitTest.setAttribute("d",edgePath);if(this.labelElement){this.labelElement.setAttribute("transform","translate("+(this.x-this.width/2)+","+(this.y-this.height/2)+")");this.labelElement.style.opacity=1}}select(){if(this.element){if(!this.element.classList.contains("select")){const path=this.element;path.classList.add("select");this.element=path.cloneNode(true);path.parentNode.replaceChild(this.element,path)}return[this.element]}return[]}deselect(){if(this.element&&this.element.classList.contains("select")){const path=this.element;path.classList.remove("select");this.element=path.cloneNode(true);path.parentNode.replaceChild(this.element,path)}}};grapher.Edge.Curve=class{constructor(points){this._path=new grapher.Edge.Path;this._x0=NaN;this._x1=NaN;this._y0=NaN;this._y1=NaN;this._state=0;for(let i=0;i<points.length;i++){const point=points[i];this.point(point.x,point.y);if(i===points.length-1){switch(this._state){case 3:this.curve(this._x1,this._y1);this._path.lineTo(this._x1,this._y1);break;case 2:this._path.lineTo(this._x1,this._y1);break;default:break}if(this._line||this._line!==0&&this._point===1){this._path.closePath()}this._line=1-this._line}}}get path(){return this._path}point(x,y){x=+x;y=+y;switch(this._state){case 0:this._state=1;if(this._line){this._path.lineTo(x,y)}else{this._path.moveTo(x,y)}break;case 1:this._state=2;break;case 2:this._state=3;this._path.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);this.curve(x,y);break;default:this.curve(x,y);break}this._x0=this._x1;this._x1=x;this._y0=this._y1;this._y1=y}curve(x,y){this._path.bezierCurveTo((2*this._x0+this._x1)/3,(2*this._y0+this._y1)/3,(this._x0+2*this._x1)/3,(this._y0+2*this._y1)/3,(this._x0+4*this._x1+x)/6,(this._y0+4*this._y1+y)/6)}};grapher.Edge.Path=class{constructor(){this._x0=null;this._y0=null;this._x1=null;this._y1=null;this._data=""}moveTo(x,y){this._data+="M"+(this._x0=this._x1=+x)+","+(this._y0=this._y1=+y)}lineTo(x,y){this._data+="L"+(this._x1=+x)+","+(this._y1=+y)}bezierCurveTo(x1,y1,x2,y2,x,y){this._data+="C"+ +x1+","+ +y1+","+ +x2+","+ +y2+","+(this._x1=+x)+","+(this._y1=+y)}closePath(){if(this._x1!==null){this._x1=this._x0;this._y1=this._y0;this._data+="Z"}}get data(){return this._data}};if(typeof window!=="undefined"&&typeof window==="object"){window.grapher=grapher}