@@ -0,0 +1,3520 @@
+# A simple script for timing point-in-polygon lookups in an instance%0A# of MapIt UK.  The results for this tend to be quite variable - the%0A# suggestion in the timeit documentation is to take the minimum over%0A# a number of repetitions.%0A%0Afrom random import randint, uniform, seed%0Afrom time import time%0Afrom timeit import timeit, Timer, repeat%0Afrom django.core.management.base import BaseCommand, CommandError%0Afrom django.db import connection%0Afrom django.db.models import Min, Max%0Afrom mapit.models import *%0A%0Aminimum_postcode_id = Postcode.objects.aggregate(Min('id'))%5B'id__min'%5D%0Amaximum_postcode_id = Postcode.objects.aggregate(Max('id'))%5B'id__max'%5D%0A%0Adef get_random_UK_location():%0A    %22%22%22Return a random location generally on the UK mainland%0A%0A    This doesn't need to be very good for our testing purposes, so we%0A    just pick a random postcode from the database, and add some error%0A    to the latitude and longitude for that postcode.  Sometimes this%0A    might give you a point which is actually out in the sea, but again%0A    this doesn't really matter for these purposes.  Obviously these%0A    locations aren't going to be uniform across the UK, since%0A    postcodes are more dense in towns.%22%22%22%0A%0A    location = None%0A    while not location:%0A        postcode_id = randint(minimum_postcode_id, maximum_postcode_id)%0A        try:%0A            location = Postcode.objects.get(id=postcode_id).location%0A        # It's always possible that the IDs aren't sequential:%0A        except Postcode.DoesNotExist:%0A            continue%0A%0A    # This is (very) roughly a kilometer in degrees longitude or%0A    # latitude in the UK:%0A    max_error_to_add = 0.01%0A    new_lon = location.coords%5B0%5D + uniform(-max_error_to_add, max_error_to_add)%0A    new_lat = location.coords%5B1%5D + uniform(-max_error_to_add, max_error_to_add)%0A    location.coords = (new_lon, new_lat)%0A    return location%0A%0Arandom_locations = None%0A%0Aclass Command(BaseCommand):%0A    args = '%3Citerations%3E'%0A    help = 'Time many point-in-polygon lookups'%0A%0A    def handle(self, *args, **options):%0A        if len(args) != 1:%0A            raise CommandError('There must be only one argument')%0A%0A        try:%0A            iterations = int(args%5B0%5D)%0A        except ValueError:%0A            raise CommandError('The iterations argument must be an integer')%0A%0A        repeats = 5%0A%0A        # So that the time to generate random locations isn't a factor%0A        # in the timing, generate all the locations ahead of time.%0A        # (In fact, this takes a vanishingly small amount of time%0A        # compared to the area lookups in the current version, but in%0A        # previous versions of this script generating random locations%0A        # was much slower.)%0A%0A        to_generate = repeats * iterations%0A        print %22Generating %25d random locations in the UK ...%22 %25 (to_generate,)%0A        global random_locations%0A        random_locations = %5Bget_random_UK_location() for _ in xrange(to_generate)%5D%0A        print %22... done.%22%0A%0A        # Now look up each of those locations, timing the process with%0A        # timeit.  Note that the list() is required to cause%0A        # evaluation of the GeoQuerySet.%0A%0A        print %22Testing point-in-polygon tests ...%22%0A        result = repeat(stmt='list(Area.objects.by_location(random_locations.pop()))',%0A                        setup='''%0Afrom mapit.models import Area%0Afrom mapit.management.commands.mapit_UK_time_lookups import random_locations%0A''',%0A                        repeat=repeats,%0A                        number=iterations)%0A        print %22... done.%22%0A%0A        print result%0A

Add a script for timing point -> areas lookups in MapIt UK