source: orange/orange/Orange/network/snap.py @ 9204:2c17bf220dc3

Revision 9204:2c17bf220dc3, 7.7 KB checked in by miha <miha.stajdohar@…>, 2 years ago (diff)

Moved Qt imports.

Line 
1"""
2.. index: Stanford Large Network Dataset Collection
3.. index:
4   single: network; Stanford Large Network Dataset Collection
5   
6*****************************************
7Stanford Large Network Dataset Collection
8*****************************************
9
10This module includes classes to access the `Stanford Large Network Dataset
11Collection <http://snap.stanford.edu/data/>`_ by `Jure Leskovec
12<http://cs.stanford.edu/~jure/>`_.
13
14.. autoclass:: Orange.network.snap.SNAP
15   :members:
16
17.. autoclass:: Orange.network.snap.NetworkInfo
18   :members:
19
20"""
21
22import os
23import os.path
24import urllib
25import httplib
26
27import Orange.misc
28import Orange.network
29
30from HTMLParser import HTMLParser
31
32class NetworkInfo(object):
33    """The NetworkInfo class provides information about a network on the SNAP
34    web site.
35   
36    .. attribute:: name
37   
38        The name of the network.
39   
40    .. attribute:: link
41   
42        The url address of the network file.
43   
44    .. attribute:: type
45   
46        Network type (directed, undirected).
47   
48    .. attribute:: nodes
49   
50        Number of nodes in the network.
51   
52    .. attribute:: edges
53   
54        Number of edges in the network.
55   
56    .. attribute:: repository
57   
58        The repository name (Social networks, Communication networks, ...).
59   
60    .. attribute:: description
61   
62        Detailed description of the network.
63   
64    """
65    def __init__(self, name='', link='', type='', nodes='', edges='', repository='', description=''):
66        self.name = name
67        self.link = link
68        self.type = type
69        self.nodes = nodes
70        self.edges = edges
71        self.repository = repository
72        self.description = description
73        self._root =  Orange.misc.environ.buffer_dir + "/snap/"
74        self._local_file = self._root + self.name + ".txt.gz"
75        self._remote_file = "http://snap.stanford.edu/data/" + self.name + ".txt.gz"
76       
77    def read(self, progress_callback=None):
78        """Read and return the network from file. Download the network to the
79        Orange home first if it was not jet downloaded.
80       
81        :param progress_callback: a callback method to update a progress bar
82        :type progress_callback: function(numblocks, blocksize, filesize)
83       
84        """
85       
86        if not self._is_downloaded():
87            self._download(progress_callback)
88       
89        return Orange.network.readwrite.read(self._local_file)
90   
91    def _is_downloaded(self):
92        if os.path.isfile(self._local_file):
93            return True
94        else:
95            return False
96       
97    def _download(self, progress_callback=None):
98        if not os.path.exists(self._root):
99            os.makedirs(self._root)
100           
101        urllib.urlretrieve(self._remote_file, self._local_file, progress_callback)
102
103class SNAPParser(HTMLParser):
104    def __init__(self, *args, **kwargs):
105        HTMLParser.__init__(self) 
106       
107        self.h3 = False
108        self.tr = False
109        self.td = False
110        self.title = ''
111        self.table = False
112        self.networks = []
113       
114    def handle_starttag(self, tag, attrs):
115        attrs = dict(attrs)
116       
117        if tag == 'h3':
118            self.h3 = True
119           
120        if tag == 'table':
121            self.table = True
122            #self.networks = []
123           
124        if tag == 'tr':
125            self.tr = True
126            self.net_data = []
127           
128        if tag == 'td':
129            self.td = True
130           
131        if tag == 'a' and self.td and self.tr:
132            self.net_data.append(attrs.get('href', ''))
133           
134    def handle_data(self, data):
135        if self.h3:
136            self.title = data
137           
138        if self.tr and self.td:
139            self.net_data.append(data)
140           
141    def handle_endtag(self, tag):
142        if tag == 'h3':
143            self.h3 = False
144           
145        if tag == 'table':
146            self.table = False
147            #self.repos[self.title] = self.networks
148           
149        if tag == 'tr':
150            if len(self.net_data) == 6:
151                self.networks.append(NetworkInfo(self.net_data[1], 
152                     'http://snap.stanford.edu/data/' + self.net_data[0],
153                     self.net_data[2],
154                     self.net_data[3],
155                     self.net_data[4],
156                     self.title,
157                     self.net_data[5]))
158               
159            self.tr = False
160           
161        if tag == 'td':
162            self.td = False
163   
164class SNAP(object):
165    """A collection of methods to access the information about networks in the
166    Stanford Large Network Dataset Collection.
167   
168    .. attribute:: network_list
169   
170        A list of networks on the `Stanford Large Network Dataset Collection web
171        site <http://snap.stanford.edu/data>`_. Each list item is an instance of the
172        :obj:`Orange.networks.snap.NetworkInfo` class.
173   
174    """
175   
176    def __init__(self):
177        self.network_list = []
178        self.http = None
179       
180    def parse_snap(self, error, done_callback, progress_callback=None):
181        if not error:
182            #self.last_total = self.http.bytesAvailable()
183            #if self.last_total <= 0:
184            #    self.last_total = 24763
185           
186            src = str(self.http.readAll())
187            snap_parser = SNAPParser()
188            snap_parser.feed(src)
189           
190            self.network_list = snap_parser.networks
191            done_callback(snap_parser.networks)
192        else:
193            done_callback(None)
194       
195        if progress_callback is not None:
196            progress_callback(1,1)
197       
198    def get_network_list(self, done_callback=None, progress_callback=None):
199        """Read the networks from the SNAP web site and populate the n
200        etwork_list attribute. If done_callback is set, an asynchronous HTTP
201        request is made to the SNAP web site. If the done_callback is left None,
202        the HTTP request made is synchronous and the network_list is returned.
203       
204        :param done_callback: a callback method called when the network info is downloaded
205        :type done_callback: function(bool)
206       
207        :param progress_callback: a callback method to update a progress bar
208        :type progress_callback: function(done, total)
209       
210        """
211        if done_callback == None: 
212            conn = httplib.HTTPConnection("snap.stanford.edu")
213            conn.request("GET", "/data/index.html")
214            r1 = conn.getresponse()
215            src = r1.read()
216            snap_parser = SNAPParser()
217            snap_parser.feed(src)
218            self.network_list = snap_parser.networks
219            return self.network_list
220        else:
221            import PyQt4.QtNetwork
222            from PyQt4.QtCore import QObject, QString, SIGNAL
223
224            self.http = PyQt4.QtNetwork.QHttp()
225           
226            QObject.connect(self.http, SIGNAL('done(bool)'), lambda error,\
227                    done_callback=done_callback, progress_callback=progress_callback: \
228                    self.parse_snap(error, done_callback, progress_callback))
229           
230            if progress_callback is not None:
231                QObject.connect(self.http, SIGNAL('dataReadProgress(int,int)'), progress_callback)
232           
233            self.http.setHost('snap.stanford.edu')
234            self.http.get('/data/index.html')
235           
236    def get_network(self, id):
237        """Find and return the network by name. If no network is found, return
238        None. Call get_network_list before calling this method to populate the
239        network_list attribute.
240       
241        :param id: a name of the network in SNAP collection
242        :type id: string
243       
244        """
245       
246        for network in self.network_list:
247            if str(network.name) == str(id):
248                return network
249           
250        return None
Note: See TracBrowser for help on using the repository browser.