generate_trips.py (4687B)
1 #!/usr/bin/env python3 2 3 # Process registration data to generate the list of trip legs 4 5 import csv 6 import sys 7 import json 8 from geopy.distance import geodesic 9 from collections import defaultdict 10 from random import uniform 11 12 # place of the conference 13 origin = (sys.argv[1], sys.argv[2]) 14 noise = float(sys.argv[3]) # how much multiplicative noise to add to distances 15 16 # read locations 17 location = {} 18 with open("locations_all.txt", 'r') as floc: 19 for l in floc.readlines(): 20 f = l.strip().split(' ') 21 lat = f[0] 22 lon = f[1] 23 loc = ' '.join(f[2:]) 24 location[loc] = (lat, lon) 25 26 FNAME = "location_mode.csv" 27 28 modes = ["train", "plane", "bus/coach", "other", ""] 29 places = defaultdict(lambda : [0, 0, ""]) 30 31 def complete_mode(dist): 32 # from highlights 2025 data, from 600km onwards most trips are by plane 33 if dist > 600: 34 return "plane" 35 else: 36 return "train" 37 38 # compute trips 39 with open("trips_anonymized.csv", 'w') as fout: 40 with open("trips.csv", 'w') as fout2: 41 with open(FNAME, 'r') as ftrip: 42 reader = csv.reader(ftrip, delimiter="\t") 43 for r in reader: 44 #university = r[5] 45 # first = r[2].replace(',', '') 46 # last = r[3].replace(',', '') 47 # assert(r[6] == "I'm coming to Bordeaux") 48 # assert(r[8] == "External Participant") 49 # typ = r[7].replace(',', '') 50 if (len(r) < 4): 51 print (r) 52 assert(False) 53 from_place = r[0].strip() 54 from_mode = r[1].replace(',', '').lower() 55 to_place = r[2].strip() 56 to_mode = r[3].replace(',', '').lower() 57 #annotation = ' '.join((first, last, university, typ)) 58 annotation = '' 59 if from_mode == "bus": 60 from_mode = "bus/coach" 61 if to_mode == "bus": 62 to_mode = "bus/coach" 63 if not (from_mode in modes): 64 print (from_mode) 65 assert(False) 66 assert (from_mode in modes) 67 assert (to_mode in modes) 68 from_coord = location[from_place] 69 to_coord = location[to_place] 70 71 from_dist = geodesic(origin, from_coord).kilometers 72 to_dist = geodesic(origin, to_coord).kilometers 73 from_dist_anon = round(uniform(from_dist * (1-noise), from_dist * (1+noise))) 74 to_dist_anon = round(uniform(to_dist * (1-noise), to_dist * (1+noise))) 75 if from_mode == '' or from_mode == 'other': 76 from_mode = complete_mode(from_dist) 77 if to_mode == '' or to_mode == 'other': 78 to_mode = complete_mode(to_dist) 79 80 places[from_coord][1] += 1 81 places[to_coord][1] += 1 82 places[from_coord][2] += annotation + "\n" 83 places[to_coord][2] += annotation + "\n" 84 if from_mode == "plane": 85 places[from_coord][0] += 1 86 if to_mode == "plane": 87 places[to_coord][0] += 1 88 89 90 print(','.join(( 91 from_mode.lower(), 92 str(from_dist), 93 from_place.replace(',', ''), 94 *from_coord, annotation)), file=fout2) 95 print(','.join(( 96 to_mode.lower(), 97 str(to_dist), 98 to_place.replace(',', ''), 99 *to_coord, annotation)), file=fout2) 100 print(','.join(( 101 from_mode.lower(), 102 str(from_dist_anon), 103 )), file=fout) 104 print(','.join(( 105 to_mode.lower(), 106 str(to_dist_anon), 107 )), file=fout) 108 109 ## OUTPUT GEOJSON 110 111 features = [] 112 for k in places.keys(): 113 red = int(255.*places[k][0]/places[k][1]) 114 green = 0 115 blue = int(255.*(places[k][1]-places[k][0])/places[k][1]) 116 color = '#%02X%02X%02X' % (red, green, blue) 117 feature = { 118 "type": "Feature", 119 "properties": { 120 "name":places[k][2], 121 "_umap_options": {"color": color} 122 }, 123 "geometry": { 124 "type": "Point", 125 "coordinates": [ 126 k[1], k[0] 127 ] 128 } 129 } 130 features.append(feature) 131 132 output = { 133 "type": "FeatureCollection", 134 "features": features 135 } 136 137 with open("map.geojson", 'w') as f: 138 print (json.dumps(output), file=f) 139