def data_sources_by_date_range(start_year, end_year, measurement): ''' Gives all data-sources for the specified date range and measurement. ''' start_date = date(start_year, 1, 1) end_date = date(end_year, 12, 31) measurement_id = climatedb.fetch_measurement(measurement)['id'] datasets = climatedb.fetch_datasets_by_date_range(start_date, end_date) if datasets: data_source_ids = {(dataset['data_source_id'], dataset['measurement_id'], dataset['calibrated']) for dataset in datasets} data_sources = [(climatedb.fetch_data_source_by_id(data_source_id), calibrated) for data_source_id, dataset_measurement_id, calibrated in data_source_ids if dataset_measurement_id == measurement_id] selected_data_sources = [ data_source_record for data_source_record, calibrated in data_sources if calibrated or data_source_record['baseline'] ] selected_data_sources.sort( key=lambda data_source_record: data_source_record['name']) return jsonify(selected_data_sources) else: return jsonify({ 'error': 'Could not find date range %d-%d in the datasets' % (start_year, end_year) }), 404
def fetch_nontemporal_value(measurement_code, lat, lon): ''' Fetches the elevation of the specified latitude and longitude from the baseline data source. Returns value, units, data_source ''' data_source_id = climatedb.fetch_baseline_data_source() measurement = climatedb.fetch_measurement(measurement_code) unit = climatedb.fetch_unit('m') dataset = climatedb.fetch_dataset_by_measurement_id( data_source_id, measurement['id'], unit['id']) actual_lat, actual_lon, value = climatedb.fetch_nontemporal_value( dataset, lat, lon) data_source = climatedb.fetch_data_source_by_id(data_source_id) return value, unit['code'], data_source['code']
def main(args): ''' The main function ''' data_source, variable_name, start_date, end_date, calibrated = get_args(args) measurement = transform.to_standard_variable_name(variable_name) units = transform.standard_units_from_measurement(measurement) climatedb.connect() unit_id = climatedb.fetch_unit(units)['id'] measurement_id = climatedb.fetch_measurement(measurement)['id'] data_source_record = climatedb.fetch_data_source(data_source) dataset = climatedb.fetch_dataset( data_source_record['id'], measurement_id, unit_id, start_date, end_date, calibrated=True if calibrated else False ) print(data_source, measurement, start_date.year, end_date.year, 'year') lat_arr, lon_arr, normals = climatedb.fetch_normals_from_dataset_mean(dataset) projected_y_arr = geo.lat2y(lat_arr) projected_x_arr = geo.lon2x(lon_arr) output_folder = tiling.tile_folder(data_source, variable_name, start_date, end_date) tiling.save_contour_tiles( projected_y_arr, projected_x_arr, measurement, units, normals, output_folder, data_source_record['id'] ) for start_month in (12, 3, 6, 9): months = start_month, (start_month + 1) % 12, (start_month + 2) % 12 print(data_source, measurement, start_date.year, end_date.year, months) aggregated_normals = None for month in months: lat_arr, lon_arr, normals = climatedb.fetch_normals_from_dataset(dataset, month) if aggregated_normals is None: aggregated_normals = normals.copy() else: aggregated_normals += normals aggregated_normals = aggregated_normals / len(months) output_folder = tiling.tile_folder(data_source, variable_name, start_date, end_date, months) tiling.save_contour_tiles( projected_y_arr, projected_x_arr, measurement, units, aggregated_normals, output_folder, data_source_record['id'] ) climatedb.close()
def climates_of_places(data_source, start_year, end_year, measurement, period): ''' Gives the list of the most populated places within the specified bounding box, together with the specified measurements. The bounding box must be specified in the min_lat, max_lat, min_lon, and max_lon the GET parameters. ''' try: min_lat = float(request.args.get('min_lat')) max_lat = float(request.args.get('max_lat')) min_lon = float(request.args.get('min_lon')) max_lon = float(request.args.get('max_lon')) except TypeError: return jsonify({'error': 'Invalid coordinates'}), 400 start_date = date(start_year, 1, 1) end_date = date(end_year, 12, 31) measurement_id = climatedb.fetch_measurement(measurement)['id'] if period != 'year': months = [int(month) - 1 for month in period.split('_')] else: months = range(0, 12) geonames = list( geonamedb.fetch_populous_places_within_area(min_lat, max_lat, min_lon, max_lon)) for geoname in geonames: geoname['province'] = geonamedb.get_human_readable_province(geoname) geoname['country'] = geonamedb.get_human_readable_country(geoname) try: data_source_record = climatedb.fetch_data_source(data_source) data_source_id = data_source_record['id'] if data_source_record['baseline']: calibrated = False else: calibrated = True datasets = climatedb.fetch_datasets(data_source_id, start_date, end_date, calibrated) for dataset in datasets: if measurement_id == dataset['measurement_id']: units = climatedb.fetch_unit_by_id(dataset['unit_id'])['code'] for geoname in geonames: lat = geoname['latitude'] lon = geoname['longitude'] try: actual_lat, actual_lon, normals_arr = fetch_normals_by_location( dataset, lat, lon, False) if not np.ma.is_masked(normals_arr[months]): mean = normals_arr[months].mean() geoname[measurement] = [mean, units] except climatedb.NotFoundError: # Presumably the place is in the ocean where there is no data. pass return jsonify(geonames) except climatedb.NotFoundError as e: return jsonify({'error': str(e)}), 404
def calibrate(baseline_data_source_code, historical_data_source_code, projection_data_source_code, measurement, units, baseline_start_date, baseline_end_date, projection_start_date, projection_end_date, month): ''' Adds projected differences to the baseline data. ''' unit_id = climatedb.fetch_unit(units)['id'] measurement_id = climatedb.fetch_measurement(measurement)['id'] baseline_data_source = climatedb.fetch_data_source( baseline_data_source_code) if not baseline_data_source['baseline']: raise Exception('Expected data source %s to be flagged as "baseline"' % baseline_data_source_code) historical_data_source = climatedb.fetch_data_source( historical_data_source_code) projection_data_source = climatedb.fetch_data_source( projection_data_source_code) print('Using historical dataset %s-%d-%d-%s-%s' % (historical_data_source_code, baseline_start_date.year, baseline_end_date.year, measurement, units)) historical_dataset = climatedb.fetch_dataset(historical_data_source['id'], measurement_id, unit_id, baseline_start_date, baseline_end_date, calibrated=False) historical_lat, historical_lon, historical_data = climatedb.fetch_normals_from_dataset( historical_dataset, month) print('And projection dataset %s-%d-%d-%s-%s' % (projection_data_source_code, projection_start_date.year, projection_end_date.year, measurement, units)) projection_dataset = climatedb.fetch_dataset(projection_data_source['id'], measurement_id, unit_id, projection_start_date, projection_end_date, calibrated=False) projection_lat, projection_lon, projection_data = climatedb.fetch_normals_from_dataset( projection_dataset, month) if projection_data.shape != historical_data.shape: raise Exception( 'Expected historical data to have the same shape as projection') if np.any(projection_lat != historical_lat): raise Exception( 'Expected historical latitudes to be the same as projection latitudes' ) if np.any(projection_lon != historical_lon): raise Exception( 'Expected historical longitudes to be the same as projection longitudes' ) if measurement in ABSOLUTE_DIFFERENCE_MEASUREMENTS: print('Using absolute difference') differences = projection_data - historical_data else: print('Using relative difference') differences = projection_data / historical_data abs_differences = projection_data - historical_data print('Against baseline dataset %s-%d-%d-%s-%s' % (baseline_data_source_code, baseline_start_date.year, baseline_end_date.year, measurement, units)) baseline_dataset = climatedb.fetch_dataset(baseline_data_source['id'], measurement_id, unit_id, baseline_start_date, baseline_end_date, calibrated=False) baseline_lat, baseline_lon, baseline_data = climatedb.fetch_normals_from_dataset( baseline_dataset, month) downscaled_differences = arrays.downscale_array( baseline_lat, baseline_lon, projection_lat, projection_dataset['lat_delta'], projection_lon, projection_dataset['lon_delta'], differences) if downscaled_differences.shape != baseline_data.shape: raise Exception( 'Expected downscaled differences to have the same shape as baseline data' ) if measurement in ABSOLUTE_DIFFERENCE_MEASUREMENTS: calibrated_data = baseline_data + downscaled_differences else: downscaled_abs_differences = arrays.downscale_array( baseline_lat, baseline_lon, projection_lat, projection_dataset['lat_delta'], projection_lon, projection_dataset['lon_delta'], abs_differences) calibrated_data = np.round(baseline_data * downscaled_differences) above_threshold = above_absolute_threshold(calibrated_data, downscaled_differences, downscaled_abs_differences) calibrated_data[above_threshold] = baseline_data[ above_threshold] + downscaled_abs_differences[above_threshold] pack.mask_out_of_bounds(calibrated_data) calibrated_data = calibrated_data.astype(pack.OUTPUT_DTYPE) climatedb.save_normals(baseline_lat, baseline_lon, units, calibrated_data, measurement, projection_start_date, projection_end_date, month, projection_data_source['code'], calibrated=True) print('Created calibrated dataset %s-%d-%d-%s-%s-calibrated' % (projection_data_source_code, projection_start_date.year, projection_end_date.year, measurement, units))