-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfastcom.py
executable file
·155 lines (137 loc) · 5.17 KB
/
fastcom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python
###############################################################################
#
# fastcom.py - Wrapper to run FastCommunity and get resulting communities
#
# File: fastcom.py
# Author: Alex Stivala
# Created: December 2007
#
# $Id: fastcom.py 1729 2008-07-22 07:13:09Z astivala $
#
# Usage: fastcom.py [pairsfile]
#
# pairsfile is the input .pairs file describing the graph in terms
# of (one per line) tab-delimited pairs of node numbers (from 0)
# indicating undirected edges, as described in the FastCommunity
# documentation (see website below).
# If not specified, then input is from stdin
#
# Output is to stdout.
#
# This is a wrapper around the FastCommunityFH program from Aaron Clauset
# that hides the necessity to run it twice, the first time to get the step
# number with max modularity and second to actually get the groups.
#
# FastCommunity is available from
#
# http://cs.unm.edu/~aaron/research/fastmodularity.htm
#
# where the usage and file formats are also described.
# The relevant publication to cite is
#
# A. Clauset, M.E.J. Newman and C. Moore, "Finding community structure
# in very large networks." Phys. Rev. E 70, 066111 (2004).
#
###############################################################################
import warnings # so we can suppress the annoying tempnam 'security' warning
import sys,os,glob
import getopt
#-----------------------------------------------------------------------------
#
# Constants
#
#-----------------------------------------------------------------------------
FASTCOMMUNITY = "FastCommunityMH" # binary to run (in PATH)
#-----------------------------------------------------------------------------
#
# Functions
#
#-----------------------------------------------------------------------------
def cleanup_tmpdir(tmpdir):
"""
Remove a temporary directory and its contents
Parameters:
tmpdir - temporary directory to remove
Return value: None
"""
try:
for filename in glob.glob(os.path.join(tmpdir, "*")):
os.remove(filename)
os.rmdir(tmpdir)
except OSError, inst:
sys.stderr.write('WARNING: could not remove temp files'
' in ' + tmpdir + '\n' + str(inst) + '\n')
def usage(progname):
"""
Print usage message and exit
"""
sys.stderr.write("Usage: " + progname + " <pairsfile>\n")
sys.exit(1)
#-----------------------------------------------------------------------------
#
# Main
#
#-----------------------------------------------------------------------------
def main():
"""
main for fastcom.py
"""
if len(sys.argv) > 2:
usage(os.path.basename(sys.argv[0]))
elif len(sys.argv) == 2:
pairsfilename = sys.argv[1]
use_stdin = False
else:
use_stdin = True
# We need to make a temp directory to work in,
# as FastCommunityMH insists on putting all
# work files in directory of input file (-o option although documented
# is not in code).
# If input is a file then symlink to it (note, must end in .pairs)
# else write our stdin to a file (ending with .pairs)
TMPDIR = os.tempnam(None, "fc")
os.mkdir(TMPDIR)
os.chdir(TMPDIR)
try:
oldcwd = os.getcwd()
if use_stdin:
pairsfile_basename = 'mystdin.pairs'
(pairsfile_prefix, suffix) = os.path.splitext(pairsfile_basename)
fh = open(pairsfile_basename, 'w')
for line in sys.stdin:
fh.write(line)
fh.close()
else:
pairsfile_basename = os.path.basename(pairsfilename)
(pairsfile_prefix, suffix) = os.path.splitext(pairsfile_basename)
symlink_path = os.path.join(TMPDIR, pairsfile_basename)
os.symlink(os.path.abspath(pairsfilename), symlink_path)
firstlabel = "first" # label for first run
secondlabel = "second" # and for second run
# Run FastCommunity the first time to .info file and to get max Q step
os.system(FASTCOMMUNITY + " -f " + pairsfile_basename +
" -l " + firstlabel + " >/dev/null")
info_filename = pairsfile_prefix + "-fc_" + firstlabel + ".info"
for line in open(info_filename):
if line[:11] == "STEP------:":
step = int(line.split()[1])
break
# Now we have the max Q step, use it on the -c option on second run
os.system(FASTCOMMUNITY + " -f " + pairsfile_basename +
" -l " + secondlabel + " -c " + str(step) + " >/dev/null")
groups_filename = pairsfile_prefix + "-fc_" + secondlabel + ".groups"
# and just output the groups file to stdout as the result
for line in open(groups_filename):
sys.stdout.write(line)
finally:
if not use_stdin:
os.unlink(symlink_path)
os.chdir(oldcwd)
cleanup_tmpdir(TMPDIR)
if __name__ == "__main__":
# tmpdir() annoyingly gives 'security' warning on stderr, as does
# tmpnam(), unless we add these filterwarnings() calls.
warnings.filterwarnings('ignore', 'tempdir', RuntimeWarning)
warnings.filterwarnings('ignore', 'tempnam', RuntimeWarning)
main()