Meta Network Coverage Maps

Meta Network Coverage Maps#

Network Coverage Maps show where people on Facebook have cellular connectivity. This data provides critical information about gaps in cellular network coverage after natural disasters for the purpose of restoring connectivity as well as determining where aid workers and communities will be able to communicate.

Data Collection and Methodology#

This is determined based on the types of cell sites that users connect to in order to update their Facebook app’s data, which causes data to be sent between a user’s device and the Facebook servers that host the app. In other words, this measures the estimated range, approximate coverage area and type of network connection based on the cell site IDs and locations that the users’ devices report. It is not based on data obtained from telecommunication services.

Active Network Coverage This map shows which grid tiles in the region of interest had network coverage on that date. More precisely, we estimate which grid tiles had at least one cell site active on a given day. We assume a cell site is active on a day if we see at least one user pinging that cell site on that date.

Network Coverage Undetected This map shows which grid tiles we are not certain of having network coverage on that date because no users’ devices reported connecting to cell sites there, but where we have observed coverage during the 30-day baseline period. We compare the maximum area where we observed some network coverage in the last 30 days, subtract the areas that had active coverage today and highlight the difference in this map.

Data aggregation: We publish this data in a grid format at Bing tile level 16. This is equivalent to roughly 600 meters on a side near the equator or the size of 2 city blocks.

We estimate if a grid tile lies inside the coverage areas of the nearby cell sites to determine if that tile is served by network coverage. To get the probability score of network coverage at a grid tile, we aggregate the independent probability scores attributed to all nearby cell sites serving that tile.


Population sample: Only the data from Facebook users who have turned on the Location Services device setting on their mobile device contribute to these maps. In regions with few such users, estimates become more uncertain.

Data considerations: In areas affected by a crisis, it is very difficult to distinguish between a nonoperational cell site and one that didn’t receive signals because users have left the area.

We rely on a phone’s reporting of cell IDs, and we have found that different phone models occasionally report different cell IDs for the same physical base station. This leads to overcounting the number of cell sites covering a grid tile.

In addition, those incorrect cell IDs lead to fewer location samples for the correct cell ID and create additional unreliable coverage polygons for the incorrectly reported cell IDs. As we rely on “last known location” for our coverage area estimates, discrepancies between the actual location and the reported location of a user’s device may be included in the samples for any given cell site, especially when the cell site is close to an airport.

color_dict = {'Network Undetected':'blue', 'Network Detected':'green'}
Hide code cell source
fig, axs = plt.subplots(2,2, figsize=(15,15),  gridspec_kw={'hspace': 0.00003})
ax = axs.flatten()
from matplotlib.lines import Line2D

plt.rcParams[""] = "Georgia"

for id, date in enumerate(['2023-09-08', '2023-09-12', '2023-09-16', '2023-09-20']):
    ei_adm4.plot(column='PARAMVALUE', cmap = 'Reds', ax=ax[id],alpha = 0.5)
    morocco_adm1.boundary.plot(ax=ax[id], color = 'lightgrey')
    networkDetected[networkDetected['date']==date].plot(ax=ax[id], color = 'green', markersize=1, label = 'Network Detected', legend = True)
    networkUndetected[networkUndetected['date']==date].plot(ax=ax[id], color = 'blue', markersize=1, label = 'Network Not Detected', legend = True)

    x, y =gdf_adm4[gdf_adm4['PARAMVALUE']== gdf_adm4['PARAMVALUE'].max()]['geometry'].iloc[0].centroid.x, gdf_adm4[gdf_adm4['PARAMVALUE']== gdf_adm4['PARAMVALUE'].max()]['geometry'].iloc[0].centroid.y

    ax[id].scatter(x, y, c='black', marker='o', s=50)



    legend_labels = ['Network Undetected', 'Network Detected']
    handles = [Line2D([0], [0], marker='o', color='w', label=label, markerfacecolor=color_dict[label]) for label in legend_labels]
    ax[0].legend(handles=handles, loc='upper left',  frameon=False)

main_title = fig.suptitle('Network Connectivity in Morocco post Earthquake', fontsize = 14)

subtitle = f'Source: Network Detection from Meta For Good,  Earthquake intensity (Modified Mercalli Intensity) from USGS, Shapefiles from GADM'

fig.text(0, 0.1, subtitle, ha='left', va='center', fontsize=12, color='black', weight='normal')

plt.subplots_adjust(hspace=0, wspace=0)
Hide code cell source
bokeh.core.validation.silence(EMPTY_LAYOUT, True)
bokeh.core.validation.silence(MISSING_RENDERERS, True)

tabs = []

for adm in morocco_adm1['NAME_1'].unique():
    df = networkUndetected_adm2[networkUndetected_adm2['NAME_1']==adm] 
    df = df.groupby(['NAME_1', 'date', 'NAME_2']).sum('no_coverage').reset_index()

        child=get_line_plot(df, f"Grid Plots with Undetected Network", "Source: Data for Good Meta", earthquakes=True, subtitle = '600m plot network post earthquake compared to 90 day prior baseline'),

tabs = Tabs(tabs=tabs, sizing_mode="scale_both")
show(tabs, warn_on_missing_glyphs=False)
Loading BokehJS ...