I'm a first-year medical student and I'd like to use Graphviz to create an easy-to-interpret graph of human anatomy structures and their functional relationships. In particular, I'd like to create a graph with about 50 muscles, 50 nerves, 50 arteries, 80 bones and bony processes, the proximal and distal points of attachments for muscles onto bony processes, which nerves innervate which muscles, which arteries perfuse which muscles, et. al.
For a comprehensive image representing all of these structures and all of their relationships (which will be very complex, I know) I think a graph is probably the best way to represent these structures and their functional relationships, and Graphviz seems like good software for making such graphs, but there are different types of edges that connect structures. For example, based strictly upon macroscopic observation of gross structures, it appears that the axillary nerve derives from the posterior cord of the brachial plexus (BP) which contains fibers from the upper, middle, and lower trunks of the BP, and these three trunks contain nerve fibers from each of the anterior rami originating in spinal nerves C5, C6, C7, C8, and T1. However, despite physical appearances, the electrical connectivity of the axillary nerve is such that it actually contains nerve fibers originating in the anterior rami of only spinal nerves C5 and C6 (see image and I should explain here that all nerve fibers from all spinal nerves are the same color in the actual gross anatomy, so try to imagine the image with no colors to get an idea about the physical connections versus the electrical connections as shown in colors). So to make an accurate representation of the physical connectivity and the electrical connectivity for the axillary nerve and all the upstream nerve fibers that it derives from, I'll need at least two different types of edges: "physical" edges and "electrical" edges. I think Graphviz can do that kind of thing, but I'm new to using Graphviz and am unsure about the best way to accomplish that (although this is not my main question here).
I'll also need to find a way to represent relationships such as those depicted above where nerve fibers pass through multiple structures on their way to named nerves downstream of those structures. For example, in the image above, color is used to show one continuous set of nerve fibers originating in C6 (blue) and winding their way to all of the following structures: "Nerve to subclavius", "Upper Trunk", "Lateral Cord", "Median Nerve", "Lateral Pectoral nerve", "Axillary nerve", and "Radial Nerve".
I've tried to represent some of that with Graphviz as in the following image.
that I created with lines of DOT language code like the following (this is an incomplete code snippet; not the entire DOT file I used to create that image):
snc05 -- bput -- bplc -- mn[color="#ffde17",penwidth=3];
snc06 -- bput -- bplc -- mn[color="#0056e0",penwidth=3];
snc07 -- bpmt -- bplc -- mn[color="#ff6f00",penwidth=3];
snc08 -- bplt -- bpmc -- mn[color="#be1e2d",penwidth=3];
snt01 -- bplt -- bpmc -- mn[color="#00a651",penwidth=3];
snc05 -- bput -- bppc -- rn[color="#ffde17",penwidth=3];
snc06 -- bput -- bppc -- rn[color="#0056e0",penwidth=3];
snc07 -- bpmt -- bppc -- rn[color="#ff6f00",penwidth=3];
snc08 -- bplt -- bppc -- rn[color="#be1e2d",penwidth=3];
snt01 -- bplt -- bppc -- rn[color="#00a651",penwidth=3];
But the main problem with this representation is that there are multiple blue edges between C6 and the brachial plexus upper trunk and there are multiple yellow edges between C5 and the brachial plexus upper trunk and there are multiple orange edges between C7 and the brachial plexus middle trunk and there are multiple orange edges between the brachial plexus middle trunk and the brachial plexus lateral cord.
I know why there are multiple edges of the same color as in the paragraph above. I explicitly created them in the DOT file. And for the logic to be correct (I may eventually parse this DOT file with python or something), I do actually want the DOT file to contain those multiple edges of the same color. But I don't want to see the multiple edges of the same color in the rendered image.
So my main question is: how do I get Graphviz to suppress the rendering of the 5 blue edges between C6 and upper (superior) trunk and render them instead as just 1 blue edge?
A secondary question is: how do I force Graphviz to render edges that are different colors in such a way that they do not overlap each other so each differently-colored edge remains distinct over the entire range (from originating node to adjacent node)? The best example of this being a problem in the image above can be seen in the two (blue and yellow) edges connecting upper (superior) trunk with posterior cord. Although the blue and yellow edges are distinct near the two nodes, in the middle of their span, they are overlapping so completely that it is difficult to see that there are two edges there; the blue almost completely obscures the yellow. I'd like to find a general way to force Graphviz to make the blue and yellow edges not overlap each other at all (I would not want to have to check the image visually and correct the DOT file, but rather, find some way of telling Graphviz not to allow edges to overlap at all, unless perhaps they are the same color).
The previous Graphviz image begins to show why this question is important to me, but having now worked on this for longer, the image below shows it even better. Things get so messy that it becomes difficult to interpret.
#Simon thanks for explaining (in your comment below) about GNU head. head on OS X behaves differently, so I used your sed script and that removed my first problem. However, I think your removeDupEdge script may be causing other problems with my .gv file.
To demonstrate, I'll start with your example multiEdge.gv file. Making some slight changes, I have:
graph {
node [style=filled];
a [label="a1",fillcolor=green]
b [label="b1",fillcolor=purple]
c [label="c1"]
d [label="d1"]
e [label="e1"]
a -- b -- c[color = blue];
a -- b -- c -- d[color = red];
a -- c;
a -- b -- c -- d -- e[color = blue];
}
Your removeDupEdge script seems to handle the two-trait lines above badly:
$ ./removeDupEdge <multiEdge.gv
graph {
node [label="\N",
label=a1];
label=b1];
style=filled
];
a [fillcolor=green,
a -- b [color=blue];
a -- b [color=red];
a -- c;
b [fillcolor=purple,
b -- c [color=blue];
b -- c [color=red];
c [label=c1];
c -- d [color=blue];
c -- d [color=red];
d [label=d1];
d -- e [color=blue];
e [label=e1];
}
And I think this is no longer valid DOT language code. Your removeDupEdge script looks very promising to me, but I'm not sure how to fix it for the example I showed above. My .gv file is more than 700 lines, and I also use the C++-style comments allowed in the DOT language documentation. I'm not sure if comments might create problems for your removeDupEdge script too.
(Heavily edited to make the process robust to multi-attribute nodes and edges)
With respect to the first question, GraphViz, grouping the same edges shows that using the strict keyword stops graphviz from displaying multiple edges between nodes. However, that does not let it display one edge for each color between two nodes. The best way to do that, as far as I can see, would be to process the graphviz file and then display it.
For example, given multiEdge.gv:
graph {
node [style=filled];
a [label="a1",fillcolor=green]
b [label="b1",fillcolor=purple]
c [label="c1"]
d [label="d1"]
e [label="e1"]
a -- b -- c[color = blue];
a -- b -- c -- d[color = red];
a -- c;
a -- b -- c -- d -- e[color = blue];
}
... which looks like this:
... we can process it with the following removeDupEdge script:
#!/bin/sh
neato -Tcanon | perl -p -e 's/,\n/,/' >tmp.tmp
head -3 tmp.tmp >header.tmp
tail -1 tmp.tmp >tail.tmp
tail -n +4 tmp.tmp | sed -n '$ !p' | sort | uniq | cat header.tmp - tail.tmp
... which first produces a version of the script in canonical form, in which each edge goes between two nodes only. Unfortunately, canonical form also puts multi-attribute node and element attribute lists on multiple lines ending in commas so the next part of the script uses perl to re-join all lines that end in commas (thanks to an answer to How can you combine all lines that end with a backslash character?). The script then saves the top three lines and the bottom line of the canonical form as a header and footer respectively, before taking all but the header and footer lines, sorting them, keeping only the unique lines and then concatenating the header and footer back to form a legal xdot file. The result is as follows:
$ removeDupEdge <multiEdge.gv
graph {
node [label="\N", style=filled
];
a -- b [color=blue];
a -- b [color=red];
a -- c;
a [fillcolor=green, label=a1];
b -- c [color=blue];
b -- c [color=red];
b [fillcolor=purple, label=b1];
c -- d [color=blue];
c -- d [color=red];
c [label=c1];
d -- e [color=blue];
d [label=d1];
e [label=e1];
}
We can then display it with:
$ removeDupEdge <multiEdge.gv | neato -Tpng -omultiEdge.png
... to get:
... which only shows one copy of each identical edge.
The script could be made a bit more robust by inserting sed 's/ */ /g' before the sort, because that would remove non-significant spaces from the xdot file before sorting and comparing the lines. However, it would also remove multiple spaces from (say) node labels, which might not be desirable.
Regarding comments in the original xdot source, that will not cause a problem because they are removed by the canonicalization process.
Related
I'm currently developing a multi-level SSRS report, and I'm struggling with the algorithm. I've developed a recursion class which looks like below, but the level numbers are incorrect. I want the parent record (represented by a, b, and c) to show the child records so that the child records' level = (parentRecLevel+1). Right now, the level values just increment by 1. Anyone have any advice?
protected BOMLevel getBomLevelItem(str itemId, int numLevel, boolean firstRec)
while select tmpBOM
{
bomLevel = this.getBomLevelItem(bomLevel.ItemId, bomLevel.Level, false);
}
Current Outcome (where b1, c1, and c2 are children of b and c respectively):
1 a
2 b
2 b1
3 c
4 c1
5 c2
Wanted Outcome:
1 a
2 b
3 b1
2 c
3 c1
3 c2
TLDR: Do not reinvent the wheel, use existing algorithms and frameworks.
I'm assuming your question is not for a training exercise, but a real world problem. If it is an exercise, try to get a good grasp of recursion in an easy to use language of your choice with a big community before coming back to x++.
Your recursion method looks incomplete, because in each recursion, you iterate through all records of tmpBom, which (unless you modify the records in that table somewhere else) does not make sense and will never terminate. I also don't see how this method could produce the outcome you describe. I suggest you take a look at some recursion algorithm training material to learn about the fundamental parts of a recursion.
You tagged the question x++ and the syntax also looks very much like that. Unfortunately you did not add the information which version of microsoft-dynamics you are using, but I will assume dynamics-ax-2012 as it is currently the most common version in use.
In this version, there is already an out-of-the-box SSRS report that will show you the structure of a bill of material. You can call the report at Inventory management > Reports > Bills of materials > Lines. It should be fairly easy to modify this report so that it also shows the level if the report does not already fulfill your requirements.
If you still need to implement your own solution, take a look at class BOMSearch and its children. It is used in several places (check the cross references) and can also used to expand/explode a bill of material.
Also note that there are a lot of articles out there that try to explain how to expand or explode a bill of material in x++ code, but as with all things on the internet, be careful: Most of them are incomplete or plain wrong.
I am given the above system for atomic propositions {a,b,c}.
I'm then meant to say if certain LTL formulae hold (such as ♢☐c).
I understand what the LTL formulae mean (eventually forever c holds) but I have no idea how to read the diagram and relate it to the LTL.
I assume it's like a flow chart in that we start from the top left, /{a} and can go through the different states. But what does each of it mean divided by a?
Looks like FSM/transduser rather than a Kripke structure. Input/output or more generally precondition/postcondition is a common notation for FSM and its kin. precondition/postcondition (a and b and ...) / (x and y and...). So a in the state q1. In next states either only b in q4 or b and c or q3. Might be of course or instead of and in precondition, otherwise the system might halt..
I'm doing a self-educational research on finite state machines. And currently stumbled upon interesting but non-trivial task to accomplish. It is really hard to define state machine for the rules of game of chess.
Though the rules seem simple the game itself is hard to approach using FSM. I was thinking about encoding game state as a state of board, where each square is either empty or contains some piece. But it becomes hard to define transitions, because the transition should be aware of facts that concern the neighborhood of the subject cell. It is also hard to define transitions for cases like en-passant or castling, especially when castling is blocked by some other piece. The same way it is hard to define move limitations for pieces that are blocked by other pieces and are not capable to jump them, i.e. pawns, bishops, rooks, queens.
How would you approach this problem? Or maybe there are some extensions to FSM that I'm not aware of. I'm pretty sure that there are a lot of similar applications where FSM will be impractical to use. How would you deal with this problem in general case.
Thank you in advance,
In your approach each state would be a matrix of fields, where each field has a specific state, which is a composition of the color and the chess piece that is placed on it and chess pieces themselves are a composition of the color of the chess-piece and it's type (pawn, rook, etc.). So you can easily define rules by utilizing these matrices:
Example for pawn:
Initial state:
C D E
5 (W , (X , ?)) (B , (P , B)) (W , (P , B))
4 (B , (P , W)) (W , (X , ?)) (B , (P , W))
Now we can evalute rules for moving the two white figures based on this rule:
A pawn can move straight forward, if it's not blocked by another figure, or it can beat the figure that is placed diagonally one block away from it. Building the transition-table for the above state with a white move next can be done in the following way:
S1->(a)X (just the standard way to define a transition)
a would be the figure, we want to move and S2 the resulting state
X are the reachable state.
a = Pawn at C4
we have two options evaluating the field:
C5 is free, so we can move the pawn to that field
D5 is held by a black pawn, so we can beat it and move to that field
a = Pawn at E4
E5 not free, we can't move ahead
D5 is held by a black pawn, which we can beat
Translating this into math shouldn't be too hard. The state transition-table for each state would include all possible moves for all figures. The resulting machine would be a NFA.
Another option would be to define transitions as a pair of the chess piece you want to move and where you want to move it. That'd allow you to construct a DFA.
I am writing a program that repeatedly renders many small graphs (50-100) using dot. It does this by calling dot. Unfortunately this process is really slow. When I look at the activity monitor, I saw that fontd was consuming nearly all of the process time. It appears that this is due to some kind of font enumeration.
Given that I'm using the SVG backend, is there any way to speed up the rendering of many graphs?
I don't believe I can do all of the graphs in one render as they must all be embedded into an automatically generated HTML page.
The following example script takes 30 seconds to run on my 2.2 GHz Core i7 (2011 MacBook Pro)
#!/bin/bash
for i in {1..100}
do
dot -o tmp.svg -Tsvg <<Limit
digraph g {
a1 -> a2;
}
Limit
done
Rendering a single graph such as the following (97 edges not shown) takes 0.3 seconds.
digraph g {
a1 -> a2;
a3 -> a4;
...
a199 -> a200;
}
I'm trying to solve the following problem:
I'm analyzing an image and I obtain from this analysis a set of segments
I want to know the intersection of these lines (best fit)
I'm using for this opencv's function cvSolve. For reasonably good input everything works fine.
The problem that I have comes from the fact that when I have just a single bad segment as input the result is different from the one expected.
Details:
Upper left image show the "lonely" purple lines influencing the result (all lines are used as input).
Upper right image shows how a single purple line (one removed) can influence the result.
Lower left image show what we want - the intersection of lines as expected (both purple lines eliminated).
Lower right image show how the other purple line (the other is removed) can influence the result.
As you can see only two lines and the result is completely different from the one expected. Any ideas on how to avoid this are appreciated.
Thanks,
Iulian
The algorithm you are using finds, as described in the link, the least square error solution to the problem. This means that if there are more intersection points, the result will be an average (for a reasonable definition of average) of the real solutions.
I would try an iterative solution: if the error of the first solution is too large, remove from the set of segments the one farthest to the solution, and iterate until the error is acceptably small. This should remove one of the many intersection point, and converge on the one with most lines nearby.
A general answer to this kind of problems is the RANSAC algorithm (question dealing with this), however it has a few disadvantages, for example you need to estimate things like "the expected number of outliers" beforehand. Another Problem I see with your sample is that removing the two green lines also results in a pretty good fit, so that might be a more general problem.
you can solve using SVD incase line1 =(x1,y1)-(x2,y2) ; line2 =(x2,y2)-(x3,y3)
let Ax = b where;
A = [-(y2-y1) (x2-x1);
-(y3-y2) (x3-x2);
.................
.................] -->(nx2)
x = transpose[s t] -->(2x1)
b = [-(y2-y1)x1 + (x2-x1)y1 ;
-(y3-y2)x2 + (x3-x2)y2 ;
........................
........................] --> (nx1)
Example; Matlab Code
line1=[0,10;5,10]
line2=[10,0;10,5]
line3=[0,0;5,5]
A=[-(line1(2,2)-line1(1,2)),(line1(2,1)-line1(1,1));
-(line2(2,2)-line2(1,2)),(line2(2,1)-line2(1,1));
-(line3(2,2)-line3(1,2)),(line3(2,1)-line3(1,1))];
b=[(line1(1,1)*A(1,1))+ (line1(1,2)*A(1,2));
(line2(1,1)*A(2,1))+ (line2(1,2)*A(2,2));
(line3(1,1)*A(3,1))+ (line3(1,2)*A(3,2))];
[U D V] = svd(A)
bprime = U'*b
y=[bprime(1)/D(1,1);bprime(2)/D(2,2)]
x=V*y