Skip to content

LLouice/platform

Repository files navigation

Contents

Project

libtorch

inject data

cargo run --release --example inject_data

Front-end

trunk

github website

rebuild issue

trunk-rs/trunk#156 (comment)

Trunk supports an optional Trunk.toml config file. An example config file is included in the Trunk repo, and shows all available config options along with their default values. By default, Trunk will look for a Trunk.toml config file in the current working directory. Trunk supports the global –config option to specify an alternative location for the file.

Note that any relative paths declared in a Trunk.toml file will be treated as being relative to the Trunk.toml file itself.

# An example Trunk.toml with all possible fields along with their defaults.

[build]
# The index HTML file to drive the bundling process.
target = "index.html"
# Build in release mode.
release = false
# The output dir for all final assets.
dist = "dist"
# The public URL from which assets are to be served.
public_url = "/"

[watch]
# Paths to watch. The `build.target`'s parent folder is watched by default.
watch = []
# Paths to ignore.
ignore = []

[serve]
# The port to serve on.
port = 8080
# Open a browser tab once the initial build is complete.
open = false
# Disable auto-reload of the web app.
no_autoreload = false

[clean]
# The output dir for all final assets.
dist = "dist"
# Optionally perform a cargo clean.
cargo = false

[tools]
# Default wasm-bindgen version to download.
wasm_bindgen = "0.2.74"
# Default wasm-opt version to download.
wasm_opt = "version_101"

## proxy
# Proxies are optional, and default to `None`.
# Proxies are only run as part of the `trunk serve` command.

[[proxy]]
# This WebSocket proxy example has a backend and ws field. This example will listen for
# WebSocket connections at `/api/ws` and proxy them to `ws://localhost:9000/api/ws`.
backend = "ws://localhost:9000/api/ws"
ws = true

[[proxy]]
# This proxy example has a backend and a rewrite field. Requests received on `rewrite` will be
# proxied to the backend after rewriting the `rewrite` prefix to the `backend`'s URI prefix.
# E.G., `/api/v1/resource/x/y/z` -> `/resource/x/y/z`
rewrite = "/api/v1/"
backend = "http://localhost:9000/"

[[proxy]]
# This proxy specifies only the backend, which is the only required field. In this example,
# request URIs are not modified when proxied.
backend = "http://localhost:9000/api/v2/"

script

all build data go into dist directory include script: copy-file then foo.js

web

d3.js

template
label
var nodeEnter = d3.select("svg").selectAll("g.node")
    .data(nodes)
    .enter()
    .append("g")
    .attr("class", "node")
    .call(force.drag());

nodeEnter.append("circle")
    .attr("r", 5)
    .style("fill", "#CC9999");

nodeEnter.append("text")
    .style("text-anchor", "middle")
    .attr("y", 15)
    .text(function (d) {return d.id})

