| 1 | # Brute Force: |
|---|
| 2 | # 481 hits |
|---|
| 3 | # 29637.96 usec/pass |
|---|
| 4 | # |
|---|
| 5 | # Memory-based Rtree Intersection: |
|---|
| 6 | # 481 hits |
|---|
| 7 | # 1216.70 usec/pass |
|---|
| 8 | # \Disk-based Rtree Intersection: |
|---|
| 9 | # 481 hits |
|---|
| 10 | # 2617.95 usec/pass |
|---|
| 11 | |
|---|
| 12 | import random |
|---|
| 13 | import timeit |
|---|
| 14 | |
|---|
| 15 | try: |
|---|
| 16 | import pkg_resources |
|---|
| 17 | pkg_resources.require('Rtree') |
|---|
| 18 | except: |
|---|
| 19 | pass |
|---|
| 20 | |
|---|
| 21 | from rtree import Rtree as _Rtree |
|---|
| 22 | |
|---|
| 23 | TEST_TIMES = 20 |
|---|
| 24 | |
|---|
| 25 | # a very basic Geometry |
|---|
| 26 | class Point(object): |
|---|
| 27 | def __init__(self, x, y): |
|---|
| 28 | self.x = x |
|---|
| 29 | self.y = y |
|---|
| 30 | |
|---|
| 31 | # Scatter points randomly in a 1x1 box |
|---|
| 32 | # |
|---|
| 33 | |
|---|
| 34 | class Rtree(_Rtree): |
|---|
| 35 | pickle_protocol = -1 |
|---|
| 36 | |
|---|
| 37 | bounds = (0, 0, 6000000, 6000000) |
|---|
| 38 | count = 30000 |
|---|
| 39 | points = [] |
|---|
| 40 | |
|---|
| 41 | insert_object = None |
|---|
| 42 | insert_object = {'a': range(100), 'b': 10, 'c': object(), 'd': dict(x=1), 'e': Point(2, 3)} |
|---|
| 43 | |
|---|
| 44 | index = Rtree() |
|---|
| 45 | disk_index = Rtree('test', overwrite=1) |
|---|
| 46 | |
|---|
| 47 | coordinates = [] |
|---|
| 48 | for i in xrange(count): |
|---|
| 49 | x = random.randrange(bounds[0], bounds[2]) + random.random() |
|---|
| 50 | y = random.randrange(bounds[1], bounds[3]) + random.random() |
|---|
| 51 | point = Point(x, y) |
|---|
| 52 | points.append(point) |
|---|
| 53 | |
|---|
| 54 | index.add(i, (x, y), insert_object) |
|---|
| 55 | disk_index.add(i, (x, y), insert_object) |
|---|
| 56 | coordinates.append((i, (x, y, x, y), insert_object)) |
|---|
| 57 | |
|---|
| 58 | s =""" |
|---|
| 59 | bulk = Rtree(coordinates[:2000]) |
|---|
| 60 | """ |
|---|
| 61 | t = timeit.Timer(stmt=s, setup='from __main__ import coordinates, Rtree, insert_object') |
|---|
| 62 | print "\nStream load:" |
|---|
| 63 | print "%.2f usec/pass" % (1000000 * t.timeit(number=TEST_TIMES)/TEST_TIMES) |
|---|
| 64 | |
|---|
| 65 | s =""" |
|---|
| 66 | idx = Rtree() |
|---|
| 67 | i = 0 |
|---|
| 68 | for point in points[:2000]: |
|---|
| 69 | idx.add(i, (point.x, point.y), insert_object) |
|---|
| 70 | i+=1 |
|---|
| 71 | """ |
|---|
| 72 | t = timeit.Timer(stmt=s, setup='from __main__ import points, Rtree, insert_object') |
|---|
| 73 | print "\nOne-at-a-time load:" |
|---|
| 74 | print "%.2f usec/pass\n\n" % (1000000 * t.timeit(number=TEST_TIMES)/TEST_TIMES) |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | bbox = (1240000, 1010000, 1400000, 1390000) |
|---|
| 78 | print count, "points" |
|---|
| 79 | print "Query box: ", bbox |
|---|
| 80 | print "" |
|---|
| 81 | |
|---|
| 82 | # Brute force all points within a 0.1x0.1 box |
|---|
| 83 | s = """ |
|---|
| 84 | hits = [p for p in points if p.x >= bbox[0] and p.x <= bbox[2] and p.y >= bbox[1] and p.y <= bbox[3]] |
|---|
| 85 | """ |
|---|
| 86 | t = timeit.Timer(stmt=s, setup='from __main__ import points, bbox') |
|---|
| 87 | print "\nBrute Force:" |
|---|
| 88 | print len([p for p in points if p.x >= bbox[0] and p.x <= bbox[2] and p.y >= bbox[1] and p.y <= bbox[3]]), "hits" |
|---|
| 89 | print "%.2f usec/pass" % (1000000 * t.timeit(number=TEST_TIMES)/TEST_TIMES) |
|---|
| 90 | |
|---|
| 91 | # 0.1x0.1 box using intersection |
|---|
| 92 | |
|---|
| 93 | if insert_object is None: |
|---|
| 94 | s = """ |
|---|
| 95 | hits = [points[id] for id in index.intersection(bbox)] |
|---|
| 96 | """ |
|---|
| 97 | else: |
|---|
| 98 | s = """ |
|---|
| 99 | hits = [p.object for p in index.intersection(bbox, objects=insert_object)] |
|---|
| 100 | """ |
|---|
| 101 | |
|---|
| 102 | t = timeit.Timer(stmt=s, setup='from __main__ import points, index, bbox, insert_object') |
|---|
| 103 | print "\nMemory-based Rtree Intersection:" |
|---|
| 104 | print len([points[id] for id in index.intersection(bbox)]), "hits" |
|---|
| 105 | print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | # run same test on disk_index. |
|---|
| 109 | s = s.replace("index.", "disk_index.") |
|---|
| 110 | |
|---|
| 111 | t = timeit.Timer(stmt=s, setup='from __main__ import points, disk_index, bbox, insert_object') |
|---|
| 112 | print "\nDisk-based Rtree Intersection:" |
|---|
| 113 | print len(disk_index.intersection(bbox)), "hits" |
|---|
| 114 | print "%.2f usec/pass" % (1000000 * t.timeit(number=TEST_TIMES)/TEST_TIMES) |
|---|
| 115 | |
|---|
| 116 | |
|---|
| 117 | if insert_object: |
|---|
| 118 | s = """ |
|---|
| 119 | hits = disk_index.intersection(bbox, objects="raw") |
|---|
| 120 | """ |
|---|
| 121 | t = timeit.Timer(stmt=s, setup='from __main__ import points, disk_index, bbox, insert_object') |
|---|
| 122 | print "\nDisk-based Rtree Intersection without Item() wrapper (objects='raw'):" |
|---|
| 123 | result = disk_index.intersection(bbox, objects="raw") |
|---|
| 124 | print len(result), "raw hits" |
|---|
| 125 | print "%.2f usec/pass" % (1000000 * t.timeit(number=TEST_TIMES)/TEST_TIMES) |
|---|
| 126 | assert 'a' in result[0], result[0] |
|---|
| 127 | |
|---|
| 128 | import os |
|---|
| 129 | try: |
|---|
| 130 | os.remove('test.dat') |
|---|
| 131 | os.remove('test.idx') |
|---|
| 132 | except: |
|---|
| 133 | pass |
|---|