def create_contours_for_station(departure_station, stations, config, overwrite_existing=False, use_saved_data=False): logger.info(departure_station) max_level = 180 filepaths = [] contourmap = nsmaps.contourmap.Contour(departure_station, stations, config) filepath_geojson = os.path.join( DATA_DIR, 'contours/' + departure_station.get_code() + '.geojson') if not overwrite_existing and os.path.exists(filepath_geojson): print('WARNING: skipping station ' + departure_station.get_code() + ', files already exist.') return filepaths.append(filepath_geojson) if use_saved_data: contourmap.load() else: contourmap.create_contour_data() contourmap.save() levels_minor = numpy.linspace(0, max_level, num=37) contourmap.create_geojson(filepath_geojson, stroke_width=4, levels=levels_minor, overwrite=overwrite_existing)
def recreate_missing_destinations(self, departure_timestamp, dry_run=False): ignore_station_ids = [ 'HRY', 'WTM', 'KRW', 'VMW', 'RTST', 'WIJ', 'SPV', 'SPH' ] for station in self.stations: if not station.has_travel_time_data(): continue stations_missing = self.get_missing_destinations( station.get_travel_time_filepath()) stations_missing_filtered = [] for station_missing in stations_missing: if station_missing.get_code() not in ignore_station_ids: stations_missing_filtered.append(stations_missing) logger.info(station.get_name() + ' has missing station: ' + station_missing.get_name()) if stations_missing_filtered and not dry_run: json_data = self.create_trip_data_from_station( station, departure_timestamp) with open(station.get_travel_time_filepath(), 'w') as fileout: fileout.write(json_data) else: logger.info('No missing destinations for ' + station.get_name() + ' with ' + str(len(ignore_station_ids)) + ' ignored.')
def create_trip_data_from_station(self, station_from, timestamp): """ timestamp format: DD-MM-YYYY hh:mm """ via = "" data = {'stations': []} data['stations'].append({ 'name': station_from.get_name(), 'id': station_from.get_code(), 'travel_time_min': 0, 'travel_time_planned': "0:00" }) nsapi = ns_api.NSAPI(USERNAME, APIKEY) for station in self.stations: if station.get_code() == station_from.get_code(): continue trips = [] try: trips = nsapi.get_trips(timestamp, station_from.get_code(), via, station.get_code()) except TypeError as error: # this is a bug in ns-api, should return empty trips in case there are no results logger.error( 'Error while trying to get trips for destination: ' + station.get_name() + ', from: ' + station_from.get_name()) continue except requests.exceptions.HTTPError as error: # 500: Internal Server Error does always happen for some stations (example are Eijs-Wittem and Kerkrade-West) logger.error( 'HTTP Error while trying to get trips for destination: ' + station.get_name() + ', from: ' + station_from.get_name()) continue if not trips: continue shortest_trip = trips[0] for trip in trips: travel_time = datetime.strptime(trip.travel_time_planned, "%H:%M").time() trip.travel_time_min = travel_time.hour * 60 + travel_time.minute if trip.travel_time_min < shortest_trip.travel_time_min: shortest_trip = trip logger.info(shortest_trip.departure + ' - ' + shortest_trip.destination) data['stations'].append({ 'name': shortest_trip.destination, 'id': self.get_station_code(shortest_trip.destination), 'travel_time_min': shortest_trip.travel_time_min, 'travel_time_planned': shortest_trip.travel_time_planned }) # time.sleep(0.3) # balance load on the NS server json_data = json.dumps(data, indent=4, sort_keys=True, ensure_ascii=False) return json_data
def interpolate_travel_time(q, position, stations, kdtree, gps, latrange, lonrange, altitude, n_nearest, cycle_speed_kmh): # n_nearest: check N nearest stations as best start for cycle route logger.info('interpolate_travel_time') Z = numpy.zeros((int(latrange.shape[0]), int(lonrange.shape[0]))) min_per_m = 1.0 / (cycle_speed_kmh / 60.0 * 1000.0) for i, lat in enumerate(latrange): if i % (len(latrange) / 10) == 0: logger.debug(str(int(i / len(latrange) * 100)) + '%') for j, lon in enumerate(lonrange): x, y, z = gps.lla2ecef([lat, lon, altitude]) distances, indexes = kdtree.query([x, y, z], n_nearest) min_travel_time = sys.float_info.max for distance, index in zip(distances, indexes): if stations[index].travel_time_min is None: continue travel_time = stations[ index].travel_time_min + distance * min_per_m if travel_time < min_travel_time: min_travel_time = travel_time Z[i][j] = min_travel_time data = ContourData() data.index_begin = position data.Z = Z q.put(data) logger.info('end interpolate_travel_time') return
def create_geojson(self, filepath, stroke_width=1, levels=[], norm=None, overwrite=False): if not overwrite and os.path.exists(filepath): logger.error('Output file ' + filepath + ' already exists. Will not override.') return figure = Figure(frameon=False) FigureCanvas(figure) ax = figure.add_subplot(111) # contours = plt.contourf(lonrange, latrange, Z, levels=levels, cmap=plt.cm.plasma) contours = ax.contour(self.lonrange, self.latrange, self.Z, levels=levels, norm=norm, cmap=plt.cm.jet, linewidths=3) ndigits = len(str(int(1.0 / self.config.stepsize_deg))) + 1 logger.info('converting contour to geojson file: ' + filepath) geojsoncontour.contour_to_geojson( contour=contours, geojson_filepath=filepath, contour_levels=levels, min_angle_deg=self.config.min_angle_between_segments, ndigits=ndigits, unit='min', stroke_width=stroke_width) cbar = figure.colorbar(contours, format='%d', orientation='horizontal') cbar.set_label('Travel time [minutes]') # cbar.set_ticks(self.config.colorbar_ticks) ax.set_visible(False) figure.savefig( filepath.replace('.geojson', '') + "_colorbar.png", dpi=90, bbox_inches='tight', pad_inches=0, transparent=True, )
def create_contour_data(self): logger.info('BEGIN') if self.departure_station.has_travel_time_data(): self.stations.travel_times_from_json( self.departure_station.get_travel_time_filepath()) else: logger.error('Input file ' + self.departure_station.get_travel_time_filepath() + ' not found. Skipping station.') start = timer() numpy.set_printoptions(3, threshold=100, suppress=True) # .3f altitude = 0.0 self.Z = numpy.zeros( (int(self.lonrange.shape[0]), int(self.latrange.shape[0]))) gps = nsmaps.utilgeo.GPS() positions = [] for station in self.stations: x, y, z = gps.lla2ecef( [station.get_lat(), station.get_lon(), altitude]) positions.append([x, y, z]) logger.info('starting spatial interpolation') # tree to find nearest neighbors tree = KDTree(positions) queue = Queue() processes = [] if self.config.n_nearest > len(self.stations): self.config.n_nearest = len(self.stations) latrange_per_process = int( len(self.latrange) / self.config.n_processes) for i in range(0, self.config.n_processes): begin = i * latrange_per_process end = (i + 1) * latrange_per_process latrange_part = self.latrange[begin:end] process = Process(target=self.interpolate_travel_time, args=(queue, i, self.stations.stations, tree, gps, latrange_part, self.lonrange, altitude, self.config.n_nearest, self.config.cycle_speed_kmh)) processes.append(process) for process in processes: process.start() # get from the queue and append the values for i in range(0, self.config.n_processes): data = queue.get() index_begin = data.index_begin begin = int(index_begin * len(self.latrange) / self.config.n_processes) end = int((index_begin + 1) * len(self.latrange) / self.config.n_processes) self.Z[0:][begin:end] = data.Z for process in processes: process.join() end = timer() logger.info('finished spatial interpolation in ' + str(end - start) + ' [sec]') logger.info('END')