function updateNetwork() {
    d3.select("svg").selectAll("g.node")
        .attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"});
fixing networks and nodes
var nodeEnter = d3.select("svg").selectAll("g.node")
    .data(nodes)
    .enter()
    .append("g")
    .attr("class", "node")
    .on("click", nodeClick)
    .on("dblclick", nodeDoubleClick)
    .on("mouseover", nodeOver)
    .on("mouseout", nodeOut)
    .call(force.drag());

function nodeClick(d) {
    d.fixed = true;
}

function nodeDoubleClick(d) {
    d.fixed = false;
    force.start();
}

function nodeOver() {
    force.stop();
}

function nodeOut() {
    force.start();
}
ego network 可展开

全部数据 隐藏展开模式?

function nodeOver(d) {
    force.stop();
    highlightEgoNetwork(d);
}

function nodeOut() {
    force.start();
    d3.selectAll("g.node > circle")
        .style("fill", "#CC9999");

    d3.selectAll("line")
        .style("stroke", "#996666")
        .style("stroke-width", "1px");
}

function highlightEgoNetwork(d) {
    var egoIDs = [];
    var filteredEdges = edges.filter(function (p) {return p.source == d || p.target == d});

    filteredEdges
        .forEach(function (p) {
            if (p.source == d) {
                egoIDs.push(p.target.id)
            }
            else {
                egoIDs.push(p.source.id)
            }
        });

    d3.selectAll("line")
        .filter(function (p) {return filteredEdges.indexOf(p) > -1})
        .style("stroke", "#66CCCC")
        .style("stroke-width", "2px");

    d3.selectAll("circle")
        .filter(function (p) {return egoIDs.indexOf(p.id) > -1})
        .style("fill", "#66CCCC");
}

function updateNetwork() {
    d3.select("svg").selectAll("g.node > circle")
        .attr("r", function (d) {return d.weight});
deleting nodes and edges (dblclick)
edgeEnter
  .append("line")
  .attr("class", "highlight")
  .style("stroke-width", "8px")
  .style("stroke", "#66CCCC")
  .style("opacity", 0)
  .on("dblclick", deleteEdge)
  .on("mouseover", edgeOver)
  .on("mouseout", edgeOut);

var nodeEnter = d3.select("svg").selectAll("g.node")
  .data(nodes, function (d) {return d.id})
  .enter()
  .append("g")
  .attr("class", "node")
  .on("dblclick", deleteNode)
  .on("mouseover", nodeOver)
  .on("mouseout", nodeOut)
  .call(force.drag());

function deleteNode(d) {
    var currentNodes = d3.selectAll("g.node").data();
    var currentEdges = d3.selectAll("g.edge").data();
    var filteredNodes = currentNodes.filter(function (p) {return p !== d});
    var filteredEdges = currentEdges.filter(function (p) {return p.source !== d && p.target !== d});

    force.stop();
    force.nodes(filteredNodes);
    force.links(filteredEdges);

    d3.selectAll("g.node").data(filteredNodes, function (d) {return d.id})
    .exit()
    .transition()
    .duration(500)
    .style("opacity", 0)
    .remove();

    d3.selectAll("g.edge").data(filteredEdges, function (d) {return d.id})
    .exit()
    .transition()
    .duration(500)
    .style("opacity", 0)
    .remove();

    force.start();
}

function deleteEdge(d) {
    var currentEdges = d3.selectAll("g.edge").data();
    var filteredEdges = currentEdges.filter(function (p) {return p !== d});

    force.stop();
    force.links(filteredEdges);

    d3.selectAll("g.edge").data(filteredEdges, function (d) {return d.id})
    .exit()
    .transition()
    .duration(500)
    .style("opacity", 0)
    .remove();

    force.start();
}

function nodeOver() {
    d3.select(this).select("circle")
      .style("fill", "#66CCCC")
      .style("stroke", "#66CCCC")
      .style("stroke-width", "3px");
}

function nodeOut() {
    d3.selectAll("circle")
      .style("fill", "#CC9999")
      .style("stroke", "black")
      .style("stroke-width", "1px");
}

function edgeOver(d) {
    d3.select(this).style("opacity", 0.75);
}

function edgeOut() {
    d3.selectAll("line.highlight").style("opacity", 0);
}
mini-map
var modules = nodes.map(function (d) {return d.module})
    .filter(onlyUnique)
    .map(function (d) {return {id: d, members: []}});

var moduleEdges = [];
var singletons = {id: "singletons", members: []};

var moduleNodeHash = {};

modules.forEach(function (module) {
    module.members = nodes.filter(function (d) {return d.module === module.id});
    moduleNodeHash[module.id] = module;

    if (module.members.length === 1) {
        singletons.members.push(module.members[0]);
    }
});

modules.push(singletons);

var moduleEdgeHash = {};

edges.forEach(function (edge) {
    if (!moduleEdgeHash[moduleNodeHash[edge.source.module].id + "-" + moduleNodeHash[edge.target.module].id]) {
        var moduleEdge = {source: moduleNodeHash[edge.source.module], target: moduleNodeHash[edge.target.module], weight: 1};
        moduleEdgeHash[moduleNodeHash[edge.source.module].id + "-" + moduleNodeHash[edge.target.module].id] = moduleEdge;
        moduleEdges.push(moduleEdge);
    }
    else {
        moduleEdgeHash[moduleNodeHash[edge.source.module].id + "-" + moduleNodeHash[edge.target.module].id].weight += 1;
    }
})

return {nodes: modules, edges: moduleEdges}

var modularityGraph = modularityCensus(nodes, edges, result);

var modularityForce = d3.layout.force()
    .nodes(modularityGraph.nodes)
    .links(modularityGraph.edges)
    .size([125,125])
    .charge(function (d) {return d.members.length * -25})
    .gravity(0.75)
    .on("tick", updateModularityNetwork);

var mSVG = d3.select("#viz").append("svg")
    .attr("class", "modularity")
    .attr("height", 100)
    .attr("width", 100)
    .style("height", 100)
    .style("width", 100)
    .style("position", "absolute")
    .style("left", 375)
    .style("top", 375)
    .style("background", "white");

mSVG.selectAll("line")
    .data(modularityGraph.edges)
    .enter()
    .append("line")
    .attr("class", "modularity")
    .style("stroke-width", function (d) {return d.weight * 2})
    .style("stroke", "black");

mSVG.selectAll("circle")
    .data(modularityGraph.nodes.filter(function(d) {return d.members.length > 1}))
    .enter()
    .append("circle")
    .attr("class", "modularity")
    .attr("r", function (d) {return d.members.length})
    .style("stroke", "black")
    .style("stroke-width", "1px")
    .style("fill", function (d) {return d.id == "singletons" ? "lightgray" : colors(d.id)})

modularityForce.start();

function updateModularityNetwork() {
    d3.select("svg.modularity").selectAll("line")
        .attr("x1", function (d) {return d.source.x})
        .attr("y1", function (d) {return d.source.y})
        .attr("x2", function (d) {return d.target.x})
        .attr("y2", function (d) {return d.target.y});

    d3.select("svg.modularity").selectAll("circle")
        .attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"});
}
linked mini-map
function moduleOver(d) {
    d3.select(this)
        .style("stroke-width", "4px")
    d3.select("svg.main").selectAll("circle")
        .style("stroke-width", function (p) {return p.module == d.id ? "4px" : "1px"})
}

function moduleOut(d) {
    d3.select(this)
        .style("stroke-width", "1px")
    d3.select("svg.main").selectAll("circle")
        .style("stroke-width", "1px")
}

function updateNetwork() {
    d3.select("svg.modularity").selectAll("circle")
        .each(function (d) {
            var theseNodes = d.members;
            var avgX = d3.mean(theseNodes, function (p) {return p.x});
            var avgY = d3.mean(theseNodes, function (p) {return p.y});
            d.x = avgX / 5;
            d.y = avgY / 5;
        })
        .attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"});

    d3.select("svg.modularity").selectAll("line")
        .attr("x1", function (d) {return d.source.x})
        .attr("y1", function (d) {return d.source.y})
        .attr("x2", function (d) {return d.target.x})
        .attr("y2", function (d) {return d.target.y});
make connections (drag to connect)
var drag = force.drag()
    .on("drag", drag)
    .on("dragend", dragend)
    .on("dragstart", dragstart);

var nodeEnter = d3.select("svg.main").selectAll("g.node")
    .data(nodes, function (d) {return d.id})
    .enter()
    .append("g")
    .attr("class", "node")
    .call(drag);

function dragstart() {
    nodes.forEach(function (node) {
        node.fixed = true;
    })
}

function drag(d) {
    var nodeDom = this;
    var foundOverlap = false
    nodes.forEach(function (otherNode) {
        var distance = Math.sqrt(Math.pow(otherNode.x - d.x, 2) + Math.pow(otherNode.y - d.y, 2));
        if (otherNode != d && distance < 16) {
            foundOverlap = true;
        }
    })
    if (foundOverlap == true) {
        d3.select(nodeDom).select("circle.background")
            .style("opacity", 0.5)
    }
    else {
        d3.select(nodeDom).select("circle.background")
            .style("opacity", 0)
    }
}

function dragend(d) {
    force.stop();

    d3.selectAll("circle.background")
        .style("opacity", 0);

    nodes.forEach(function (otherNode) {
        otherNode.fixed = false;
        var distance = Math.sqrt(Math.pow(otherNode.x - d.x, 2) + Math.pow(otherNode.y - d.y, 2));
        if (otherNode != d && distance < 16) {
            var newEdge = {id: d.id + "-" + otherNode.id, source: d, target: otherNode};
            if (edges.map(function (d) {return d.id}).indexOf(newEdge.id) == -1) {
                edges.push(newEdge);
            }
        }
    });
    force.links(edges);

    var edgeEnter = d3.select("svg.main").selectAll("g.edge")
        .data(edges, function (d) {return d.id})
        .enter()
        .insert("g", "g.node")
        .attr("class", "edge");

    edgeEnter
        .append("line")
        .style("stroke-width", function (d) {return d.border ? "3px" : "1px"})
        .style("stroke", "black")
        .style("pointer-events", "none");

    var community = jLouvain().nodes(node_data).edges(edge_data);
    var result  = community();

    nodes.forEach(function (node) {
        node.module = result[node.id]
    });

    node_data = nodes.map(function (d) {return d.id});
    edge_data = edges.map(function (d) {return {source: d.source.id, target: d.target.id, weight: 1}; });

    modularityCensus(nodes, edges, result);

    d3.selectAll("circle.foreground")
        .style("fill", function (d) {return colors(d.module)})
        .style("stroke-width", function (d) {return d.border ? "3px" : "1px"});

    force.start();
}
forcesimulation

side effect!!! change data.nodes and data.links

"nodes":{
    "id": 2,
    "index": 1,
    "name": "B",
    "vx": 0,
    "vy": 0,
    "x": -9.03088751750192,
    "y": 8.273032735715967
},
"links":{
    "source": {
        "id": 3,
        "index": 2,
        "name": "C",
        "vx": 0,
        "vy": 0,
        "x": 1.3823220809823638,
        "y": -15.750847141167634,
    },
    "target": {
        "id": 4,
        "index": 3,
        "name": "D",
        "vx": 0,
        "vy": 0,
        "x": 11.382848792909423,
        "y": 14.846910566099618
    }
}
legend

https://www.d3-graph-gallery.com/graph/custom_legend.html

****

types/d3
npm install --save @types/d3
reference

https://github.com/Lemoncode/d3js-typescript-examples

data

selection.data default bases on array index, use key fn to customize data key

swc & tsc

swc src --out-dir build/src -w --sync & tsc -w --pretty --skipLibCheck --noEmit

svg

g

group other SVG elements svg tut

The <g>-element doesn’t have x and y attributes. To move the contents of a <g>-element you can only do so using the transform attribute, using the “translate” function, like this: transform=”translate(x,y)”.

parcel bundle

sudo sysctl fs.inotify.max_user_watches=32768

esbuild

./node_modules/.bin/esbuild src/index.ts --bundle --outfile=out.js

todo

  • [x] include bundle data
  • [x] import all export js snippet

界面构建

  • [x] navbar
  • [ ] mobile responsive

Echarts

word cloud

https://github.com/ecomfe/echarts-wordcloud/

About Data

Type

“rdf-schema#subClassOf”,

2:#疾病 rdf-schema#subClassOf      owl#Thing
4:#症状 rdf-schema#subClassOf      owl#Thing
6:#科室 rdf-schema#subClassOf      owl#Thing
8:#检查 rdf-schema#subClassOf      owl#Thing
10:#药品        rdf-schema#subClassOf      owl#Thing
12:#中药        rdf-schema#subClassOf      #药品
14:#西药        rdf-schema#subClassOf      #药品
16:#中医症状      rdf-schema#subClassOf      #症状
18:#西医症状      rdf-schema#subClassOf      #症状

“owl#sameAs”,

245236:急性发热性嗜中性白细胞增多性皮肤病或隆起性红斑        owl#sameAs 斯威特氏综合征
245237:酞咪脉啶酮,沙利窦迈,撒利多胺        owl#sameAs 撒利多胺
245238:新达罗颗粒剂,头孢克洛颗粒剂 owl#sameAs 头孢克洛颗粒剂
245239:先天性红细胞生成不良性贫血,遗传性良性网织红细胞增生性贫血  owl#sameAs 先天性红细胞生成不良性贫血
245240:上气     owl#sameAs 气喘,喘逆,喘促
245241:野蜀葵    owl#sameAs 三叶
245242:妊娠试验   owl#sameAs 尿HCG
245243:老年人慢性肾衰竭       owl#sameAs 老年人慢性肾功能衰竭
245244:小儿主动脉弓综合征      owl#sameAs 小儿高安氏动脉炎
245245:晶      owl#sameAs 晶状体诱导的葡萄膜炎
245246:小儿房中隔缺损        owl#sameAs 小儿房缺
245247:斯欧蜜    owl#sameAs 火府丸
245248:疔      owl#sameAs 外阴疖
245249:海冻菜,红丝 owl#sameAs 红丝
245250:绿萼梅,绿梅花        owl#sameAs 白梅花

“22-rdf-syntax-ns#type”,

“X rdf-schema#label”,

200746:雌二醇地屈孕酮片复合包装   rdf-schema#label   雌二醇地屈孕酮片复合包装"@Z
204680:肾微粒体抗体测定       rdf-schema#label   肾微粒体抗体测定"@Z
208670:雌二醇地屈孕酮片复合包装)  rdf-schema#label   雌二醇地屈孕酮片复合包装)"@Z
209788:1.2型   rdf-schema#label   1.2型"@Z
210669:中毒性表皮坏死松解型药疹   rdf-schema#label   中毒性表皮坏死松解型药疹"@Z
213265:地塞米松眼膏)        rdf-schema#label   地塞米松眼膏)"@Z
213735:S)型    rdf-schema#label   S)型"@Z
214565:粒*100粒*5瓶      rdf-schema#label   粒*100粒*5瓶"@Z
214825:长链脂肪乳注射液(C8~24Ve)      rdf-schema#label   长链脂肪乳注射液(C8~24Ve)"@Z
216010:氢氯噻嗪片  rdf-schema#label   氢氯噻嗪片"@Z
217294:克拉维酸钾片 rdf-schema#label   克拉维酸钾片"@Z
218617:盒包TYS  rdf-schema#label   盒包TYS"@Z
221118:30(精蛋白锌重组人胰岛素混合注射液)    rdf-schema#label   30(精蛋白锌重组人胰岛素混合注射液)"@Z
224908:粒))    rdf-schema#label   粒))"@Z
225809:三氯生乳膏  rdf-schema#label   三氯生乳膏"@Z
228247:地塞米松眼膏 rdf-schema#label   地塞米松眼膏"@Z
228794:甲氧苄啶   rdf-schema#label   甲氧苄啶"@Z

