aplbrain/dotmotif

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 :)