##// END OF EJS Templates
Merging upstream changes.
bgranger -
r2316:61e9f7ac merge
parent child Browse files
Show More
@@ -0,0 +1,90 b''
1 from numpy import *
2
3 def mandel(n, m, itermax, xmin, xmax, ymin, ymax):
4 '''
5 Fast mandelbrot computation using numpy.
6
7 (n, m) are the output image dimensions
8 itermax is the maximum number of iterations to do
9 xmin, xmax, ymin, ymax specify the region of the
10 set to compute.
11 '''
12 # The point of ix and iy is that they are 2D arrays
13 # giving the x-coord and y-coord at each point in
14 # the array. The reason for doing this will become
15 # clear below...
16 ix, iy = mgrid[0:n, 0:m]
17 # Now x and y are the x-values and y-values at each
18 # point in the array, linspace(start, end, n)
19 # is an array of n linearly spaced points between
20 # start and end, and we then index this array using
21 # numpy fancy indexing. If A is an array and I is
22 # an array of indices, then A[I] has the same shape
23 # as I and at each place i in I has the value A[i].
24 x = linspace(xmin, xmax, n)[ix]
25 y = linspace(ymin, ymax, m)[iy]
26 # c is the complex number with the given x, y coords
27 c = x+complex(0,1)*y
28 del x, y # save a bit of memory, we only need z
29 # the output image coloured according to the number
30 # of iterations it takes to get to the boundary
31 # abs(z)>2
32 img = zeros(c.shape, dtype=int)
33 # Here is where the improvement over the standard
34 # algorithm for drawing fractals in numpy comes in.
35 # We flatten all the arrays ix, iy and c. This
36 # flattening doesn't use any more memory because
37 # we are just changing the shape of the array, the
38 # data in memory stays the same. It also affects
39 # each array in the same way, so that index i in
40 # array c has x, y coords ix[i], iy[i]. The way the
41 # algorithm works is that whenever abs(z)>2 we
42 # remove the corresponding index from each of the
43 # arrays ix, iy and c. Since we do the same thing
44 # to each array, the correspondence between c and
45 # the x, y coords stored in ix and iy is kept.
46 ix.shape = n*m
47 iy.shape = n*m
48 c.shape = n*m
49 # we iterate z->z^2+c with z starting at 0, but the
50 # first iteration makes z=c so we just start there.
51 # We need to copy c because otherwise the operation
52 # z->z^2 will send c->c^2.
53 z = copy(c)
54 for i in xrange(itermax):
55 if not len(z): break # all points have escaped
56 # equivalent to z = z*z+c but quicker and uses
57 # less memory
58 multiply(z, z, z)
59 add(z, c, z)
60 # these are the points that have escaped
61 rem = abs(z)>2.0
62 # colour them with the iteration number, we
63 # add one so that points which haven't
64 # escaped have 0 as their iteration number,
65 # this is why we keep the arrays ix and iy
66 # because we need to know which point in img
67 # to colour
68 img[ix[rem], iy[rem]] = i+1
69 # -rem is the array of points which haven't
70 # escaped, in numpy -A for a boolean array A
71 # is the NOT operation.
72 rem = -rem
73 # So we select out the points in
74 # z, ix, iy and c which are still to be
75 # iterated on in the next step
76 z = z[rem]
77 ix, iy = ix[rem], iy[rem]
78 c = c[rem]
79 return img
80
81 if __name__=='__main__':
82 from pylab import *
83 import time
84 start = time.time()
85 I = mandel(400, 400, 100, -2, .5, -1.25, 1.25)
86 print 'Time taken:', time.time()-start
87 I[I==0] = 101
88 img = imshow(I.T, origin='lower left')
89 img.write_png('mandel.png', noscale=True)
90 show()
@@ -15,6 +15,8 b' The IPython cluster directory'
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from __future__ import with_statement
19
18 import os
20 import os
19 import shutil
21 import shutil
20 import sys
22 import sys
@@ -37,6 +39,10 b' class ClusterDirError(Exception):'
37 pass
39 pass
38
40
39
41
42 class PIDFileError(Exception):
43 pass
44
45
40 class ClusterDir(Component):
46 class ClusterDir(Component):
41 """An object to manage the cluster directory and its resources.
47 """An object to manage the cluster directory and its resources.
42
48
@@ -50,9 +56,11 b' class ClusterDir(Component):'
50
56
51 security_dir_name = Unicode('security')
57 security_dir_name = Unicode('security')
52 log_dir_name = Unicode('log')
58 log_dir_name = Unicode('log')
53 security_dir = Unicode()
59 pid_dir_name = Unicode('pid')
54 log_dir = Unicode('')
60 security_dir = Unicode(u'')
55 location = Unicode('')
61 log_dir = Unicode(u'')
62 pid_dir = Unicode(u'')
63 location = Unicode(u'')
56
64
57 def __init__(self, location):
65 def __init__(self, location):
58 super(ClusterDir, self).__init__(None)
66 super(ClusterDir, self).__init__(None)
@@ -65,6 +73,7 b' class ClusterDir(Component):'
65 os.chmod(new, 0777)
73 os.chmod(new, 0777)
66 self.security_dir = os.path.join(new, self.security_dir_name)
74 self.security_dir = os.path.join(new, self.security_dir_name)
67 self.log_dir = os.path.join(new, self.log_dir_name)
75 self.log_dir = os.path.join(new, self.log_dir_name)
76 self.pid_dir = os.path.join(new, self.pid_dir_name)
68 self.check_dirs()
77 self.check_dirs()
69
78
70 def _log_dir_changed(self, name, old, new):
79 def _log_dir_changed(self, name, old, new):
@@ -85,9 +94,19 b' class ClusterDir(Component):'
85 else:
94 else:
86 os.chmod(self.security_dir, 0700)
95 os.chmod(self.security_dir, 0700)
87
96
97 def _pid_dir_changed(self, name, old, new):
98 self.check_pid_dir()
99
100 def check_pid_dir(self):
101 if not os.path.isdir(self.pid_dir):
102 os.mkdir(self.pid_dir, 0700)
103 else:
104 os.chmod(self.pid_dir, 0700)
105
88 def check_dirs(self):
106 def check_dirs(self):
89 self.check_security_dir()
107 self.check_security_dir()
90 self.check_log_dir()
108 self.check_log_dir()
109 self.check_pid_dir()
91
110
92 def load_config_file(self, filename):
111 def load_config_file(self, filename):
93 """Load a config file from the top level of the cluster dir.
112 """Load a config file from the top level of the cluster dir.
@@ -209,13 +228,13 b' class AppWithClusterDirArgParseConfigLoader(ArgParseConfigLoader):'
209 """Default command line options for IPython cluster applications."""
228 """Default command line options for IPython cluster applications."""
210
229
211 def _add_other_arguments(self):
230 def _add_other_arguments(self):
212 self.parser.add_argument('-ipythondir', '--ipython-dir',
231 self.parser.add_argument('--ipython-dir',
213 dest='Global.ipythondir',type=str,
232 dest='Global.ipythondir',type=str,
214 help='Set to override default location of Global.ipythondir.',
233 help='Set to override default location of Global.ipythondir.',
215 default=NoConfigDefault,
234 default=NoConfigDefault,
216 metavar='Global.ipythondir'
235 metavar='Global.ipythondir'
217 )
236 )
218 self.parser.add_argument('-p','-profile', '--profile',
237 self.parser.add_argument('-p', '--profile',
219 dest='Global.profile',type=str,
238 dest='Global.profile',type=str,
220 help='The string name of the profile to be used. This determines '
239 help='The string name of the profile to be used. This determines '
221 'the name of the cluster dir as: cluster_<profile>. The default profile '
240 'the name of the cluster dir as: cluster_<profile>. The default profile '
@@ -224,25 +243,25 b' class AppWithClusterDirArgParseConfigLoader(ArgParseConfigLoader):'
224 default=NoConfigDefault,
243 default=NoConfigDefault,
225 metavar='Global.profile'
244 metavar='Global.profile'
226 )
245 )
227 self.parser.add_argument('-log_level', '--log-level',
246 self.parser.add_argument('--log-level',
228 dest="Global.log_level",type=int,
247 dest="Global.log_level",type=int,
229 help='Set the log level (0,10,20,30,40,50). Default is 30.',
248 help='Set the log level (0,10,20,30,40,50). Default is 30.',
230 default=NoConfigDefault,
249 default=NoConfigDefault,
231 metavar="Global.log_level"
250 metavar="Global.log_level"
232 )
251 )
233 self.parser.add_argument('-cluster_dir', '--cluster-dir',
252 self.parser.add_argument('--cluster-dir',
234 dest='Global.cluster_dir',type=str,
253 dest='Global.cluster_dir',type=str,
235 help='Set the cluster dir. This overrides the logic used by the '
254 help='Set the cluster dir. This overrides the logic used by the '
236 '--profile option.',
255 '--profile option.',
237 default=NoConfigDefault,
256 default=NoConfigDefault,
238 metavar='Global.cluster_dir'
257 metavar='Global.cluster_dir'
239 )
258 )
240 self.parser.add_argument('-clean_logs', '--clean-logs',
259 self.parser.add_argument('--clean-logs',
241 dest='Global.clean_logs', action='store_true',
260 dest='Global.clean_logs', action='store_true',
242 help='Delete old log flies before starting.',
261 help='Delete old log flies before starting.',
243 default=NoConfigDefault
262 default=NoConfigDefault
244 )
263 )
245 self.parser.add_argument('-noclean_logs', '--no-clean-logs',
264 self.parser.add_argument('--no-clean-logs',
246 dest='Global.clean_logs', action='store_false',
265 dest='Global.clean_logs', action='store_false',
247 help="Don't Delete old log flies before starting.",
266 help="Don't Delete old log flies before starting.",
248 default=NoConfigDefault
267 default=NoConfigDefault
@@ -375,6 +394,8 b' class ApplicationWithClusterDir(Application):'
375 self.security_dir = config.Global.security_dir = sdir
394 self.security_dir = config.Global.security_dir = sdir
376 ldir = self.cluster_dir_obj.log_dir
395 ldir = self.cluster_dir_obj.log_dir
377 self.log_dir = config.Global.log_dir = ldir
396 self.log_dir = config.Global.log_dir = ldir
397 pdir = self.cluster_dir_obj.pid_dir
398 self.pid_dir = config.Global.pid_dir = pdir
378 self.log.info("Cluster directory set to: %s" % self.cluster_dir)
399 self.log.info("Cluster directory set to: %s" % self.cluster_dir)
379
400
380 def start_logging(self):
401 def start_logging(self):
@@ -392,3 +413,46 b' class ApplicationWithClusterDir(Application):'
392 else:
413 else:
393 open_log_file = sys.stdout
414 open_log_file = sys.stdout
394 log.startLogging(open_log_file)
415 log.startLogging(open_log_file)
416
417 def write_pid_file(self):
418 """Create a .pid file in the pid_dir with my pid.
419
420 This must be called after pre_construct, which sets `self.pid_dir`.
421 This raises :exc:`PIDFileError` if the pid file exists already.
422 """
423 pid_file = os.path.join(self.pid_dir, self.name + '.pid')
424 if os.path.isfile(pid_file):
425 pid = self.get_pid_from_file()
426 raise PIDFileError(
427 'The pid file [%s] already exists. \nThis could mean that this '
428 'server is already running with [pid=%s].' % (pid_file, pid))
429 with open(pid_file, 'w') as f:
430 self.log.info("Creating pid file: %s" % pid_file)
431 f.write(repr(os.getpid())+'\n')
432
433 def remove_pid_file(self):
434 """Remove the pid file.
435
436 This should be called at shutdown by registering a callback with
437 :func:`reactor.addSystemEventTrigger`.
438 """
439 pid_file = os.path.join(self.pid_dir, self.name + '.pid')
440 if os.path.isfile(pid_file):
441 try:
442 self.log.info("Removing pid file: %s" % pid_file)
443 os.remove(pid_file)
444 except:
445 pass
446
447 def get_pid_from_file(self):
448 """Get the pid from the pid file.
449
450 If the pid file doesn't exist a :exc:`PIDFileError` is raised.
451 """
452 pid_file = os.path.join(self.pid_dir, self.name + '.pid')
453 if os.path.isfile(pid_file):
454 with open(pid_file, 'r') as f:
455 pid = int(f.read().strip())
456 return pid
457 else:
458 raise PIDFileError('pid file not found: %s' % pid_file) No newline at end of file
@@ -20,13 +20,15 b' import os'
20 import signal
20 import signal
21 import sys
21 import sys
22
22
23 from twisted.scripts._twistd_unix import daemonize
24
23 from IPython.core import release
25 from IPython.core import release
24 from IPython.external import argparse
26 from IPython.external import argparse
25 from IPython.config.loader import ArgParseConfigLoader, NoConfigDefault
27 from IPython.config.loader import ArgParseConfigLoader, NoConfigDefault
26 from IPython.utils.importstring import import_item
28 from IPython.utils.importstring import import_item
27
29
28 from IPython.kernel.clusterdir import (
30 from IPython.kernel.clusterdir import (
29 ApplicationWithClusterDir, ClusterDirError
31 ApplicationWithClusterDir, ClusterDirError, PIDFileError
30 )
32 )
31
33
32 from twisted.internet import reactor, defer
34 from twisted.internet import reactor, defer
@@ -48,12 +50,12 b' class IPClusterCLLoader(ArgParseConfigLoader):'
48 def _add_arguments(self):
50 def _add_arguments(self):
49 # This has all the common options that all subcommands use
51 # This has all the common options that all subcommands use
50 parent_parser1 = argparse.ArgumentParser(add_help=False)
52 parent_parser1 = argparse.ArgumentParser(add_help=False)
51 parent_parser1.add_argument('-ipythondir', '--ipython-dir',
53 parent_parser1.add_argument('--ipython-dir',
52 dest='Global.ipythondir',type=str,
54 dest='Global.ipythondir',type=str,
53 help='Set to override default location of Global.ipythondir.',
55 help='Set to override default location of Global.ipythondir.',
54 default=NoConfigDefault,
56 default=NoConfigDefault,
55 metavar='Global.ipythondir')
57 metavar='Global.ipythondir')
56 parent_parser1.add_argument('-log_level', '--log-level',
58 parent_parser1.add_argument('--log-level',
57 dest="Global.log_level",type=int,
59 dest="Global.log_level",type=int,
58 help='Set the log level (0,10,20,30,40,50). Default is 30.',
60 help='Set the log level (0,10,20,30,40,50). Default is 30.',
59 default=NoConfigDefault,
61 default=NoConfigDefault,
@@ -61,7 +63,7 b' class IPClusterCLLoader(ArgParseConfigLoader):'
61
63
62 # This has all the common options that other subcommands use
64 # This has all the common options that other subcommands use
63 parent_parser2 = argparse.ArgumentParser(add_help=False)
65 parent_parser2 = argparse.ArgumentParser(add_help=False)
64 parent_parser2.add_argument('-p','-profile', '--profile',
66 parent_parser2.add_argument('-p','--profile',
65 dest='Global.profile',type=str,
67 dest='Global.profile',type=str,
66 default=NoConfigDefault,
68 default=NoConfigDefault,
67 help='The string name of the profile to be used. This determines '
69 help='The string name of the profile to be used. This determines '
@@ -70,7 +72,7 b' class IPClusterCLLoader(ArgParseConfigLoader):'
70 'if the --cluster-dir option is not used.',
72 'if the --cluster-dir option is not used.',
71 default=NoConfigDefault,
73 default=NoConfigDefault,
72 metavar='Global.profile')
74 metavar='Global.profile')
73 parent_parser2.add_argument('-cluster_dir', '--cluster-dir',
75 parent_parser2.add_argument('--cluster-dir',
74 dest='Global.cluster_dir',type=str,
76 dest='Global.cluster_dir',type=str,
75 default=NoConfigDefault,
77 default=NoConfigDefault,
76 help='Set the cluster dir. This overrides the logic used by the '
78 help='Set the cluster dir. This overrides the logic used by the '
@@ -122,16 +124,38 b' class IPClusterCLLoader(ArgParseConfigLoader):'
122 help='The number of engines to start.',
124 help='The number of engines to start.',
123 metavar='Global.n'
125 metavar='Global.n'
124 )
126 )
125 parser_start.add_argument('-clean_logs', '--clean-logs',
127 parser_start.add_argument('--clean-logs',
126 dest='Global.clean_logs', action='store_true',
128 dest='Global.clean_logs', action='store_true',
127 help='Delete old log flies before starting.',
129 help='Delete old log flies before starting.',
128 default=NoConfigDefault
130 default=NoConfigDefault
129 )
131 )
130 parser_start.add_argument('-noclean_logs', '--no-clean-logs',
132 parser_start.add_argument('--no-clean-logs',
131 dest='Global.clean_logs', action='store_false',
133 dest='Global.clean_logs', action='store_false',
132 help="Don't delete old log flies before starting.",
134 help="Don't delete old log flies before starting.",
133 default=NoConfigDefault
135 default=NoConfigDefault
134 )
136 )
137 parser_start.add_argument('--daemon',
138 dest='Global.daemonize', action='store_true',
139 help='Daemonize the ipcluster program. This implies --log-to-file',
140 default=NoConfigDefault
141 )
142 parser_start.add_argument('--nodaemon',
143 dest='Global.daemonize', action='store_false',
144 help="Dont't daemonize the ipcluster program.",
145 default=NoConfigDefault
146 )
147
148 parser_start = subparsers.add_parser(
149 'stop',
150 help='Stop a cluster.',
151 parents=[parent_parser1, parent_parser2]
152 )
153 parser_start.add_argument('--signal-number',
154 dest='Global.stop_signal', type=int,
155 help="The signal number to use in stopping the cluster (default=2).",
156 metavar="Global.stop_signal",
157 default=NoConfigDefault
158 )
135
159
136 default_config_file_name = 'ipcluster_config.py'
160 default_config_file_name = 'ipcluster_config.py'
137
161
@@ -153,6 +177,8 b' class IPClusterApp(ApplicationWithClusterDir):'
153 self.default_config.Global.n = 2
177 self.default_config.Global.n = 2
154 self.default_config.Global.reset_config = False
178 self.default_config.Global.reset_config = False
155 self.default_config.Global.clean_logs = True
179 self.default_config.Global.clean_logs = True
180 self.default_config.Global.stop_signal = 2
181 self.default_config.Global.daemonize = False
156
182
157 def create_command_line_config(self):
183 def create_command_line_config(self):
158 """Create and return a command line config loader."""
184 """Create and return a command line config loader."""
@@ -170,7 +196,7 b' class IPClusterApp(ApplicationWithClusterDir):'
170 elif subcommand=='create':
196 elif subcommand=='create':
171 self.auto_create_cluster_dir = True
197 self.auto_create_cluster_dir = True
172 super(IPClusterApp, self).find_resources()
198 super(IPClusterApp, self).find_resources()
173 elif subcommand=='start':
199 elif subcommand=='start' or subcommand=='stop':
174 self.auto_create_cluster_dir = False
200 self.auto_create_cluster_dir = False
175 try:
201 try:
176 super(IPClusterApp, self).find_resources()
202 super(IPClusterApp, self).find_resources()
@@ -182,6 +208,16 b' class IPClusterApp(ApplicationWithClusterDir):'
182 "information about creating and listing cluster dirs."
208 "information about creating and listing cluster dirs."
183 )
209 )
184
210
211 def pre_construct(self):
212 super(IPClusterApp, self).pre_construct()
213 config = self.master_config
214 try:
215 daemon = config.Global.daemonize
216 if daemon:
217 config.Global.log_to_file = True
218 except AttributeError:
219 pass
220
185 def construct(self):
221 def construct(self):
186 config = self.master_config
222 config = self.master_config
187 if config.Global.subcommand=='list':
223 if config.Global.subcommand=='list':
@@ -288,11 +324,52 b' class IPClusterApp(ApplicationWithClusterDir):'
288 super(IPClusterApp, self).start_logging()
324 super(IPClusterApp, self).start_logging()
289
325
290 def start_app(self):
326 def start_app(self):
327 """Start the application, depending on what subcommand is used."""
291 config = self.master_config
328 config = self.master_config
292 if config.Global.subcommand=='create' or config.Global.subcommand=='list':
329 subcmd = config.Global.subcommand
330 if subcmd=='create' or subcmd=='list':
293 return
331 return
294 elif config.Global.subcommand=='start':
332 elif subcmd=='start':
333 # First see if the cluster is already running
334 try:
335 pid = self.get_pid_from_file()
336 except:
337 pass
338 else:
339 self.log.critical(
340 'Cluster is already running with [pid=%s]. '
341 'use "ipcluster stop" to stop the cluster.' % pid
342 )
343 # Here I exit with a unusual exit status that other processes
344 # can watch for to learn how I existed.
345 sys.exit(10)
346 # Now log and daemonize
347 self.log.info('Starting ipcluster with [daemon=%r]' % config.Global.daemonize)
348 if config.Global.daemonize:
349 if os.name=='posix':
350 os.chdir(config.Global.cluster_dir)
351 self.log_level = 40
352 daemonize()
353
354 # Now write the new pid file after our new forked pid is active.
355 self.write_pid_file()
356 reactor.addSystemEventTrigger('during','shutdown', self.remove_pid_file)
295 reactor.run()
357 reactor.run()
358 elif subcmd=='stop':
359 try:
360 pid = self.get_pid_from_file()
361 except PIDFileError:
362 self.log.critical(
363 'Problem reading pid file, cluster is probably not running.'
364 )
365 # Here I exit with a unusual exit status that other processes
366 # can watch for to learn how I existed.
367 sys.exit(11)
368 sig = config.Global.stop_signal
369 self.log.info(
370 "Stopping cluster [pid=%r] with [signal=%r]" % (pid, sig)
371 )
372 os.kill(pid, sig)
296
373
297
374
298 def launch_new_instance():
375 def launch_new_instance():
@@ -15,6 +15,8 b' The IPython controller application.'
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from __future__ import with_statement
19
18 import copy
20 import copy
19 import os
21 import os
20 import sys
22 import sys
@@ -158,9 +160,13 b' cl_args = ('
158 'are deleted before the controller starts. This must be set if '
160 'are deleted before the controller starts. This must be set if '
159 'specific ports are specified by --engine-port or --client-port.')
161 'specific ports are specified by --engine-port or --client-port.')
160 ),
162 ),
161 (('-ns','--no-security'), dict(
163 (('--no-secure',), dict(
162 action='store_false', dest='Global.secure', default=NoConfigDefault,
164 action='store_false', dest='Global.secure', default=NoConfigDefault,
163 help='Turn off SSL encryption for all connections.')
165 help='Turn off SSL encryption for all connections.')
166 ),
167 (('--secure',), dict(
168 action='store_true', dest='Global.secure', default=NoConfigDefault,
169 help='Turn off SSL encryption for all connections.')
164 )
170 )
165 )
171 )
166
172
@@ -213,7 +219,7 b' class IPControllerApp(ApplicationWithClusterDir):'
213
219
214 self.start_logging()
220 self.start_logging()
215 self.import_statements()
221 self.import_statements()
216
222
217 # Create the service hierarchy
223 # Create the service hierarchy
218 self.main_service = service.MultiService()
224 self.main_service = service.MultiService()
219 # The controller service
225 # The controller service
@@ -240,6 +246,8 b' class IPControllerApp(ApplicationWithClusterDir):'
240 def start_app(self):
246 def start_app(self):
241 # Start the controller service and set things running
247 # Start the controller service and set things running
242 self.main_service.startService()
248 self.main_service.startService()
249 self.write_pid_file()
250 reactor.addSystemEventTrigger('during','shutdown', self.remove_pid_file)
243 reactor.run()
251 reactor.run()
244
252
245
253
@@ -1,13 +1,20 b''
1 """Count the frequencies of words in a string"""
1 """Count the frequencies of words in a string"""
2
2
3 from __future__ import division
4
5 import cmath as math
6
7
3 def wordfreq(text):
8 def wordfreq(text):
4 """Return a dictionary of words and word counts in a string."""
9 """Return a dictionary of words and word counts in a string."""
5
10
6 freqs = {}
11 freqs = {}
7 for word in text.split():
12 for word in text.split():
8 freqs[word] = freqs.get(word, 0) + 1
13 lword = word.lower()
14 freqs[lword] = freqs.get(lword, 0) + 1
9 return freqs
15 return freqs
10
16
17
11 def print_wordfreq(freqs, n=10):
18 def print_wordfreq(freqs, n=10):
12 """Print the n most common words and counts in the freqs dict."""
19 """Print the n most common words and counts in the freqs dict."""
13
20
@@ -17,7 +24,43 b' def print_wordfreq(freqs, n=10):'
17 for (count, word) in items[:n]:
24 for (count, word) in items[:n]:
18 print word, count
25 print word, count
19
26
20 if __name__ == '__main__':
27
21 import gzip
28 def wordfreq_to_weightsize(worddict, minsize=10, maxsize=50, minalpha=0.4, maxalpha=1.0):
22 text = gzip.open('HISTORY.gz').read()
29 mincount = min(worddict.itervalues())
23 freqs = wordfreq(text) No newline at end of file
30 maxcount = max(worddict.itervalues())
31 weights = {}
32 for k, v in worddict.iteritems():
33 w = (v-mincount)/(maxcount-mincount)
34 alpha = minalpha + (maxalpha-minalpha)*w
35 size = minsize + (maxsize-minsize)*w
36 weights[k] = (alpha, size)
37 return weights
38
39
40 def tagcloud(worddict, n=10, minsize=10, maxsize=50, minalpha=0.4, maxalpha=1.0):
41 from matplotlib import pyplot as plt
42 import random
43
44 worddict = wordfreq_to_weightsize(worddict, minsize, maxsize, minalpha, maxalpha)
45
46 fig = plt.figure()
47 ax = fig.add_subplot(111)
48 ax.set_position([0.0,0.0,1.0,1.0])
49 plt.xticks([])
50 plt.yticks([])
51
52 words = worddict.keys()
53 alphas = [v[0] for v in worddict.values()]
54 sizes = [v[1] for v in worddict.values()]
55 items = zip(alphas, sizes, words)
56 items.sort(reverse=True)
57 for alpha, size, word in items[:n]:
58 xpos = random.normalvariate(0.5, 0.3)
59 ypos = random.normalvariate(0.5, 0.3)
60 # xpos = random.uniform(0.0,1.0)
61 # ypos = random.uniform(0.0,1.0)
62 ax.text(xpos, ypos, word.lower(), alpha=alpha, fontsize=size)
63 ax.autoscale_view()
64 return ax
65
66 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now