“X rdf-schema#domain”,

20:#症状相关症状    rdf-schema#domain  #症状
23:#症状相关疾病    rdf-schema#domain  #症状
26:#症状相关药品    rdf-schema#domain  #症状
29:#症状相关科室    rdf-schema#domain  #症状
32:#症状相关检查    rdf-schema#domain  #症状
35:#症状相关部位    rdf-schema#domain  #症状
38:#疾病相关症状    rdf-schema#domain  #疾病
41:#疾病相关疾病    rdf-schema#domain  #疾病
44:#疾病相关药品    rdf-schema#domain  #疾病
47:#疾病相关科室    rdf-schema#domain  #疾病
50:#疾病相关检查    rdf-schema#domain  #疾病
53:#疾病相关部位    rdf-schema#domain  #疾病
56:#检查相关症状    rdf-schema#domain  #检查
59:#检查相关疾病    rdf-schema#domain  #检查
62:#检查相关科室    rdf-schema#domain  #检查
65:#检查相关检查    rdf-schema#domain  #检查
68:#检查相关部位    rdf-schema#domain  #检查

“X rdf-schema#range”,

21:#症状相关症状    rdf-schema#range   #症状
24:#症状相关疾病    rdf-schema#range   #疾病
27:#症状相关药品    rdf-schema#range   #药品
30:#症状相关科室    rdf-schema#range   #科室
33:#症状相关检查    rdf-schema#range   #检查
36:#症状相关部位    rdf-schema#range   rdf-schema#Literal
39:#疾病相关症状    rdf-schema#range   #症状
42:#疾病相关疾病    rdf-schema#range   #疾病
45:#疾病相关药品    rdf-schema#range   #药品
48:#疾病相关科室    rdf-schema#range   #科室
51:#疾病相关检查    rdf-schema#range   #检查
54:#疾病相关部位    rdf-schema#range   rdf-schema#Literal
57:#检查相关症状    rdf-schema#range   #症状
60:#检查相关疾病    rdf-schema#range   #疾病
63:#检查相关科室    rdf-schema#range   #科室
66:#检查相关检查    rdf-schema#range   #检查
69:#检查相关部位    rdf-schema#range   rdf-schema#Literal

