1window.initCg = async function (sel, slug, {clickedId, clickedIdCb, isModal, isGridsnap} = {}){ 2 var data = await util.getFile(`/graph_data/${slug}.json`) 3 console.log(data) 4 5 var visState = { 6 pinnedIds: [], 7 hiddenIds: [], 8 hoveredId: null, 9 hoveredNodeId: null, 10 hoveredCtxIdx: null, 11 clickedId: null, 12 clickedCtxIdx: null, 13 linkType: 'both', 14 isShowAllLinks: '', 15 isSyncEnabled: '', 16 subgraph: null, 17 isEditMode: 1, 18 isHideLayer: data.metadata.scan == util.scanSlugToName.h35 || data.metadata.scan == util.scanSlugToName.moc, 19 sg_pos: '', 20 isModal: true, 21 isGridsnap, 22 ...data.qParams 23 } 24 25 if (visState.clickedId?.includes('supernode')) delete visState.clickedId 26 if (clickedId && clickedId != 'null' && !clickedId.includes('supernode-')) visState.clickedId = clickedId 27 if (!visState.clickedId || visState.clickedId == 'null' || visState.clickedId == 'undefined') visState.clickedId = data.nodes.find(d => d.isLogit)?.nodeId 28 29 if (visState.pinnedIds.replace) visState.pinnedIds = visState.pinnedIds.split(',') 30 if (visState.hiddenIds.replace) visState.hiddenIds = visState.hiddenIds.split(',') 31 32 await utilCg.formatData(data, visState) 33 34 var renderAll = util.initRenderAll(['hClerpUpdate', 'clickedId', 'hiddenIds', 'pinnedIds', 'linkType', 'isShowAllLinks', 'features', 'isSyncEnabled', 'shouldSortByWeight', 'hoveredId']) 35 36 function colorNodes() { 37 data.nodes.forEach(d => d.nodeColor = '#fff') 38 } 39 colorNodes() 40 41 // global link color â the color scale skips #fff so links are visible 42 // TODO: weight by input sum instead 43 function colorLinks() { 44 var absMax = d3.max(data.links, d => d.absWeight) 45 var _linearAbsScale = d3.scaleLinear().domain([-absMax, absMax]) 46 var _linearPctScale = d3.scaleLinear().domain([-.4, .4]) 47 var _linearTScale = d3.scaleLinear().domain([0, .5, .5, 1]).range([0, .5 - .001, .5 + .001, 1]) 48 49 var widthScale = d3.scaleSqrt().domain([0, 1]).range([.00001, 3]) 50 51 utilCg.pctInputColorFn = d => d3.interpolatePRGn(_linearTScale(_linearPctScale(d))) 52 53 data.links.forEach(d => { 54 // d.color = d3.interpolatePRGn(_linearTScale(_linearAbsScale(d.weight))) 55 d.strokeWidth = widthScale(Math.abs(d.pctInput)) 56 d.pctInputColor = utilCg.pctInputColorFn(d.pctInput) 57 d.color = d3.interpolatePRGn(_linearTScale(_linearPctScale(d.pctInput))) 58 }) 59 } 60 colorLinks() 61 62 renderAll.hClerpUpdate.fns.push(() => utilCg.hClerpUpdateFn(null, data)) 63 64 renderAll.hoveredId.fns.push(() => { 65 // use hovered node if possible, otherwise use last occurence of feature 66 var targetCtxIdx = visState.hoveredCtxIdx ?? 999 67 var hoveredNodes = data.nodes.filter(n => n.featureId == visState.hoveredId) 68 var node = d3.sort(hoveredNodes, d => Math.abs(d.ctx_idx - targetCtxIdx))[0] 69 visState.hoveredNodeId = node?.nodeId 70 }) 71 72 // set tmpClickedLink w/ strength of all the links connected the clickedNode 73 renderAll.clickedId.fns.push(() => { 74 clickedIdCb?.(visState.clickedId) 75 76 var node = data.nodes.idToNode[visState.clickedId] 77 if (!node){ 78 // for a clicked supernode, sum over memberNode links to make tmpClickedLink 79 if (visState.clickedId?.startsWith('supernode-')) { 80 node = { 81 nodeId: visState.clickedId, 82 memberNodes: visState.subgraph.supernodes[+visState.clickedId.split('-')[1]] 83 .slice(1) 84 .map(id => data.nodes.idToNode[id]) 85 } 86 node.memberSet = new Set(node.memberNodes.map(d => d.nodeId)) 87 88 function combineLinks(links, isSrc) { 89 return d3.nestBy(links, d => isSrc ? d.sourceNode.nodeId : d.targetNode.nodeId) 90 .map(links => ({ 91 source: isSrc ? links[0].sourceNode.nodeId : visState.clickedId, 92 target: isSrc ? visState.clickedId : links[0].targetNode.nodeId, 93 sourceNode: isSrc ? links[0].sourceNode : node, 94 targetNode: isSrc ? node : links[0].targetNode, 95 weight: d3.sum(links, d => d.weight), 96 absWeight: Math.abs(d3.sum(links, d => d.weight)) 97 })) 98 } 99 100 node.sourceLinks = combineLinks(node.memberNodes.flatMap(d => d.sourceLinks), true) 101 node.targetLinks = combineLinks(node.memberNodes.flatMap(d => d.targetLinks), false) 102 } else {
103 return data.nodes.forEach(d => { 104 d.tmpClickedLink = null 105 d.tmpClickedSourceLink = null 106 d.tmpClickedTargetLink = null 107 }) 108 } 109 } 110 111 var connectedLinks = [...node.sourceLinks, ...node.targetLinks] 112 var max = d3.max(connectedLinks, d => d.absWeight) 113 var colorScale = d3.scaleSequential(d3.interpolatePRGn).domain([-max*1.1, max*1.1]) 114 115 // allowing supernode links means each node can have a both tmpClickedSourceLink and tmpClickedTargetLink 116 // currently we render bidirectional links where possible, falling back to the target side links otherwises 117 var nodeIdToSourceLink = {} 118 var nodeIdToTargetLink = {} 119 var featureIdToLink = {} 120 connectedLinks.forEach(link => { 121 if (link.sourceNode === node) { 122 nodeIdToTargetLink[link.targetNode.nodeId] = link 123 featureIdToLink[link.targetNode.featureId] = link 124 link.tmpClickedCtxOffset = link.targetNode.ctx_idx - node.ctx_idx 125 } 126 if (link.targetNode === node) { 127 nodeIdToSourceLink[link.sourceNode.nodeId] = link 128 featureIdToLink[link.sourceNode.featureId] = link 129 link.tmpClickedCtxOffset = link.sourceNode.ctx_idx - node.ctx_idx 130 } 131 // link.tmpColor = colorScale(link.pctInput) 132 link.tmpColor = link.pctInputColor 133 }) 134 135 data.nodes.forEach(d => { 136 var link = nodeIdToSourceLink[d.nodeId] || nodeIdToTargetLink[d.nodeId] 137 d.tmpClickedLink = link 138 d.tmpClickedSourceLink = nodeIdToSourceLink[d.nodeId] 139 d.tmpClickedTargetLink = nodeIdToTargetLink[d.nodeId] 140 }) 141 142 data.features.forEach(d => { 143 var link = featureIdToLink[d.featureId] 144 d.tmpClickedLink = link 145 }) 146 }) 147 148 function initGridsnap() { 149 var gridData = [ 150 // {cur: {x: 0, y: 0, w: 6, h: 1}, class: 'button-container'}, 151 // {cur: {x: 0, y: 8, w: 8, h: 8}, class: 'subgraph'}, 152 {cur: {x: 8, y: 1, w: 4, h: 6}, class: 'node-connections'}, 153 {cur: {x: 8, y: 6, w: 4, h: 10}, class: 'feature-detail'}, 154 {cur: {x: 0, y: 0, w: 8, h: 16}, class: 'link-graph', resizeFn: makeResizeFn(initCgLinkGraph)}, 155 // {cur: {x: 0, y: 18, w: 6, h: 7}, class: 'clerp-list'}, 156 // {cur: {x: 6, y: 30, w: 4, h: 7}, class: 'feature-scatter'}, 157 // {cur: {x: 0, y: 30, w: 3, h: 8}, class: 'metadata'}, 158 ].filter(d => d) 159 160 var initFns = [ 161 // initCgButtonContainer, 162 // initCgSubgraph, 163 initCgLinkGraph, 164 initCgNodeConnections, 165 initCgFeatureDetail, 166 // initCgClerpList, 167 // initCgFeatureScatter, 168 ].filter(d => d) 169 170 var gridsnapSel = sel.html('').append('div.gridsnap.cg') 171 //.classed('is-edit-mode', visState.isGridsnap) 172 if (visState.isModal) gridsnapSel.st({width: '100%', height: '100%'}) 173 174 175 window.initGridsnap({ 176 gridData, 177 gridSizeY: 50, 178 pad: 10, 179 sel: gridsnapSel, 180 isFullScreenY: false, 181 isFillContainer: visState.isModal, 182 serializedGrid: data.qParams.gridsnap 183 }) 184 185 initFns.forEach(fn => fn({visState, renderAll, data, cgSel: sel})) 186 187 function makeResizeFn(fn){ 188 return () => { 189 fn({visState, renderAll, data, cgSel: sel.select('.gridsnap.cg')}) 190 Object.values(renderAll).forEach(d => d()) 191 } 192 } 193 } 194 195 initGridsnap() 196 renderAll.hClerpUpdate() 197 renderAll.isShowAllLinks() 198 renderAll.linkType() 199 renderAll.clickedId() 200 renderAll.pinnedIds() 201 renderAll.features() 202 renderAll.isSyncEnabled() 203 renderAll.hoveredId() 204} 205 206window.init?.()
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.