Vary bleed amount based on population density

There are basically two kinds of 4G masts:

Frequency | Range       | Bandwidth
----------|-------------|----------------------------------
800MHz    | Long (500m) | Low (can handle a bit of traffic)
1800Mhz   | Short (5km) | High (can handle lots of traffic)

The 1800Mhz masts are better in terms of how much traffic they can
handle and how fast a connection they provide. But because they have
quite short range, it’s only economical to install them in very built up
areas†.

In more rural areas the 800MHz masts are better because they cover a
wider area, and have enough bandwidth for the lower population density.

The net effect of this is that cell broadcasts in rural areas are likely
to bleed further, because the masts they are being broadcast from are
less precise.

We can use population density as a proxy for how likely it is to be
covered by 1800Mhz masts, and therefore how much bleed we should expect.
So this commit varies the amount of bleed shown based on the population
density.

I came up with the formula based on 3 fixed points:
- The most remote areas (for example the Scottish Highlands) should have
  the highest average bleed, estimated at 5km
- An town, like Crewe, should have about the same bleed as we were
  estimating before (1.5km) – Pete D thinks this is about right based on
  his knowledge of the area around his office in Crewe
- The most built up areas, like London boroughs, could have as little as
  500m of bleed

Based on these three figures I came up with the following formula, which
roughly gives the right bleed distance (`b`) for each of their population
densities (`d`):
```
b = 5900 - (log10(d) × 1_250)
```

Plotted on a curve it looks like this:

This is based on averages – remember that the UI shows where is _likely_
to receive the alert, based on bleed, not where it’s _possible_ to
receive the alert.

Here’s what it looks like on the map:

---

†There are some additional subtleties which make this not strictly true:
- The 800Mhz masts are also used in built up areas to fill in the gaps
  between the areas covered by the 1800Mhz masts
- Switching between masts is inefficient, so if you’re moving fast
  through a built up area (for example on a train) your phone will only
  use the 800MHz masts so that you have to handoff from one mast to
  another less often
This commit is contained in:
Chris Hill-Scott
2021-03-18 09:37:23 +00:00
parent fb1345494c
commit 738ac1d818
8 changed files with 130 additions and 9 deletions
+27
View File
@@ -1,3 +1,5 @@
import math
from notifications_utils.formatters import formatted_list
from notifications_utils.polygons import Polygons
from notifications_utils.serialised_model import SerialisedModelCollection
@@ -49,6 +51,10 @@ class BroadcastArea(SortableMixin):
BroadcastAreasRepository().get_simple_polygons_for_area(self.id)
)
@cached_property
def simple_polygons_with_bleed(self):
return self.simple_polygons.bleed_by(self.estimated_bleed_in_degrees)
@cached_property
def sub_areas(self):
return [
@@ -68,6 +74,20 @@ class BroadcastArea(SortableMixin):
# https://www.pivotaltracker.com/story/show/174837293
return self._count_of_phones or 0
@property
def phone_density(self):
return self.count_of_phones / self.polygons.estimated_area
@property
def estimated_bleed_in_m(self):
if self.id.endswith(CITY_OF_LONDON.WARDS):
return 500
return 5_900 - (math.log(self.phone_density, 10) * 1_250)
@property
def estimated_bleed_in_degrees(self):
return self.estimated_bleed_in_m / Polygons.approx_metres_to_degree
@cached_property
def parents(self):
return list(filter(None, self._parents_iterator))
@@ -109,6 +129,13 @@ class CustomBroadcastArea:
simple_polygons = polygons
@cached_property
def simple_polygons_with_bleed(self):
# We dont yet have a way of working out the population density
# of a custom area, so for now we have to use an average number
# to estimate the amount of bleed
return self.simple_polygons.bleed_by(Polygons.approx_bleed_in_degrees)
class CustomBroadcastAreas(SerialisedModelCollection):
model = CustomBroadcastArea