“X 症状相关药品”, just a little, not include in triples due to # in there

“X 疾病相关药品”, just a little, not include in triples due to # in there

Triples

27915 17 52146 { “检查相关症状”, “疾病相关疾病”, “疾病相关症状”, “检查相关部位”, “症状相关部位”, “症状相关症状”, “症状相关科室”, “症状相关疾病”, “症状相关检查”, “疾病相关检查”, “疾病相关部位”, “疾病相关药品”, “检查相关检查”, “检查相关疾病”, “疾病相关科室”, “症状相关药品”, “检查相关科室”, }

togs_head: 687 togs_tail: 1385

Rel

“检查相关症状”,=> 检查后遗症 “症状相关检查”, => 检查

区分性不大 后者质量更差 “疾病相关检查”, “检查相关疾病”,

Todo

症状 - 推测 -> 疾病 -> 科室

split to cats

症状

症状相关部位 症状相关症状 症状相关科室 症状相关疾病 症状相关检查 症状相关药品 all: 200043 unique: 10894

*

疾病

疾病相关疾病 疾病相关症状 疾病相关检查 疾病相关部位 疾病相关药品 疾病相关科室 all: 359438 unique: 14664

检查

检查相关症状 检查相关部位 检查相关检查 检查相关疾病 检查相关科室 all: 45217 unique: 2361

