d3 hierarchy layout with custom value for non-leaf nodes - layout

d3 defines the hierarchy layout as a tree were leaf nodes have value and non-leaf nodes have children. The value of the non leaf nodes is automatically computed as the sum of the value of its children (see here).
I have slightly different needs. I want to define a tree were non-leaf nodes have a value too. The precondition is that the value of a non-leaf node is always greater or equal to the sum of the value of its children.
{
"name": "parent",
"value": 10, <-- I want to use this value, not 4+2 = 6
"children": [
{
"name": "child1",
"value": 2,
},
{
"name": "child2",
"value": 4,
}
]
}
Graphically, I want to achieve a kind of icicle tree but the children will not always fill all the width of their parent node.
What would be the best solution to achieve this behavior ? I am new to d3 and I don't want to reinvent the wheel or create a new layout from scratch if it is not required.

Related

Aligning nifti files with different shape and q_offset values in header

I have a whole-body MRI scans with the header below:
{
dim : [ 3 320 260 96 1 0 0 0]
pixdim : [1. 1.40625 1.40625 3. 0.00436 0. 0. 0. ]
qoffset_x : -216.09375
qoffset_y : -178.90625
qoffset_z : -664.5
srow_x : [ 1.40625 0. 0. -216.09375]
srow_y : [ 0. 1.40625 0. -178.90625]
srow_z : [ 0. 0. 3. -664.5]
}
Binary label-maps for different organs in the whole-body MRI scan. I need to merge them together as a single label-map nifty file.
One of the label-map has a different shape and q_offset values in its header that make merging difficult. The header of that label-map nifty file below:
{
dim : [ 3 55 49 28 1 1 1 1]
pixdim : [1. 1.40625 1.40625 3. 1. 1. 1. 1. ]
qoffset_x : 119.41935
qoffset_y : 106.36636
qoffset_z : -503.68216
srow_x : [ -1.40625 0. 0. 119.41935]
srow_y : [ 0. -1.40625 0. 106.36636]
srow_z : [ 0. 0. 3. -503.68216]
}
When I overlay the individual label-map on top of the whole-body MRI scan using 3dSlicer, it overlayed perfectly for the concerned organ, but as the shape is different, once after merging all label-maps, it does not work [ Yellow label-map for Spleen organ].
This is how it looks in 3dSlicer [ Look for Yellow region.].
But the expected area of visualization is in the bottom right of below pic. (Spleen Organ)
As the voxel resolution is the same, I think this has something to do with different q_offset values.
Kindly, let me know if anyone has a solution.
It depends on what your program for viewing / post-processing requires.
Some programs need the resolutions to be the same (which is not true in your case), but then may allow different Q/S-forms (when they are not used).
Others allow you to overlay images with different resolutions, but then rely on the Q/S forms to position the images in the view box.
One interesting thing in your nifti headers is that the x and y voxel sizes in the S-form are positive in the scan and negative in the labels.
That means:
increasing x indices go from left to right in the MR scan
increasing x indices go from right to left in the labels
and
increasing y indices go from front to back in the MR scan
increasing y indices go from back to front in the labels
As your viewer seems to take the Q/S-forms into account, that would mean that the voxel data themselves are swapped in both directions. But that also means that the centres of gravity may need adjusting (in one case: offsets are from the left/front, in the other case from the right/back).
You can test that with a copy of your file where the new offsets are changed. The S-form does look like the labels have been aligned (the offsets are greater than the extents of the bounding box) but maybe not with a tool that handles images with different LR and AP orientations well.

Plotting A0 to Z....var in a GeoJson layer using turfjs and leaflet

