Exemplo n.º 1
0
def calculate_measurement_matrix(
        service_area_ids,
        locations,
        measurer_name,
        engine=connect.create_db_engine(),
):
    """
    Calculate a measurement matrix for the given service area IDs.

    The measurement between point i and location j in the cell with row i, column j.
    """
    # TODO: Share introduction of this function with calculate.adequacy.
    location_to_id_map = collections.defaultdict(list)
    for j, location in enumerate(locations):
        # TODO - Permanently fix this on the frontend side.
        location.pop('id')
        location_to_id_map[Point(**location)].append(j)

    locations = list(location_to_id_map.keys())
    points = representative_points.minimal_fetch_representative_points(
        service_area_ids=service_area_ids, engine=engine)

    logger.debug('{} pairwise distances to calculate.'.format(
        len(locations) * len(points)))

    measurer = get_measurer(measurer_name)
    measurer_config = config.get('measurer_config')[measurer_name]
    executor_type = measurer_config['adequacy_executor_type']
    n_processors = measurer_config['n_adequacy_processors']

    logger.debug('Starting {} executors for gravity calculations...'.format(
        n_processors))
    with executor_type(processes=n_processors) as executor:
        measurements_by_point = executor.starmap(
            func=_measure_one_to_many,
            iterable=zip(
                points,
                itertools.repeat(locations),
                itertools.repeat(measurer),
            ))

    measurements_by_point = _add_provider_ids(
        measurements_by_point=measurements_by_point,
        location_to_id_map=location_to_id_map)

    measurement_matrix = np.full(shape=(len(points), len(locations)),
                                 fill_value=float('inf'))
    for i, response in enumerate(measurements_by_point):
        for j, distance in zip(response['location_ids'],
                               response['measurements']):
            measurement_matrix[i][j] = distance

    return measurement_matrix
    def test_calculate_accessibility_indexes(self):
        """Test calculate_accessibility_indexes returns an array."""
        measurement_matrix = gravity.calculate_measurement_matrix(
            service_area_ids=self.service_area_ids,
            measurer_name='haversine',
            locations=self.locations,
            engine=engine,
        )
        points = representative_points.minimal_fetch_representative_points(
            service_area_ids=self.service_area_ids, engine=engine)
        decay_function = functools.partial(gravity.uniform_decay,
                                           scale=10.0 * 1609)
        output = gravity.calculate_accessibility_indexes(
            measurement_matrix, points, decay_function)

        assert len(output) == len(points)
        assert np.sum(0.0 < output) == 45
Exemplo n.º 3
0
def calculate_adequacies(service_area_ids,
                         locations,
                         engine,
                         measurer_name,
                         radius_in_meters=RELEVANCY_RADIUS_IN_METERS):
    """
    Calculate adequacies.

    The calculation proceeds as follows:
        - Determine nearby providers for each service area using the radius_in_meters.
        - If no nearby providers are found, use the full provider list.
        - Fetch representative points.
        - Compare each representative point to the subset of nearby providers to determine
            the closest provider.
        - Aggregate the information for each point and return.
    """
    # TODO - Split analyis by specialty.
    location_mapping = collections.defaultdict(list)
    for i, location in enumerate(locations):
        # TODO - Permanently fix this on the frontend side.
        point_id = location.pop('id', i)
        location_mapping[Point(**location)].append(point_id)

    locations = list(location_mapping.keys())

    logger.debug(
        'Calculating adequacies for {} locations ({} unique) and {} service areas using {}.'
        .format(len(locations), len(location_mapping), len(service_area_ids),
                measurer_name))

    points = representative_points.minimal_fetch_representative_points(
        service_area_ids=service_area_ids, engine=engine)

    locations_to_check_by_service_area = _get_locations_to_check_by_service_area(
        service_area_ids=service_area_ids,
        locations=locations,
        engine=engine,
        radius_in_meters=radius_in_meters)

    locations_to_check_by_point = [
        locations_to_check_by_service_area[point['service_area_id']]
        for point in points
    ]

    logger.debug('{} pairwise distances to calculate.'.format(
        str(sum(len(locations) for locations in locations_to_check_by_point))))

    measurer = get_measurer(measurer_name)
    measurer_config = config.get('measurer_config')[measurer_name]
    executor_type = measurer_config['adequacy_executor_type']
    n_processors = measurer_config['n_adequacy_processors']
    exit_distance = measurer_config[
        'exit_distance_in_miles'] * ONE_MILE_IN_METERS

    logger.debug('Starting {} executors for adequacy calculations...'.format(
        n_processors))
    with executor_type(processes=n_processors) as executor:
        adequacies = executor.starmap(func=_find_closest_location,
                                      iterable=zip(
                                          points, locations_to_check_by_point,
                                          itertools.repeat(measurer),
                                          itertools.repeat(exit_distance)))

    adequacies_response = _add_closest_provider_id(adequacies,
                                                   location_mapping)
    logger.debug('Returning adequacy results.')
    return list(adequacies_response)
Exemplo n.º 4
0
 def test_minimal_fetch_representative_points_one_service_area():
     """Test fetch_representative_points as used internally by the backend."""
     service_areas = ['ca_los_angeles_county_00000']
     results = representative_points.minimal_fetch_representative_points(
         service_areas, engine=engine)
     assert len(results) > 1000