部位

检查相关部位 症状相关部位 疾病相关部位 all: 17274 unique: 111

药品

疾病相关药品 症状相关药品 all: 109246 unique: 14277

科室

症状相关科室 疾病相关科室 检查相关科室 all: 70040 unique: 291

Nebula

SPACE

CREATE SPACE [IF NOT EXISTS] <graph_space_name> [(partition_num = <partition_number>, replica_factor = <replica_number>, vid_type = {FIXED_STRING(<N>)) | INT64}];

Create TAG and EDGE

CREATE {TAG | EDGE} {<tag_name> | <edge_type>}(<property_name> <data_type> [, <property_name> <data_type> …]);

Insert vertices and edges

INSERT VERTEX <tag_name> (<property_name>[, <property_name>…]) [, <tag_name> (<property_name>[, <property_name>…]), …] {VALUES | VALUE} <vid>: (<property_value>[, <property_value>…]) [, <vid>: (<property_value>[, <property_value>…];

INSERT EDGE <edge_type> (<property_name>[, <property_name>…]) {VALUES | VALUE} <src_vid> -> <dst_vid>[@<rank>] : (<property_value>[, <property_value>…]) [, <src_vid> -> <dst_vid>[@<rank> : (<property_name>[, <property_name>…]), …]

GO

GO [[<M> TO] <N> STEPS ] FROM <vertex_list> OVER <edge_type_list> [REVERSELY] [BIDIRECT] [WHERE <expression> [AND | OR expression …])] YIELD [DISTINCT] <return_list>

FETCH

FETCH PROP ON {<tag_name> | <tag_name_list> | *} <vid_list> [YIELD [DISTINCT] <return_list>]

FETCH PROP ON <edge_type> <src_vid> -> <dst_vid>[@<rank>] [, <src_vid> -> <dst_vid> …] [YIELD [DISTINCT] <return_list>]

LOOKUP

LOOKUP ON {<tag_name> | <edge_type>} WHERE <expression> [AND expression …])] [YIELD <return_list>]

