Skip to content

Commit

Permalink
- Added regions
Browse files Browse the repository at this point in the history
- Renamed link "type" to "geometry"
- Added "rectangle" geometry for links
- Fixed spline control points
- Removed obsolete code to draw 3d lyphs
- Script to preprocess bond graph model (incompatible format)
- Updated all test models to work with the related schema changes
  • Loading branch information
albatros13 committed Oct 20, 2018
1 parent ab7f857 commit 252583d
Show file tree
Hide file tree
Showing 27 changed files with 3,404 additions and 679 deletions.
70 changes: 35 additions & 35 deletions docs/index.html

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions manual/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

All entities come with basic properties such as `id` and `name` to identify the physiological element, and `color` to display the corresponding visual object in the viewer. The identifiers of all entities must be unique, the tool will issue a warning if this is not the case.

Each object has a read-only property `class` (the user does not need to specify it, it is assigned automatically) that returns its class from the ApiNATOMY data model, such as `Node`, `Link`, `Lyph`, `Material` or `Group`. The property `external` may be used to keep a reference to an external data source that defines or describes the entity, i.e., the [Foundational Model of Anatomy (FMA)](http://si.washington.edu/projects/fma) ontology.
Each object has a read-only property `class` (the user does not need to specify it, it is assigned automatically) that returns its class from the ApiNATOMY data model, such as `Node`, `Link`, `Lyph`, `Reion`, `Material` or `Group`. The property `external` may be used to keep a reference to an external data source that defines or describes the entity, i.e., the [Foundational Model of Anatomy (FMA)](http://si.washington.edu/projects/fma) ontology.

The property `infoFields` lists properties that are shown in the information panel of the viewer. These properties are typically set by default for all entities of the certain type, but may also be overridden for individual objects. For example, the following value of the `infoFields` property of a lyph object
The property `infoFields` lists properties that are shown in the information panel of the viewer. These properties are typically set by default for all entities of certain type, but may also be overridden for individual objects. For example, the following value of the `infoFields` property of a lyph object
```json
{
"infoFields": {
Expand Down Expand Up @@ -151,7 +151,7 @@ The ApiNATOMY model essentially defines a graph where the positions of nodes are
## Link
Links connect graph nodes and perform a number of functions in the ApiNATOMY framework, most notably, they model process flow and serve as rotational axes to position and scale conveying vessels and body elements at various scales (organs, tissues, cells, etc.).

By default, all links are drawn as straight lines, this corresponds to the `type=link` setting. To apply another visualization method, we set the link's `type` to one of the supported values enumerated in the ApiNATOMY JSON Scheme. For example, `type="semicircle"` produces a spline that resembles a semicircle:
By default, all links are drawn as straight lines, this corresponds to the `geometry=link` setting. To apply another visualization method, we set the link's `geometry` to one of the supported values enumerated in the ApiNATOMY JSON Scheme. For example, `geometry="semicircle"` produces a spline that resembles a semicircle:

```json
{
Expand All @@ -161,32 +161,32 @@ The ApiNATOMY model essentially defines a graph where the positions of nodes are
"name" : "Pulmonary",
"source" : "R",
"target" : "L",
"type" : "semicircle",
"length" : 75,
"geometry" : "semicircle",
"stroke" : "thick"
},
{
"id" : "LR",
"name" : "Systemic",
"source" : "L",
"target" : "R",
"type" : "semicircle",
"length" : 75,
"geometry" : "semicircle",
"stroke" : "thick"
},
{
"id" : "cn",
"source" : "c",
"target" : "n",
"stroke" : "dashed",
"length" : 100
"length" : 100,
"stroke" : "dashed"
}
]
}
```
<img src="asset/links.png" height="300px" caption = "Drawing links">

Among other link types supported by the lyph viewer are `path` to draw graph edges bundled together by the [d3.js edge bundling method](https://bl.ocks.org/vasturiano/7c5f24ef7d4237f7eb33f17e59a6976e).
Among other link geometries supported by the lyph viewer are `path` to draw graph edges bundled together by the [d3.js edge bundling method](https://bl.ocks.org/vasturiano/7c5f24ef7d4237f7eb33f17e59a6976e).

There are also two auxiliary link types: `invisible` links which are never displayed themselves but serve as axes for the lyphs they convey. The `force` links have no corresponding visual objects and currently only serve the purpose of binding together selected nodes. The `invisible` links can either be defined explicitly in the model or auto-generated if a lyph that is an `internalLyph` of some other lyph is not conveyed by any user-defined link in the model.

Expand All @@ -196,7 +196,7 @@ The ApiNATOMY model essentially defines a graph where the positions of nodes are

A link of any type can be set to be `collapsible`. A collapsible link exists only if its ends are constrained by the visible entities in the view, i.e., the link's source and target nodes must be inside of visible lyphs, on separate lyph borders or are hosted by other visible links. If this is not the case, the source and target nodes of the collapsible link are attracted to each other until they collide to look like a single node.

Collapsible links are auto-generated for the models where one node is constrained by two or more different entities meaning that it should be placed to several different locations. This functionality allows modellers to include the same semantic entity to various subsystems in the model, even if these subsystems are split by some space for readability. The auto-generated collapsible links are of type `dashed` to emphasize that the link is an auxiliary line that helps to locate duplicates of the same node.
Collapsible links are auto-generated for the models where one node is constrained by two or more different entities meaning that it should be placed to several different locations. This functionality allows modellers to include the same semantic entity to various subsystems in the model, even if these subsystems are split by some space for readability. The auto-generated collapsible links are `dashed` to emphasize that the link is an auxiliary line that helps to locate duplicates of the same node.

The screenshots below show the link chain representing the anterolateral apinothalamic tract in isolation and in combination with the neural system group. Observe that in the latter case the tract's nodes are bound to the neural system lyph borders with thin dashed transitions among pairs of replicated node instances.

Expand Down Expand Up @@ -332,11 +332,11 @@ The ApiNATOMY model essentially defines a graph where the positions of nodes are
{//...
"assign": [
{
"path": "$.[?(@.id=='1000')].layers[(@.length-1)]",
"path" : "$.[?(@.id=='1000')].layers[(@.length-1)]",
"value": { "internalLyphs": [ "995" ] }
},
{
"path": "$.[?(@.id=='1010')].layers[(@.length-1)]",
"path" : "$.[?(@.id=='1010')].layers[(@.length-1)]",
"value": { "internalLyphs": [ "996" ] }
}
]
Expand Down Expand Up @@ -420,16 +420,16 @@ The ApiNATOMY model essentially defines a graph where the positions of nodes are
"groups": ["arterial", "venous"]
},
{
"id" : "arterial",
"name" : "Arterial",
"nodes": [ "nLR00", "nLR01", "nLR02", "nLR03", "nLR04", "nLR05" ],
"links": [ "LR00", "LR01", "LR02", "LR03", "LR04" ]
"id" : "arterial",
"name" : "Arterial",
"nodes" : [ "nLR00", "nLR01", "nLR02", "nLR03", "nLR04", "nLR05" ],
"links" : [ "LR00", "LR01", "LR02", "LR03", "LR04" ]
},
{
"id" : "venous",
"name" : "Venous",
"nodes": [ "nLR10", "nLR11", "nLR12", "nLR13", "nLR14", "nLR15", "nLR16" ],
"links": [ "LR10", "LR11", "LR12", "LR13", "LR14", "LR15" ]
"id" : "venous",
"name" : "Venous",
"nodes" : [ "nLR10", "nLR11", "nLR12", "nLR13", "nLR14", "nLR15", "nLR16" ],
"links" : [ "LR10", "LR11", "LR12", "LR13", "LR14", "LR15" ]
}
]
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@
"npm": "^5.6.0",
"rxjs": "5",
"three": "^0.92.0",
"three-js-csg": "^72.0.0",
"three-orbit-controls": "^82.1.0",
"three-text2d": "^0.4.1",
"three-window-resize": "^1.0.4",
Expand Down
38 changes: 19 additions & 19 deletions src/components/webGLScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
forceY,
forceZ
} from 'd3-force-3d';
import {LINK_TYPES} from '../models/linkModel';

import {ModelInfoPanel} from './gui/modelInfo';
import {SelectNameSearchBar} from './gui/selectNameSearchBar';
Expand Down Expand Up @@ -42,9 +41,9 @@ const WindowResize = require('three-window-resize');
<section class="w3-center w3-card w3-grey">
<h4>Control panel</h4>
</section>
<fieldset *ngIf="!!_highlighted && !!_highlighted.__data" class="w3-card w3-round w3-margin-small">
<fieldset *ngIf="!!_highlighted && !!_highlighted.userData" class="w3-card w3-round w3-margin-small">
<legend>Highlighted</legend>
<modelInfoPanel [model]=_highlighted.__data></modelInfoPanel>
<modelInfoPanel [model]=_highlighted.userData></modelInfoPanel>
</fieldset>
<fieldset class="w3-card w3-round w3-margin-small">
<legend>Layout</legend>
Expand All @@ -55,7 +54,9 @@ const WindowResize = require('three-window-resize');
</span>
<input type="checkbox" class="w3-check" name="coalescences"
(change)="toggleGroup(graphData.coalescenceGroup)" [checked]="showGroup(graphData.coalescenceGroup)"/> Coalescences
<br/>
</fieldset>
<fieldset class="w3-card w3-round w3-margin-small">
<legend>Groups</legend>
<span *ngFor="let group of graphData.activeGroups">
<input type="checkbox" name="switch" class="w3-check"
(change)="toggleGroup(group)" [checked]="showGroup(group)"/> {{group.name || group.id}}
Expand Down Expand Up @@ -93,9 +94,9 @@ const WindowResize = require('three-window-resize');
<selectNameSearchBar [selectedName]="_selectedLyphName" [namesAvailable]="_namesAvailable"
(selectedBySearchEvent)="selectBySearchEventHandler($event)"></selectNameSearchBar>
</fieldset>
<fieldset *ngIf="!!_selected && !!_selected.__data" class="w3-card w3-round w3-margin-small">
<fieldset *ngIf="!!_selected && !!_selected.userData" class="w3-card w3-round w3-margin-small">
<legend>Selected</legend>
<modelInfoPanel [model]=_selected.__data></modelInfoPanel>
<modelInfoPanel [model]=_selected.userData></modelInfoPanel>
</fieldset>
</section>
</section>
Expand Down Expand Up @@ -160,9 +161,7 @@ export class WebGLSceneComponent {

/*Map initial positional constraints to match the scaled image*/

this._graphData.nodes.forEach(node => node.layout::keys().forEach(key => {
node.layout[key] *= this.axisLength * 0.01; }));
this._graphData.links.filter(link => link.length).forEach(link => link.length *= 2 * this.axisLength * 0.01);
this._graphData.scale(this.axisLength);

if (this.graph) { this.graph.graphData(this._graphData); }
}
Expand All @@ -185,7 +184,7 @@ export class WebGLSceneComponent {
this.unhighlight(this._selected);
this.highlight(obj, this.selectColor, obj !== this.highlighted);
this._selected = obj;
this._selectedLyphName = obj && obj.__data && (obj.__data.constructor.name === "Lyph")? obj.__data.name: "";
this._selectedLyphName = obj && obj.userData && (obj.userData.constructor.name === "Lyph")? obj.userData.name: "";
this.selectedItemChange.emit(obj);
}

Expand All @@ -208,13 +207,14 @@ export class WebGLSceneComponent {
this._showLyphs = true;
this._showLayers = true;
this._showLabels = {
"Node": true,
"Link": false,
"Lyph": false
"Node" : true,
"Link" : false,
"Lyph" : false,
"Region": false
};
this._labelClasses = (this._showLabels)::keys();
this._labelClasses = this._showLabels::keys();
this._labelProps = ["id", "name", "external"];
this._labels = {Node: "id", Link: "id", Lyph: "id"};
this._labels = {Node: "id", Link: "id", Lyph: "id", Region: "id"};
this._hideGroups = new Set();
}

Expand Down Expand Up @@ -356,10 +356,10 @@ export class WebGLSceneComponent {

let intersects = ray.intersectObjects(this.graph.children);
if (intersects.length > 0) {
if (!intersects[0].object.__data || intersects[0].object.__data.inactive) { return; }
if (!intersects[0].object.userData || intersects[0].object.userData.inactive) { return; }
//Refine selection to layers
if (intersects[0].object.__data.layers) {
let layerMeshes = intersects[0].object.__data.layers.map(layer => layer.viewObjects["main"]);
if (intersects[0].object.userData.layers) {
let layerMeshes = intersects[0].object.userData.layers.map(layer => layer.viewObjects["main"]);
let layerIntersects = ray.intersectObjects(layerMeshes);
if (layerIntersects.length > 0) {
return layerIntersects[0].object;
Expand Down Expand Up @@ -401,7 +401,7 @@ export class WebGLSceneComponent {
if (obj.material){
obj.material.color.setHex( obj.currentHex || this.defaultColor);
}
(obj.children || []).filter(child => child.material && child.currentHex).forEach(child => {
(obj.children || []).filter(child => child.material).forEach(child => {
child.material.color.setHex( child.currentHex || this.defaultColor);
})
}
Expand Down
Loading

0 comments on commit 252583d

Please sign in to comment.