Example #1
0
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
Example #2
0
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()
Example #4
0
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
Example #5
0
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))