MATCH

MATCH <pattern> [<WHERE clause>] RETURN <output>

Neo4j

create relation

match (s:Symptom{name: "血压过低"}) delete s;
MATCH (a:Person),(b:Movie)
WHERE a.name = 'Tom Hanks' AND b.title = 'Forrest Gump'
CREATE (a)-[r:ACTED_IN { roles:['Forrest'] }]->(b)
RETURN r;

MATCH(s:Symptom), (a:Area) WHERE s.name=$sname AND a.name=$aname
    CREATE (s) -[r:symptom_relate_area]->(a)
    RETURN r

constraint

CREATE CONSTRAINT ON (n:Person) ASSERT n.name IS UNIQUE;

debug

“match (ps:{}{{name:$name}}) -[r]-> (pt) return ps,r,pt”,

MATCH (n:Disease) RETURN n LIMIT 25
match (ps:Disease{name:'风热疮'}) -[r]-> (pt) return ps,r,pt
match (pt) -[r]-> (ps:Disease{name:'风热疮'}) return ps,r,pt
match (pt) -[r]-> (ps:Symptom{name:'肩背痛'}) return ps,r,pt
match (ps:Symptom{name:'肩背痛'}) -[r]-> (pt) return ps,r,pt

TodoList

  • [X] display single main node one hop neighbors
  • [ ] select data and train
  • [ ] get stats

