Error on first query
lix2k3 opened this issue · 9 comments
Tried to run the query from the tutorial:
motif = Motif("""
# My Awesome Motif
Nose_Cell -> Brain_Cell
Brain_Cell -> Arm_Cell
""")
But got this error:
FileNotFoundError Traceback (most recent call last)
<ipython-input-1-3a88159c0a0c> in <module>
----> 1 import dotmotif
2 import networkx
3
4 motif = Motif("""
5 # My Awesome Motif
~\anaconda3\lib\site-packages\dotmotif\__init__.py in <module>
24 from networkx.algorithms import isomorphism
25
---> 26 from .parsers.v2 import ParserV2
27 from .validators import DisagreeingEdgesValidator
28
~\anaconda3\lib\site-packages\dotmotif\parsers\v2\__init__.py in <module>
11
12
---> 13 dm_parser = Lark(open(os.path.join(os.path.dirname(__file__), "grammar.lark"), "r"))
14
15
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\xxxx\\anaconda3\\lib\\site-packages\\dotmotif\\parsers\\v2\\grammar.lark'
I copy and fasted the lark file and tried to run this:
from dotmotif import Motif, NetworkXExecutor
import networkx as nx
G=nx.random_regular_graph(6 ,10, seed=None)
E = NetworkXExecutor(graph=G)
motif = Motif("""
# My Awesome Motif
A -> B
""")
# Get the number of edges in this graph
results = E.count(motif)
This error occurs:
AttributeError Traceback (most recent call last)
<ipython-input-21-41a0647ff749> in <module>
18
19 # Get the number of edges in this graph
---> 20 results = E.count(motif)
~\anaconda3\envs\virt 1\lib\site-packages\dotmotif\executors\NetworkXExecutor.py in count(self, motif, limit)
189 See NetworkXExecutor#find for more documentation.
190 """
--> 191 return len(self.find(motif, limit))
192
193 def find(self, motif: "dotmotif", limit: int = None):
~\anaconda3\envs\virt 1\lib\site-packages\dotmotif\executors\NetworkXExecutor.py in find(self, motif, limit)
230 return True
231
--> 232 unfiltered_results = [
233 # Here, `mapping` has keys of self.graph node IDs and values of
234 # motif node names. We need the reverse for pretty much everything
~\anaconda3\envs\virt 1\lib\site-packages\dotmotif\executors\NetworkXExecutor.py in <listcomp>(.0)
230 return True
231
--> 232 unfiltered_results = [
233 # Here, `mapping` has keys of self.graph node IDs and values of
234 # motif node names. We need the reverse for pretty much everything
~\anaconda3\envs\virt 1\lib\site-packages\networkx\algorithms\isomorphism\isomorphvf2.py in subgraph_monomorphisms_iter(self)
389 self.test = "mono"
390 self.initialize()
--> 391 yield from self.match()
392
393 # subgraph_isomorphisms_iter.__doc__ += "\n" + subgraph.replace('\n','\n'+indent)
~\anaconda3\envs\virt 1\lib\site-packages\networkx\algorithms\isomorphism\isomorphvf2.py in match(self)
311 for G1_node, G2_node in self.candidate_pairs_iter():
312 if self.syntactic_feasibility(G1_node, G2_node):
--> 313 if self.semantic_feasibility(G1_node, G2_node):
314 # Recursive call, adding the feasible state.
315 newstate = self.state.__class__(self, G1_node, G2_node)
~\anaconda3\envs\virt 1\lib\site-packages\networkx\algorithms\isomorphism\vf2userfunc.py in semantic_feasibility(self, G1_node, G2_node)
175
176 # Test edge_match on predecessors
--> 177 self.G1_adj = self.G1.pred
178 self.G2_adj = self.G2.pred
179 feasible = _semantic_feasibility(self, G1_node, G2_node)
AttributeError: 'Graph' object has no attribute 'pred'
Thank you so much for reporting! Let me check into this and I will get back to you with some potential debug steps. Unfortunately it looks like I didn't work out all the kinks in the windows installation!
@lix2k3 Your second issue looks like it's possibly because you're searching for a directed motif in an undirected host graph (my understanding is that nx.random_regular_graph
creates an undirected graph).
You may be able to fix this by adding the ignore_direction
flag to the motif constructor:
from dotmotif import Motif, NetworkXExecutor
import networkx as nx
# Create the UNDIRECTED host graph:
G = nx.random_regular_graph(6, 10, seed=None)
# Create the executor:
E = NetworkXExecutor(graph=G)
# Construct the motif.
# * This motif has only one (directed) edge
# * We set ignore_direction to True in order
# to search for _any_ edge in the host graph
motif = Motif("""
A -> B
""", ignore_direction=True)
# Get the number of edges in this graph
results = E.count(motif)
Note that this will double-count undirected edges (so in your 30-edge graph G
, this will return 60).
The most straightforward way to forbid these double-counts is to just add the reverse edge as well:
A -> B
B -> A
I'll keep on working on your first installation issue. Really appreciate you filing the report!
Please let me know if you run into any other problems/questions! Would be happy to walk through some motifs with you :)
ignore_direction = TRUE
worked like a charm.
Thanks a lot! I'm up and running now and this is quite an awesome library you have here. The language is elegant and love the macros feature. Excited to work with it and see it grow!
I'm so excited to hear that! 😀
btw, I noticed you're using the NetworkX executor. If you're willing to install another Python package, I'd definitely recommend using the GrandIsoExecutor
where possible. It's dramatically faster (i.e. minutes vs days) and uses much less RAM, and is still compatible with NetworkX.Graph objects (i.e. it's a drop-in replacement). In fact, if you're just looking at counts for now, it's a huge performance improvement (because in this case, grandiso just keeps track of count, rather than holding onto all mapping results).
https://github.com/aplbrain/grandiso-networkx
pip install grandiso
# This example is exactly the same, but NetworkXExecutor
# has been replaced with GrandIsoExecutor:
from dotmotif import Motif, GrandIsoExecutor
import networkx as nx
# Create the UNDIRECTED host graph:
G = nx.random_regular_graph(6, 10, seed=None)
# Create the executor:
E = GrandIsoExecutor(graph=G)
# Construct the motif.
# * This motif has only one (directed) edge
# * We set ignore_direction to True in order
# to search for _any_ edge in the host graph
motif = Motif("""
A -> B
""", ignore_direction=True)
# Get the number of edges in this graph
results = E.count(motif)
Super curious to hear about your experiences / feature-requests / issues :)
Awesome to hear that regarding the performance of the GrandIsoExecutor. Will install shortly.
Right now, I am looking for ways to create random network ensembles (1000 random networks) and test the occurrence of motifs in both the real/observed network and the random networks. I am looking to compare the statistic in the observed network (# of motifs) to the random networks (average, std of motif count) to test for significance (z-scores, etc.).
Also, I am trying to obtain to complex measures of the motifs (motif intensity, motif coherence, clustering coefficient, participation coefficient) of all the found motifs in the undirected network. These measures are all mentioned in Letina et al (2019). DotMotif makes this all possible in an elegant syntax. But, of course, I will have to roll up my own functions to fully make this work. I'm a Phd student in psychology rather than a programmer, so it will take me some time. This is the only package that I think can get me what I'm looking for with minimal fuss :)
As far as feature requests, anything that can get me closer to the above is much appreciated. But, the fact that this even exists is a game-changer for me.
Letina, S., Blanken, T. F., Deserno, M. K., & Borsboom, D. (2019). Expanding network analysis tools in psychological networks: Minimal spanning trees, participation coefficients, and motif analysis applied to a network of 26 psychological attributes. Complexity, 2019.
This is a very cool use-case! I'm so glad DotMotif is helpful to you here! I'll keep those graph measures in the back of my mind, I've been considering adding some sort of metrics output as well, though it can add substantially to the runtime for larger graphs... :)
Great, thanks!
Just pushed a change that should fix this installation error as well — please do reach out if you encounter any more issues or just want to chat more about motif search :)