I am using turfjs and leaflet to plot a grid and label each square in this fashion:
[A0,A1,...,A23]
[B0,B1,...,B23]
[C0,C1,...,C23]
End goal:
To know what are the coordinates of the corner points of each cell. I mean, I want to know what are the coordinates of the 4 corners of A0 ( and the other cells ).This will then be fed to a json file with something like this:
[
{"A0": [
["x","y"],
["x","y"],
["x","y"],
["x","y"]
]},
{"A1": [
["x","y"],
["x","y"],
["x","y"],
["x","y"]
]}
]
Then, my app will ask the GPS from the device and learn which "square" i'm in.
I have managed to plot the squares ( fiddle, but could not label them or even summon a click to console to find out what are the corner coordinates. I have console'd out the layers but i'm not sure if the plot of the geoJson layer is plotted from left to right. I have concluded each layer spits out 5 coordinates which I suspect that is the information I require but there is a 5th coordinate which does not make sense to be in a square grid cell, unless the 3rd coordinate is the center...
I was able to figure out the mystery of the GeoJson layer in leaflet.
The coordinates are returned like this:
[ 0, 3 , 6 ]
[ 1, 4 , 7 ]
[ 2, 5 , 8 ]
//will label this way:
A0 = 0 ( coordinate sets at 0 )
A1 = 1 ( coordinate sets at 1 )
A2 = 2
B0 = 3
B1 = 4
B2 = 5
...
I still don't know why there is a 5th coordinate in each layer plotted by leaflet. but this is good enough for me. I can know label them as I want.
Thank you for the help.

Is corse parent == parent index?

In the H3 library, you can find the corse parent index of a H3 hexagon using the h3ToParent method. Is the corse parent the same as the parent? If not how do I find the true parent index?
The H3 docs generally use "coarse" to indicate larger-hex resolutions with lower numbers (e.g. res 1 hexes, 607,220km2), and "fine" to indicate smaller-hex resolutions with higher numbers (e.g. res 10 hexes, 0.015km2). This is to avoid confusion with "bigger"/"smaller" terminology (is a bigger resolution a large hex or a larger res number?).
The h3ToParent method can return the direct parent of a hexagon (i.e. the coarser hexagon that contains it at the next resolution up), or its ancestor at any given coarser resolution - the second argument specifies the resolution of the parent you want to obtain.
In this image, for example, all of the larger hexagons are "parents" of the smallest hexagon in the center. If the resolution of the center hex is 7, then:
H3Index directParent = h3ToParent(centerHex, 6);
H3Index grandParent = h3ToParent(centerHex, 5);
// etc

Find path following edges with greatest value in ArangoDB

Lets say, that in my graph I've got edges that have field called value. After selecting start vertex I would like to find path by always selecting the edge that has the highest value. Unfortunatly I can't figure out how to write proper query, is it possible in ArangoDB?
Hi i am unsure what you would like to achieve, there are two possible scenarios that i can imagine from your description:
First: Shortest Path
The use-case here is you know the starting vertex and the target vertex, and you want to find the shortest (or cheapest) path between those two.
The built in SHORTEST_PATH (https://docs.arangodb.com/3.1/AQL/Graphs/ShortestPath.html#shortest-path-in-aql) feature can serve it by defining the distance attribute in the options like this:
FOR v IN OUTBOUND #start TO #end ##edgeCollections OPTIONS {weightAttribute: "value", defaultWeight: 1}
RETURN v
This will give you all vertices on the path from start to end which has the lowest some of value attributes. If you need the "highest value" you could copy the value and save it again with 1/value in a different field, to find the path with the fewest edges having in total the highest sum of values
Second: Sorting of edges
The use case is you only have the starting vertex and want to get the connected vertices, ordered by the value on the edges. There you can simply combine the traversal statement with a simple sort. (https://docs.arangodb.com/3.1/AQL/Graphs/Traversals.html#graph-traversals-in-aql):
FOR v, e IN OUTBOUND #start ##edgeCollection
SORT e.value DESC
LIMIT 1 /* Only pick the highest one */
REUTRN {v: v, e: e}
Third use-case: Iterating several depth only using the highest value
The AQL in Use-case 2 can be chained up to an arbitrary depth which has to be known a-priori. So say you would like to iterate 3 steps only using the edge with highest value:
FOR v1, e1 IN OUTBOUND #start ##edgeCollection
SORT e1.value DESC
LIMIT 1 /* Only pick the highest one */
/* Depth 1 done. now depth 2*/
FOR v2, e2 IN OUTBOUND v1 ##edgeCollection
SORT e2.value DESC
LIMIT 1 /* Only pick the highest one */
FOR v3, e3 IN OUTBOUND v2 ##edgeCollection
SORT e3.value DESC
LIMIT 1 /* Only pick the highest one */
RETURN [v1,v2,v3]
Forth use-case:
The depth is not known a-priori, in this case pure AQL in the currently release version (3.1) cannot formulate this. It will be easier to use a Foxx service (https://docs.arangodb.com/3.1/Manual/Foxx/#foxx) using the traversal module (https://docs.arangodb.com/3.1/Manual/Graphs/Traversals/UsingTraversalObjects.html#getting-started) in JavaScript which is a bit more flexible, but can only be implemented in Javascript.

ArangoDB: Get every node, which is in any way related to a selected node

I have a simple node-links graph in ArangoDB. How can I traverse from 1 preselected node and return all nodes which are related to it?
For example:
A→B, B→C, C→D, C→E, F→B, F→E
Selecting any of them should return the same result (all of them).
I am very new to ArangoDB.
What you need is AQL graph traversal, available since ArangoDB 2.8. Older versions provided a set of graph-related functions, but native AQL traversal is faster, more flexible and the graph functions are no longer available starting with 3.0.
AQL traversal let's you follow edges connected to a start vertex, up to a variable depth. Each encountered vertex can be accessed, e.g. for filtering or to construct a result, as well as the edge that led you to this vertex and the full path from start to finish including both, vertices and edges.
In your case, only the names of the visited vertices need to be returned. You can run the following AQL queries, assuming there's a document collection node and an edge collection links and they contain the data for this graph:
// follow edges ("links" collection) in outbound direction, starting at A
FOR v IN OUTBOUND "node/A" links
// return the key (node name) for every vertex we see
RETURN v._key
This will only return [ "B" ], because the traversal depth is implicitly 1..1 (min=1, max=1). If we increase the max depth, then we can include nodes that are indirectly connected as well:
FOR v IN 1..10 OUTBOUND "node/A" links
RETURN v._key
This will give us [ "B", "C", "D", "E"]. If we look at the graph, this is correct: we only follow edges that point from the vertex we come from to another vertex (direction of the arrow). To do the reverse, we could use INBOUND, but in your case, we want to ignore the direction of the edge and follow anyway:
FOR v IN 1..10 ANY "node/A" links
RETURN v._key
The result might be a bit surprising at first:
[ "B", "C", "D", "E", "F", "B", "F", "E", "C", "D", "B" ]
We see duplicate nodes returned. The reason is that there are multiple paths from A to C for instance (via B and also via B-F-E), and the query returns the last node of every path as variable v. (It doesn't actually process all possible paths up to the maximum depth of 10, but you could set the traversal option OPTIONS {uniqueEdges: "none"} to do so.)
It can help to return formatted traversal paths to better understand what is going on (i.e. how nodes are reached):
FOR v, e, p IN 1..10 ANY "node/A" links OPTIONS {uniqueEdges: "path"}
RETURN CONCAT_SEPARATOR(" - ", p.vertices[*]._key)
Result:
[
"A - B",
"A - B - C",
"A - B - C - D",
"A - B - C - E",
"A - B - C - E - F",
"A - B - C - E - F - B",
"A - B - F",
"A - B - F - E",
"A - B - F - E - C",
"A - B - F - E - C - D",
"A - B - F - E - C - B"
]
There is a cycle in the graph, but there can't be an infinite loop because the maximum depth is exceeded after 10 hops. But as you can see above, it doesn't even reach the depth of 10, it rather stops because the (default) option is to not follow edges twice per path (uniqueEdges: "path").
Anyway, this is not the desired result. A cheap trick would be to use RETURN DISTINCT, COLLECT or something like that to remove duplicates. But we are better off tweaking the traversal options, to not follow edges unnecessarily.
uniqueEdges: "global" would still include the B node twice, but uniqueVertices: "global" gives the desired result. In addition, bfs: true for breadth-first search can be used in this case. The difference is that the path to the F node is shorter (A-B-F instead of A-B-C-E-F). In general, the exact options you should use largely depend on the dataset and the questions you have.
There's one more problem to solve: the traversal does not include the start vertex (other than in p.vertices[0] for every path). This can easily be solved using ArangoDB 3.0 or later by setting the minimum depth to 0:
FOR v IN 0..10 ANY "node/A" links OPTIONS {uniqueVertices: "global"}
RETURN v._key
[ "A", "B", "C", "D", "E", "F" ]
To verify that all nodes from A through F are returned, regardless of the start vertex, we can issue the following test query:
FOR doc IN node
RETURN (
FOR v IN 0..10 ANY doc links OPTIONS {uniqueVertices: "global"}
SORT v._key
RETURN v._key
)
All sub-arrays should look the same. Remove the SORT operation if you want the node names returned in traversal order. Hope this helps =)

Resources