Todo

  • [x] 启动旧的工程?
  • [ ] 再造旧的界面
  • [x] split server / client
  • [ ] web debug css
  • [x] learn d3.js
  • [x] typescript
  • [ ] Echarts 文档通读
  • [ ] split the demo.html
  • [ ] modulize the demo.html
  • [x] 词云
  • [ ] 整理代码片段
  • [ ] split the network and stats

machine learning model

read all triples from neo4j

cypher

all triples
match (x)-[r]->(y) return distinct head(labels(x)) as head, type(r), head(labels(y)) as tail limit 20
match (x)-[r]->(y) return distinct x as head, type(r), r as rname, y as tail limit 20
leaf nodes
match (n)  where not (n)-->()  return distinct n
match () -->(t) with t, count(t) as ts where ts = 1  and not (t) --> () return t,ts

head return the first element in a list

constraint
CREATE CONSTRAINT constraint_Symptom_name IF NOT EXISTS ON (s:Symptom) ASSERT s.name IS UNIQUE;
CREATE CONSTRAINT constraint_Disease_name IF NOT EXISTS ON (s:Disease) ASSERT s.name IS UNIQUE;
CREATE CONSTRAINT constraint_Drug_name IF NOT EXISTS ON (s:Drug) ASSERT s.name IS UNIQUE;
CREATE CONSTRAINT constraint_Department_name IF NOT EXISTS ON (s:Department) ASSERT s.name IS UNIQUE;
CREATE CONSTRAINT constraint_Check_name IF NOT EXISTS ON (s:Check) ASSERT s.name IS UNIQUE;
CREATE CONSTRAINT constraint_Area_name IF NOT EXISTS ON (a:Area) ASSERT a.name IS UNIQUE;
delete duplicate nodes and their relationships
MATCH (n:Symptom)
WITH n.name as name, collect(n) AS nodes
WHERE size(nodes) >  1
RETURN nodes

