Here is MCVE in PlantUML:
#startuml
'Define the components
[Main component] as c_main_component
[comp1] as c_comp1
[com2] as c_comp2
[comp3] as c_comp3
[comp4] as c_comp4
'Define the relationships
c_main_component -- c_comp3
c_main_component -- c_comp4
c_main_component - c_comp2
c_main_component - c_comp1
#enduml
The above results in the below image:
As one can see, comp3 and comp4 have a nice a diagonal lines connecting it to Main component from the bottom, just like expected. I want comp1 and comp2 have the same nice diagonal lines to connect to Main component from the right side. How can I do it?
The code as generated by PlantUML with the option -debugsvek:
digraph unix {
nodesep=0.486111;
ranksep=0.833333;
remincross=true;
searchsize=500;
sh0004->sh0006[arrowtail=none,arrowhead=none,minlen=0,color="#000011"];
sh0004->sh0005[arrowtail=none,arrowhead=none,minlen=0,color="#000015"];
sh0004 [shape=rect,label="",width=1.722222,height=0.522352,color="#000004"];
sh0005 [shape=rect,label="",width=0.861111,height=0.522352,color="#000005"];
sh0006 [shape=rect,label="",width=0.750000,height=0.522352,color="#000006"];
sh0007 [shape=rect,label="",width=0.861111,height=0.522352,color="#000007"];
sh0008 [shape=rect,label="",width=0.861111,height=0.522352,color="#000008"];
sh0004->sh0007[arrowtail=none,arrowhead=none,minlen=1,color="#000009"];
sh0004->sh0008[arrowtail=none,arrowhead=none,minlen=1,color="#00000D"];
}
Why are you using for c_comp1 and comp2 a single dash ('-') and for c_comp3 and c_comp4 a double dash ('--')?
When using for all a double dash like:
#startuml
'Define the components
[Main component] as c_main_component
[comp1] as c_comp1
[com2] as c_comp2
[comp3] as c_comp3
[comp4] as c_comp4
'Define the relationships
c_main_component -- c_comp3
c_main_component -- c_comp4
c_main_component -- c_comp2
c_main_component -- c_comp1
#enduml
You will get a nicer image:
I did some fiddling around and although I don't directly see it usable in this case I still think it might give some points to start.
I found this article: How to force node position (x and y) in graphviz
Based on this I modified the resulting "debugsvek file" (cc_svek.dot) to (and made some coordinates a bit different for easier calculations by head and added some labels):
digraph unix {
nodesep=0.5;
ranksep=1;
remincross=true;
searchsize=500;
sh0004->sh0006[arrowtail=none,arrowhead=none,minlen=0,color="#000011"];
sh0004->sh0005[arrowtail=none,arrowhead=none,minlen=0,color="#000015"];
sh0004 [pos="1,-1!",shape=rect,label="4",width=1,height=0.5,color="#000004"];
sh0005 [pos="2,-0.75!",shape=rect,label="5",width=1,height=0.5,color="#000005"];
sh0006 [pos="2,-1.25!",shape=rect,label="6",width=1,height=0.5,color="#000006"];
sh0007 [pos="0,-2!",shape=rect,label="7",width=1,height=0.5,color="#000007"];
sh0008 [pos="1,-2!",shape=rect,label="8",width=1,height=0.5,color="#000008"];
sh0004->sh0007[arrowtail=none,arrowhead=none,minlen=1,color="#000009"];
sh0004->sh0008[arrowtail=none,arrowhead=none,minlen=1,color="#00000D"];
}
When using the command dot -K fdp -T png cc_svek.dot on it this results in the image:
Related
I'm trying to learn East Model for text recognition, I want to input different images to the code each time and trying argparse but is stuck.
How do we pass image path to (ap.add_argument("-i", '--image', type=str)
path is C:\Users\nishant\Desktop\Use_case\screenshot\hqdefault.png
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-i", '--image', type=str)
ap.add_argument("-east", "--east", type=str)
ap.add_argument("-c", "--min-confidence", type=float, default=0.5,)
ap.add_argument("-w", "--width", type=int, default=320)
ap.add_argument("-e", "--height", type=int, default=320)
ap.add_argument("-p", "--padding", type=float, default=0.0)
args = vars(ap.parse_args())
usage: ipykernel_launcher.py [-h] [-i IMAGE] [-east EAST] [-c MIN_CONFIDENCE]
[-w WIDTH] [-e HEIGHT] [-p PADDING]
ipykernel_launcher.py: error: unrecognized arguments: -f C:\Users\777569\AppData\Roaming\jupyter\runtime\kernel-a0ced498-94e0-406e-9bf5-8f8c125ff96a.json
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
I fixed mine by changing the last line, like this:
args = vars(ap.parse_args()) to args = ap.parse_args(args=[])
If a simple query for a path between two nodes was made, say,
MATCH (m{name:'m'}), (n{name:'n'}),
path = (m)-[:SOME_EDGE*]->(n)
RETURN path
EDIT:
(example result)
...
segments: [
{
start: {
id: 1
labels: [lbl1, lbl2, ...],
properties: [p1, p2, ...]
}
end: { ... }
properties: { ... }
},
{
start: {
id: 1
labels: [lbl1, lbl2, ...] <--- duplicate
properties: [p1, p2, ...] <--- duplicate
}
},
...
]
the result generated contains many duplicates of properties/types/IDs of sames nodes/edges again and again, and this gets worse when there are cycles in the paths.
I googled and found that I could use projections like
return [node in nodes(path) | id(node)] as pathNodes,
[r in relationships(path) | id: id(r), type: type(r)] as rels
(Example result)
{
pathNodes: [1,2,3],
rels: {id:101,type:'SOME_EDGE'},{id:102,type:'SOME_EDGE'}
},
{
pathNodes: [1,2,1,3],
rels: ...
}, ...
But how to add nodes/relationships info (just once for one entity) to the result above?
Is there any way to get this done in a single query?
You need to collect paths, nodes and relationships into a distinct lists, and then make a maps based on them using apoc.map.setKey function:
MATCH path = (A)-[*]->(B)
UNWIND nodes(path) AS n
UNWIND relationships(path) AS r
WITH
collect(DISTINCT path) as paths,
collect(DISTINCT n) AS nodes,
collect(DISTINCT r) AS rels
RETURN
[p IN paths | {
nodes: [n IN nodes(p) | id(n)],
rels: [r IN relationships(p) | id(r)]
}] as paths,
reduce(acc={}, n IN nodes | apoc.map.setKey(acc, toString(id(n)), n)) as nodes,
reduce(acc={}, r IN rels | apoc.map.setKey(acc, toString(id(r)), r)) as rels
stdob-- was right about UNWIND and COLLECT and didn't really need to use APOC.
I came up with a solution by myself months ago and came here today so I chose his/her answer and also post my solution without APOC here.
UNWIND and re-COLLECT is the key
MATCH p=(m{name:'m'})-[:'SOME_EDGE'|:'SOME_OTHER_EDGE'*1..2]->(n{name:'n'})
WITH {
pathNodes: [node IN nodes(p) | ID(node)],
rels: [r IN RELATIONSHIPS(p) | {id:ID(r),ty:TYPE(r)}]
} AS path, p
UNWIND NODES(p) AS node
RETURN {paths:COLLECT(path), nodes: COLLECT(DISTINCT{id:ID(node),name:node.name})}
Inherit properties from all the parents.
Consider I have a graph with below format. I want the properties of a node (which will be in account node, if it has a relation) to be inherited by its child node. Assume Parent and child node relationship is maintained by [r:CHILD] and account information by [r2:ACCOUNT]. If node has more than one parent, it needs to inherit from all its parent with the first account :
(a0:ACCOUNT)<-[:HAS_ACCOUNT]-Morpheus
\
(a1:ACCOUNT)<-[:HAS_ACCOUNT]-Neo
\
alpha
\
gamma beta - [:HAS_ACCOUNT]->(a2:ACCOUNT)
\ /
A
/ \
(a3:ACCOUNT)<-[:HAS_ACCOUNT]-B C
/ \ / \
D E F G
I want to extract the data from the above graph something like this:
Problem: Given a node, get all its children and also its account (if it has account , e.g: see node B) or its inherited account information. AccountID is part of account node
Consider input is node A
OUTPUT:
|Node | CurrentNode| Account |Inherited_Account|
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | A | - | a1.accountID ,|
| | | | a2.accountID |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | B | a3.accountID | - |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | D | | a3.accountID |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | E | | a3.accountID |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | C | | a1.accountID ,|
| | | | a2.accountID |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | F | | a1.accountID ,|
| | | | a2.accountID |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
| A | G | | a1.accountID ,|
| | | | a2.accountID |
- - - - - -- - - - - -- - - - - -- - - - - -- - - - -
This was my cypher to retrive that I came up with, gets me all the accounts of all the parents. It doesnt work sometimes
MATCH (node:Person{personID:"A"})
MATCH (account:ACCOUNT)
MATCH p =(parent:Person)-[:CHILD*1..]->(node)
where (parent)-[:HAS_ACCOUNT]->(account)
UNWIND RELATIONSHIPS(p) AS rel
WITH p, account, COUNT(DISTINCT rel) AS nRoutes
RETURN account,p, nRoutes
ORDER BY nRoutes
This is a tricky one.
A pure Cypher solution exists, but it's a complicated query and requires some potentially heavy filtering to weed out paths to account-holding nodes that are beyond closer account-holding nodes along the same path.
However, I've found a better alternate using Cypher and APOC's path expander, plus some pre-processing of adding a label to nodes that are account holders.
APOC's path expander has a means of expanding while respecting a label filter, and there is a means to define a label which should prune any further traversal, but be included as a solution. We'll use this to limit our expansion when getting account-holding ancestors for nodes.
Here's a creation query to recreate the graph in your example (though I'm labeling non-ACCOUNT nodes as :Node):
// create inherited account graph
create (morpheus:Node{name:'Morpheus'})
create (neo:Node{name:'Neo'})
create (alpha:Node{name:'alpha'})
create (gamma:Node{name:'gamma'})
create (beta:Node{name:'beta'})
create (A:Node{name:'A'})
create (B:Node{name:'B'})
create (C:Node{name:'C'})
create (D:Node{name:'D'})
create (E:Node{name:'E'})
create (F:Node{name:'F'})
create (G:Node{name:'G'})
create (morpheus)-[:CHILD]->(neo)
create (neo)-[:CHILD]->(alpha)
create (alpha)-[:CHILD]->(gamma)
create (gamma)-[:CHILD]->(A)
create (beta)-[:CHILD]->(A)
create (A)-[:CHILD]->(B)
create (A)-[:CHILD]->(C)
create (B)-[:CHILD]->(D)
create (B)-[:CHILD]->(E)
create (C)-[:CHILD]->(F)
create (C)-[:CHILD]->(G)
create (morpheus)-[:HAS_ACCOUNT]->(a0:ACCOUNT{name:'a0'})
create (neo)-[:HAS_ACCOUNT]->(a1:ACCOUNT{name:'a1'})
create (beta)-[:HAS_ACCOUNT]->(a2:ACCOUNT{name:'a2'})
create (B)-[:HAS_ACCOUNT]->(a3:ACCOUNT{name:'a3'})
Next, we label account-holding nodes.
MATCH (acc:ACCOUNT)
WITH acc
MATCH (acc)<-[:HAS_ACCOUNT]-(holder)
SET holder:ACCOUNT_HOLDER
Once that's in place, we can use the following query to get your desired output:
// parameterize this in your own query
with 'A' as nodeName
match (node:Node{name:nodeName})-[r:CHILD*0..]->(currentNode)
with node, currentNode, size(r) as distance
optional match (currentNode)-[:HAS_ACCOUNT]->(acc)
with node, currentNode, distance, collect(acc) as accounts
// we now have all child nodes of the given node and their accounts, if they exist.
// this expands up from each currentNode,
// stopping each expansion at the closest ACCOUNT_HOLDER node
call apoc.path.expand(currentNode, '<CHILD', '/ACCOUNT_HOLDER', -1, -1)
yield path
with node, currentNode, distance, accounts, last(nodes(path)) as holder
// get the account for each holder,
// but only if the current doesn't have its own accounts
optional match (holder)-[:HAS_ACCOUNT]->(acc)
where size(accounts) = 0
with node, currentNode, accounts, collect(acc) as inherited, distance
order by distance asc
return node, currentNode, accounts, inherited
However, note that even with this approach, the query will not build up and reuse solutions (for example, once we've found the account-holding ancestors for node A, that solution is not referenced or reused when we have to get the account-holding ancestors for nodes, C, F, or G). You may want to consider a custom procedure to perform this complicated matching operation in code rather than Cypher for maximum efficiency.
I am newbie with SaltStack. I have an error in one of my first state files.
The state file is:
openvpn:
pkg.installed: []
/etc/openvpn:
file.recurse:
- source: salt://myvpn/openvpn-files
service.running: []
And the error: State 'openvpn' in SLS u'myvpn' is not formed as a list
Could you say me where is the fail?
I found the error. It can't define a state inside other state (/etc/openvpn: inside openvpn:)
I've fixed this way:
openvpn:
pkg.installed: []
file.recurse:
- name: /etc/openvpn
- source: salt://myvpn/openvpn-files
service.running: []
I'm tring to build an ontology to infer some informations about a domain classification and a terminology, but I'm experiencing some conceptual difficulties.
Let me explain the problem. In Protègè 4.1 i created 6 subclasses of Thing: Concept, conceptTitle, ConceptSynonym (for the classification) and Term, TermTitle, TermSynonym (for the terminology). I also have created hasConceptTitle, hasConceptSynonym, hasTermTitle and hasTermSynonym object relationships (with some constrint) to say that every Concept has one (and only one) title, and may have some synonyms, and every Term has one (and only one) title and some synonyms. Both Concept and Term have another relationship isA, giving to the classification a DAG/tree structure, while the terminology has a lattice structure (in other words, a term may be a subclass of more than one term).
Here comes the problem: I would like to create a subclass of Concept, let's say "MappedConcept"), which should be the set of mapped concepts, that is the set of concepts which have the title equals to a term's title, or it has a synonym equals to a term's title or has a synonym that is equal to a synonym of a term.
In the first-order logic, this set may be expressed as:
∀x∃y( ∃z((hasConceptTitle(x,z) ∧ hasTermTitle(y,z)) ∨
∃z((hasConceptTitle(x,z) ∧ hasTermSynonym(y,z)) ∨
∃z((hasConceptSynonym(x,z) ∧ hasTermTitle(y,z)) ∨
∃z((hasConceptSynonym(x,z) ∧ hasTermSynonym(y,z)) )
How can I obtain this? Defining data properties for "ConceptTitle", "ConceptSynonym", "TermTitle" and "TermSynonym"? And how to describe the string matches?
Maybe those 4 classes should be just data properties of Concept and Term classes?
I read the practical guide of Matthew Horridge several times, but I can't the practical ideas I have on my mind into an ongology in Protègè.
Thanks in advance.
I'm afraid you cannot do this in OWL 2 DL nor in Protégé, which is an editor for OWL 2 DL, because, as far as I can tell, it seems necessary to introduce the inverse of a datatype property, which is forbidden in OWL 2 DL. However, it's possible in OWL Full, and some DL reasoners may even be able to deal with it. Here, in Turtle:
<MappedConcept> a owl:Class;
owl:equivalentTo [
a owl:Class;
owl:unionOf (
[
a owl:Restriction;
owl:onProperty <hasConceptTitle>;
owl:someValuesFrom [
a owl:Restriction;
owl:onProperty [ owl:inverseOf <hasTermTitle> ];
owl:someValuesFrom <Term>
]
] [
a owl:Restriction;
owl:onProperty <hasConceptTitle>;
owl:someValuesFrom [
a owl:Restriction;
owl:onProperty [ owl:inverseOf <hasTermSynonym> ];
owl:someValuesFrom <Term>
]
] [
a owl:Restriction;
owl:onProperty <hasConceptSynonym>;
owl:someValuesFrom [
a owl:Restriction;
owl:onProperty [ owl:inverseOf <hasTermSynonym> ];
owl:someValuesFrom <Term>
]
] [
a owl:Restriction;
owl:onProperty <hasConceptSynonym>;
owl:someValuesFrom [
a owl:Restriction;
owl:onProperty [ owl:inverseOf <hasTermTitle> ];
owl:someValuesFrom <Term>
]
]
)
] .
You can also do it without OWL, with a rule language for instance. The rules would look closer to how you would do it in programming languages. In SWRL:
hasConceptTitle(?x,?z), hasTermTitle(?y,?z) -> MappedConcept(?x)
hasConceptTitle(?x,?z), hasTermSynonym(?y,?z) -> MappedConcept(?x)
hasConceptSynonym(?x,?z), hasTermTitle(?y,?z) -> MappedConcept(?x)
hasConceptSynonym(?x,?z), hasTermSynonym(?y,?z) -> MappedConcept(?x)