MATCH (n:Symptom) WITH n.name as name, collect(n) AS nodes WHERE size(nodes) > 1 with head(nodes) as nn return nn;

MATCH (n:Symptom) WITH collect(n) AS nodes WHERE size(nodes) > 1 WITH head(nodes) as n return n;

MATCH (n:Symptom) WITH n.name as name, collect(n) AS nodes WHERE size(nodes) > 1 UNWIND tail(nodes) as n return n;

MATCH (n:Symptom) WITH n.name as name, collect(n) AS nodes WHERE size(nodes) > 1 return nodes

MATCH (n:Area) WITH n.name as name, collect(n) AS nodes WHERE size(nodes) > 1 return nodes

MATCH (g:Symptom) WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1 FOREACH (g in tail(nodes) | DETACH DELETE g)

MATCH (g:Area) WITH g.name as name, collect(g) AS nodes WHERE size(nodes) > 1 FOREACH (g in tail(nodes) | DETACH DELETE g)

match () –>(t) with t, count(t) as ts where ts = 1 and not (t) –> () return t,ts match () –>(t) with t, count(t) as ts where not (t) –> () return t,ts

train triple data
match (h)-->(t) return t UNION match () -->(t) with t, count(t) as ts where ts = 1  and not (t) --> () return t;

stats

  • nodes number: 28754
  • triples number: 148686
  • leaf nodes: 7735
  • non-leaf triples: 140951
most in degree node

neo4j@neo4j> match (h) –> (n:Disease{name:”藏毛窦,藏毛病”}) return count(n); ----------

count(n)

----------

3046

----------

get most connected subgraph

write all data to database? text file

cypher

match (x) -[r]-> (y) return id(x), id(y), type(r) limit 30;

[CANCEL] large graph train

ScalableGCN

https://github.com/alibaba/euler/wiki/ScalableGCN ScalableGCN是一种由阿里妈妈提出的在大规模图上加速Mini-batch GCN训练速度方法。在Mini-batch GCN中,需要投入的计算力与GCN的层数成指数关系。 并且,下层模型的训练频率显著的高于上层。ScalableGCN利用前向计算和反向计算的Cache,在 *mini-batch之间共享中间层表示的计算结果*,同时维护每个顶点上的异步梯度更新的通路。达到在与GCN层数成线性关系的时间内训练GCN模型的目的。

Export to rust

make dataset record with rust

sparse label
make label
use tf.scatter_nd_update

custom record in python(tf.data), create iterator op

split train / valid / test dataset [4/4]

no repeat
separate tfrecord
inspect graph
select the D(h) > 1 && D(t) > 1 and remake the train / test label

define eval logic(op) in tensorflow [2/2]

define val / test dataset
eval op

run in rust [2/2]

make epochs / lr become a placeholder
add cli

Add word embedding

gensim

https://github.com/WENGSYX/Chinese-Word2vec-Medicine

# gensim.models.KeyedVectors
  model = KeyedVectors.load_word2vec_format('Medical.txt', binary=False)

pkgseg-pythoh

https://github.com/lancopku/pkuseg-python

Missing

NE: 28754 Missing: 6474 Missing ratio: 22.5%

Train data and label

(h,r): (t1,t2,t3,t4,t5) => train: (h,r): (t1,t2,t3) val: (h,r): (t4) also need (t1,t2,t3) for masked the prediction test: (h,r): (t5) also need (t1,t2,t3) for masked the prediction

record <= hr_map_trn; hr_map_val; hr_map_test <- hr_map

Serving

  MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['e1'] tensor_info:
        dtype: DT_INT64
        shape: (-1)
        name: input/e1:0
    inputs['rel'] tensor_info:
        dtype: DT_INT64
        shape: (-1)
        name: input/rel:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['prediciton'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 28754)
        name: prediction:0
  Method name is: tensorflow/serving/predict

Rust

rust load model

AdaEInput

frontend -> rel::name -> map id -> AdaEInput::from -> predict

actix-web use model

Usage

cd server && mk r
cd frontend && mk fr