1. Why Spatial Data? The Importance of ‘Where’
As data scientists and statisticians, we are experts at extracting
insights from data. We analyze trends, build predictive models, and
uncover hidden patterns. Traditionally, we focus on the
‘what’ (the variables) and the ‘when’
(the time). Spatial statistics adds a critical third dimension: the
‘where’.
Whether you are tracking a disease outbreak, planning aid
distribution, analyzing crime patterns, or modeling climate change, the
location of your data points is not just another variable—it’s a
fundamental part of the story. Events that happen close to each other
are often related. This principle, known as spatial
autocorrelation, is the cornerstone of spatial analysis.
This module will provide you with the foundational vocabulary and
concepts to understand, classify, and work with spatial data. We will
learn the different “shapes” spatial data can take and, most
importantly, how to choose the right type for the right question.
2. The Two Foundational Models: Vector vs. Raster
Before diving into statistical types, we must understand the two
fundamental ways computers store geographic information. All spatial
data falls into one of these two models.
2.1 Vector Data: Drawing with Coordinates
Think of vector data as drawing with coordinates. It
represents the world using discrete, precise geometric objects. Each
object has associated attributes (e.g., the name of a hospital, the type
of a road). There are three types of vector geometries:
- Points: A single coordinate pair (x, y)
representing a specific location.
- When to use: For features that have a location but
no meaningful area or length at your scale of analysis.
- Somalia/Somaliland Example: The location of a
specific hospital in Mogadishu, a water well in a rural village, or an
IDP (Internally Displaced Persons) camp. Each is a distinct, single
point.
- Lines (or Polylines): A sequence of connected
coordinate pairs.
- When to use: For features that have length but not
area, like networks or boundaries.
- Somalia/Somaliland Example: The path of the Jubba
River, the road network connecting Hargeisa and Berbera, or the
administrative border between Puntland and Galmudug.
- Polygons: A series of connected coordinate pairs
that form a closed shape, representing an area.
- When to use: For features that have a defined
boundary and area.
- Somalia/Somaliland Example: The boundary of the
Banaadir region, the area of a national park, or the footprint of a
specific neighborhood in Burao.
Vector data is ideal when you are interested in the features
themselves and their relationships.
2.2 Raster Data: A Grid of Values
Think of raster data as a digital photograph or a
grid. It represents the world as a continuous surface, divided
into a matrix of equally sized cells (or pixels). Each cell has a single
value representing the characteristic of that specific location.
- When to use: For phenomena that vary continuously
across a landscape, with no clear boundaries.
- Somalia/Somaliland Examples:
- Elevation Data (DEM): A grid where each cell’s
value is its elevation above sea level. This is crucial for
understanding topography and flood risk.
- Climate Data: A grid where each cell’s value could
be the average monthly rainfall, temperature, or a vegetation index
(like NDVI) to monitor drought conditions.
- Satellite Imagery: A picture from space where each
pixel has a color value, used to identify land cover (urban, farm,
desert).
Raster data is ideal when you are studying how a measurement
varies over a surface.
Representation |
Discrete points, lines, polygons |
Continuous grid of cells (pixels) |
Structure |
Coordinates and attributes |
Matrix of values |
Best For |
Administrative boundaries, roads, locations |
Elevation, temperature, satellite imagery |
Example |
A shapefile of Somalia’s regions |
A GeoTIFF file of rainfall in the Horn of Africa |
Key Question |
What is where? (e.g., a
hospital) |
How much of something is everywhere?
(e.g., elevation) |
3. The Three Classical Types of Spatial Data
Building on the vector/raster models, spatial statisticians classify
data into three main types based on the nature of the spatial process
being observed. Understanding this classification is key to choosing the
correct statistical methods later on.
3.1 Areal (or Lattice) Data
What it is: Areal data consists of values that are
aggregated over polygons. The domain is a fixed set of
areas, and we have a summary statistic (like a count, average, or rate)
for each one. This is perhaps the most common type of spatial data in
public health and social sciences.
The Key Question it Answers: “How does a value or
count vary from area to area, and are neighboring areas more similar
than distant ones?”
When to Use It and Why: * Privacy:
When individual-level data (like patient addresses) is too sensitive to
share, aggregating to a district or regional level protects
confidentiality. * Administrative Data: Data is often
collected and reported by administrative units (e.g., census bureaus,
ministries of health). * Stable Rates: Calculating
rates (e.g., disease incidence) requires a denominator (population),
which is usually available at an areal level.
Somalia/Somaliland Example: Mapping Malnutrition Cases by
Region Imagine we have the number of severe acute malnutrition
(SAM) cases reported by health facilities in each region of Somaliland.
We want to see if there are regional hotspots.
# Load Somalia administrative boundaries (we'll use this as our base)
# Ensure "som_admbnda_adm1_ocha_20250108.shp" is in your working directory
som_adm1 <- st_read("som_admbnda_adm1_ocha_20250108.shp")
## Reading layer `som_admbnda_adm1_ocha_20250108' from data source
## `C:\Users\Admin\Desktop\Course Spatial Statistics for Data Science\som_admbnda_adm1_ocha_20250108.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 18 features and 10 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 40.99488 ymin: -1.664897 xmax: 51.41303 ymax: 11.9852
## Geodetic CRS: WGS 84
# Filter for Somaliland regions
somaliland_regions <- som_adm1 %>%
filter(ADM1_EN %in% c("Awdal", "Woqooyi Galbeed", "Togdheer", "Sanaag", "Sool"))
# Create some fictional malnutrition data to join
malnutrition_data <- data.frame(
ADM1_EN = c("Awdal", "Woqooyi Galbeed", "Togdheer", "Sanaag", "Sool"),
SAM_cases = c(150, 320, 210, 180, 250)
)
# Join the data to the spatial object
somaliland_map_data <- left_join(somaliland_regions, malnutrition_data, by = "ADM1_EN")
# Plot the areal data
ggplot(data = somaliland_map_data) +
geom_sf(aes(fill = SAM_cases)) +
geom_sf_text(aes(label = ADM1_EN), size = 3) +
scale_fill_viridis_c(name = "SAM Cases") +
ggtitle("Areal Data: Malnutrition Cases by Region in Somaliland") +
theme_void()

3.2 Geostatistical Data
What it is: Geostatistical data consists of
measurements of a continuous phenomenon taken at specific point
locations. We assume the underlying phenomenon (e.g.,
temperature, pollution) exists everywhere, but we can only afford to
sample it at a finite number of sites.
The Key Question it Answers: “Given these sample
points, can we predict the value of the phenomenon at un-sampled
locations? (This is called interpolation or kriging).”
When to Use It and Why: * Environmental
Monitoring: It’s impossible to measure air quality or soil
contamination everywhere. We use monitoring stations (points) to sample
the continuous field. * Resource Exploration:
Geologists drill at specific locations (points) to infer the extent of
an underground oil reserve (a continuous field). * When the
underlying process is truly continuous.
Somalia/Somaliland Example: Measuring Water Salinity at
Wells Imagine we are monitoring the salinity of groundwater at
several wells along the Shabelle River to check for saltwater intrusion.
We want to create a continuous map of salinity from these point
measurements.
# Create a fictional dataset of well locations and salinity measurements
wells_data <- data.frame(
well_id = c("W1", "W2", "W3", "W4", "W5"),
longitude = c(45.0, 45.2, 45.5, 45.8, 46.1),
latitude = c(2.2, 2.5, 2.9, 3.2, 3.5),
salinity_ppm = c(800, 950, 1100, 1500, 2200) # Parts Per Million
)
# Convert the data frame to a spatial sf object
wells_sf <- st_as_sf(wells_data, coords = c("longitude", "latitude"), crs = 4326)
# Plot the points on the map of Somalia
ggplot() +
geom_sf(data = som_adm1, fill = "khaki", color = "grey") + # Base map
geom_sf(data = wells_sf, aes(color = salinity_ppm), size = 4) +
scale_color_viridis_c(name = "Salinity (PPM)") +
ggtitle("Geostatistical Data: Water Salinity at Wells") +
theme_bw()

3.3 Point Pattern Data
What it is: In a point pattern, the
locations of the events are the data themselves. We are
not interested in a value at the point, but rather in the
spatial arrangement of the points. The underlying process is what
generates the locations.
The Key Question it Answers: “Are the events
clustered, randomly distributed, or regularly spaced? What process might
be generating this pattern?”
When to Use It and Why: *
Epidemiology: To see if disease cases are clustered
around a source of infection (e.g., a contaminated water pump). *
Criminology: To identify crime hotspots. *
Ecology: To study the territorial patterns of plants or
animals.
Somalia/Somaliland Example: Mapping Security Incidents in
Mogadishu An NGO is analyzing the locations of reported
security incidents in the Banaadir region (which contains Mogadishu) to
understand if they are concentrated in specific areas.
# Get the polygon for the Banadir region
banadir_region <- som_adm1 %>% filter(ADM1_EN == "Banadir")
# Generate 100 random points *within* the Banadir polygon to simulate incidents
# In a real analysis, these would be actual coordinates of incidents
set.seed(123) # for reproducibility
incident_points <- st_sample(banadir_region, size = 100)
# Plot the point pattern
ggplot() +
geom_sf(data = banadir_region, fill = "grey80") +
geom_sf(data = incident_points, color = "red", alpha = 0.6, size = 2) +
ggtitle("Point Pattern: Simulated Security Incidents in Banadir") +
theme_bw()

4. Summary and A Glimpse Ahead
Understanding these data types is the first and most important step
in any spatial analysis. Choosing the wrong classification can lead to
using inappropriate methods and drawing incorrect conclusions.
Areal |
Aggregated values in polygons |
How do values vary by area? |
Cholera cases per district |
Disease mapping, hotspot detection |
Geostatistical |
Samples of a continuous field |
Can we predict values everywhere? |
Rainfall at weather stations |
Interpolation (Kriging), surface creation |
Point Pattern |
Locations of events |
Is there clustering? |
Locations of IDP camps |
Cluster analysis, density estimation |
In the upcoming modules, we will learn how to use R packages like
sf
and terra
to manipulate these data types
and then apply powerful statistical techniques to answer these key
questions. We will also touch upon more advanced concepts like
spatio-temporal data, which tracks these patterns over
time—for example, mapping the spread of a measles outbreak across
districts over several months. ```
LS0tDQp0aXRsZTogIk1vZHVsZSBJOiBUaGUgTGFuZ3VhZ2Ugb2YgU3BhdGlhbCBEYXRhIg0Kc3VidGl0bGU6ICJBIEZvdW5kYXRpb24gZm9yIFNwYXRpYWwgU3RhdGlzdGljcyBhbmQgRGF0YSBTY2llbmNlIg0KYXV0aG9yOiAiQWJkaXNhbGFtIEhhc3NhbiBNdXNlLCBQaEQiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IHVuaXRlZA0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQ0KIyBMb2FkIG5lY2Vzc2FyeSBwYWNrYWdlcyBmb3IgdGhlIGVudGlyZSBkb2N1bWVudA0KbGlicmFyeShzZikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpgYGANCg0KIyMgMS4gV2h5IFNwYXRpYWwgRGF0YT8gVGhlIEltcG9ydGFuY2Ugb2YgJ1doZXJlJw0KDQpBcyBkYXRhIHNjaWVudGlzdHMgYW5kIHN0YXRpc3RpY2lhbnMsIHdlIGFyZSBleHBlcnRzIGF0IGV4dHJhY3RpbmcgaW5zaWdodHMgZnJvbSBkYXRhLiBXZSBhbmFseXplIHRyZW5kcywgYnVpbGQgcHJlZGljdGl2ZSBtb2RlbHMsIGFuZCB1bmNvdmVyIGhpZGRlbiBwYXR0ZXJucy4gVHJhZGl0aW9uYWxseSwgd2UgZm9jdXMgb24gdGhlICoqJ3doYXQnKiogKHRoZSB2YXJpYWJsZXMpIGFuZCB0aGUgKiond2hlbicqKiAodGhlIHRpbWUpLiBTcGF0aWFsIHN0YXRpc3RpY3MgYWRkcyBhIGNyaXRpY2FsIHRoaXJkIGRpbWVuc2lvbjogdGhlICoqJ3doZXJlJyoqLg0KDQpXaGV0aGVyIHlvdSBhcmUgdHJhY2tpbmcgYSBkaXNlYXNlIG91dGJyZWFrLCBwbGFubmluZyBhaWQgZGlzdHJpYnV0aW9uLCBhbmFseXppbmcgY3JpbWUgcGF0dGVybnMsIG9yIG1vZGVsaW5nIGNsaW1hdGUgY2hhbmdlLCB0aGUgbG9jYXRpb24gb2YgeW91ciBkYXRhIHBvaW50cyBpcyBub3QganVzdCBhbm90aGVyIHZhcmlhYmxl4oCUaXQncyBhIGZ1bmRhbWVudGFsIHBhcnQgb2YgdGhlIHN0b3J5LiBFdmVudHMgdGhhdCBoYXBwZW4gY2xvc2UgdG8gZWFjaCBvdGhlciBhcmUgb2Z0ZW4gcmVsYXRlZC4gVGhpcyBwcmluY2lwbGUsIGtub3duIGFzICoqc3BhdGlhbCBhdXRvY29ycmVsYXRpb24qKiwgaXMgdGhlIGNvcm5lcnN0b25lIG9mIHNwYXRpYWwgYW5hbHlzaXMuDQoNClRoaXMgbW9kdWxlIHdpbGwgcHJvdmlkZSB5b3Ugd2l0aCB0aGUgZm91bmRhdGlvbmFsIHZvY2FidWxhcnkgYW5kIGNvbmNlcHRzIHRvIHVuZGVyc3RhbmQsIGNsYXNzaWZ5LCBhbmQgd29yayB3aXRoIHNwYXRpYWwgZGF0YS4gV2Ugd2lsbCBsZWFybiB0aGUgZGlmZmVyZW50ICJzaGFwZXMiIHNwYXRpYWwgZGF0YSBjYW4gdGFrZSBhbmQsIG1vc3QgaW1wb3J0YW50bHksIGhvdyB0byBjaG9vc2UgdGhlIHJpZ2h0IHR5cGUgZm9yIHRoZSByaWdodCBxdWVzdGlvbi4NCg0KIyMgMi4gVGhlIFR3byBGb3VuZGF0aW9uYWwgTW9kZWxzOiBWZWN0b3IgdnMuIFJhc3Rlcg0KDQpCZWZvcmUgZGl2aW5nIGludG8gc3RhdGlzdGljYWwgdHlwZXMsIHdlIG11c3QgdW5kZXJzdGFuZCB0aGUgdHdvIGZ1bmRhbWVudGFsIHdheXMgY29tcHV0ZXJzIHN0b3JlIGdlb2dyYXBoaWMgaW5mb3JtYXRpb24uIEFsbCBzcGF0aWFsIGRhdGEgZmFsbHMgaW50byBvbmUgb2YgdGhlc2UgdHdvIG1vZGVscy4NCg0KIyMjIyAyLjEgVmVjdG9yIERhdGE6IERyYXdpbmcgd2l0aCBDb29yZGluYXRlcw0KDQpUaGluayBvZiB2ZWN0b3IgZGF0YSBhcyAqKmRyYXdpbmcgd2l0aCBjb29yZGluYXRlcyoqLiBJdCByZXByZXNlbnRzIHRoZSB3b3JsZCB1c2luZyBkaXNjcmV0ZSwgcHJlY2lzZSBnZW9tZXRyaWMgb2JqZWN0cy4gRWFjaCBvYmplY3QgaGFzIGFzc29jaWF0ZWQgYXR0cmlidXRlcyAoZS5nLiwgdGhlIG5hbWUgb2YgYSBob3NwaXRhbCwgdGhlIHR5cGUgb2YgYSByb2FkKS4gVGhlcmUgYXJlIHRocmVlIHR5cGVzIG9mIHZlY3RvciBnZW9tZXRyaWVzOg0KDQoqICAgKipQb2ludHM6KiogQSBzaW5nbGUgY29vcmRpbmF0ZSBwYWlyICh4LCB5KSByZXByZXNlbnRpbmcgYSBzcGVjaWZpYyBsb2NhdGlvbi4NCiAgICAqICAgKipXaGVuIHRvIHVzZToqKiBGb3IgZmVhdHVyZXMgdGhhdCBoYXZlIGEgbG9jYXRpb24gYnV0IG5vIG1lYW5pbmdmdWwgYXJlYSBvciBsZW5ndGggYXQgeW91ciBzY2FsZSBvZiBhbmFseXNpcy4NCiAgICAqICAgKipTb21hbGlhL1NvbWFsaWxhbmQgRXhhbXBsZToqKiBUaGUgbG9jYXRpb24gb2YgYSBzcGVjaWZpYyBob3NwaXRhbCBpbiBNb2dhZGlzaHUsIGEgd2F0ZXIgd2VsbCBpbiBhIHJ1cmFsIHZpbGxhZ2UsIG9yIGFuIElEUCAoSW50ZXJuYWxseSBEaXNwbGFjZWQgUGVyc29ucykgY2FtcC4gRWFjaCBpcyBhIGRpc3RpbmN0LCBzaW5nbGUgcG9pbnQuDQoNCiogICAqKkxpbmVzIChvciBQb2x5bGluZXMpOioqIEEgc2VxdWVuY2Ugb2YgY29ubmVjdGVkIGNvb3JkaW5hdGUgcGFpcnMuDQogICAgKiAgICoqV2hlbiB0byB1c2U6KiogRm9yIGZlYXR1cmVzIHRoYXQgaGF2ZSBsZW5ndGggYnV0IG5vdCBhcmVhLCBsaWtlIG5ldHdvcmtzIG9yIGJvdW5kYXJpZXMuDQogICAgKiAgICoqU29tYWxpYS9Tb21hbGlsYW5kIEV4YW1wbGU6KiogVGhlIHBhdGggb2YgdGhlIEp1YmJhIFJpdmVyLCB0aGUgcm9hZCBuZXR3b3JrIGNvbm5lY3RpbmcgSGFyZ2Vpc2EgYW5kIEJlcmJlcmEsIG9yIHRoZSBhZG1pbmlzdHJhdGl2ZSBib3JkZXIgYmV0d2VlbiBQdW50bGFuZCBhbmQgR2FsbXVkdWcuDQoNCiogICAqKlBvbHlnb25zOioqIEEgc2VyaWVzIG9mIGNvbm5lY3RlZCBjb29yZGluYXRlIHBhaXJzIHRoYXQgZm9ybSBhIGNsb3NlZCBzaGFwZSwgcmVwcmVzZW50aW5nIGFuIGFyZWEuDQogICAgKiAgICoqV2hlbiB0byB1c2U6KiogRm9yIGZlYXR1cmVzIHRoYXQgaGF2ZSBhIGRlZmluZWQgYm91bmRhcnkgYW5kIGFyZWEuDQogICAgKiAgICoqU29tYWxpYS9Tb21hbGlsYW5kIEV4YW1wbGU6KiogVGhlIGJvdW5kYXJ5IG9mIHRoZSBCYW5hYWRpciByZWdpb24sIHRoZSBhcmVhIG9mIGEgbmF0aW9uYWwgcGFyaywgb3IgdGhlIGZvb3RwcmludCBvZiBhIHNwZWNpZmljIG5laWdoYm9yaG9vZCBpbiBCdXJhby4NCg0KKipWZWN0b3IgZGF0YSBpcyBpZGVhbCB3aGVuIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiB0aGUgZmVhdHVyZXMgdGhlbXNlbHZlcyBhbmQgdGhlaXIgcmVsYXRpb25zaGlwcy4qKg0KDQojIyMjIDIuMiBSYXN0ZXIgRGF0YTogQSBHcmlkIG9mIFZhbHVlcw0KDQpUaGluayBvZiByYXN0ZXIgZGF0YSBhcyBhICoqZGlnaXRhbCBwaG90b2dyYXBoIG9yIGEgZ3JpZCoqLiBJdCByZXByZXNlbnRzIHRoZSB3b3JsZCBhcyBhIGNvbnRpbnVvdXMgc3VyZmFjZSwgZGl2aWRlZCBpbnRvIGEgbWF0cml4IG9mIGVxdWFsbHkgc2l6ZWQgY2VsbHMgKG9yIHBpeGVscykuIEVhY2ggY2VsbCBoYXMgYSBzaW5nbGUgdmFsdWUgcmVwcmVzZW50aW5nIHRoZSBjaGFyYWN0ZXJpc3RpYyBvZiB0aGF0IHNwZWNpZmljIGxvY2F0aW9uLg0KDQoqICAgKipXaGVuIHRvIHVzZToqKiBGb3IgcGhlbm9tZW5hIHRoYXQgdmFyeSBjb250aW51b3VzbHkgYWNyb3NzIGEgbGFuZHNjYXBlLCB3aXRoIG5vIGNsZWFyIGJvdW5kYXJpZXMuDQoqICAgKipTb21hbGlhL1NvbWFsaWxhbmQgRXhhbXBsZXM6KioNCiAgICAqICAgKipFbGV2YXRpb24gRGF0YSAoREVNKToqKiBBIGdyaWQgd2hlcmUgZWFjaCBjZWxsJ3MgdmFsdWUgaXMgaXRzIGVsZXZhdGlvbiBhYm92ZSBzZWEgbGV2ZWwuIFRoaXMgaXMgY3J1Y2lhbCBmb3IgdW5kZXJzdGFuZGluZyB0b3BvZ3JhcGh5IGFuZCBmbG9vZCByaXNrLg0KICAgICogICAqKkNsaW1hdGUgRGF0YToqKiBBIGdyaWQgd2hlcmUgZWFjaCBjZWxsJ3MgdmFsdWUgY291bGQgYmUgdGhlIGF2ZXJhZ2UgbW9udGhseSByYWluZmFsbCwgdGVtcGVyYXR1cmUsIG9yIGEgdmVnZXRhdGlvbiBpbmRleCAobGlrZSBORFZJKSB0byBtb25pdG9yIGRyb3VnaHQgY29uZGl0aW9ucy4NCiAgICAqICAgKipTYXRlbGxpdGUgSW1hZ2VyeToqKiBBIHBpY3R1cmUgZnJvbSBzcGFjZSB3aGVyZSBlYWNoIHBpeGVsIGhhcyBhIGNvbG9yIHZhbHVlLCB1c2VkIHRvIGlkZW50aWZ5IGxhbmQgY292ZXIgKHVyYmFuLCBmYXJtLCBkZXNlcnQpLg0KDQoqKlJhc3RlciBkYXRhIGlzIGlkZWFsIHdoZW4geW91IGFyZSBzdHVkeWluZyBob3cgYSBtZWFzdXJlbWVudCB2YXJpZXMgb3ZlciBhIHN1cmZhY2UuKioNCg0KfCBGZWF0dXJlIHwgVmVjdG9yIERhdGEgfCBSYXN0ZXIgRGF0YSB8DQp8IDotLS0gfCA6LS0tIHwgOi0tLSB8DQp8ICoqUmVwcmVzZW50YXRpb24qKiB8IERpc2NyZXRlIHBvaW50cywgbGluZXMsIHBvbHlnb25zIHwgQ29udGludW91cyBncmlkIG9mIGNlbGxzIChwaXhlbHMpIHwNCnwgKipTdHJ1Y3R1cmUqKiB8IENvb3JkaW5hdGVzIGFuZCBhdHRyaWJ1dGVzIHwgTWF0cml4IG9mIHZhbHVlcyB8DQp8ICoqQmVzdCBGb3IqKiB8IEFkbWluaXN0cmF0aXZlIGJvdW5kYXJpZXMsIHJvYWRzLCBsb2NhdGlvbnMgfCBFbGV2YXRpb24sIHRlbXBlcmF0dXJlLCBzYXRlbGxpdGUgaW1hZ2VyeSB8DQp8ICoqRXhhbXBsZSoqIHwgQSBzaGFwZWZpbGUgb2YgU29tYWxpYSdzIHJlZ2lvbnMgfCBBIEdlb1RJRkYgZmlsZSBvZiByYWluZmFsbCBpbiB0aGUgSG9ybiBvZiBBZnJpY2EgfA0KfCAqKktleSBRdWVzdGlvbioqIHwgKldoYXQqIGlzICp3aGVyZSo/IChlLmcuLCBhIGhvc3BpdGFsKSB8ICpIb3cgbXVjaCogb2Ygc29tZXRoaW5nIGlzICpldmVyeXdoZXJlKj8gKGUuZy4sIGVsZXZhdGlvbikgfA0KDQotLS0NCg0KIyMgMy4gVGhlIFRocmVlIENsYXNzaWNhbCBUeXBlcyBvZiBTcGF0aWFsIERhdGENCg0KQnVpbGRpbmcgb24gdGhlIHZlY3Rvci9yYXN0ZXIgbW9kZWxzLCBzcGF0aWFsIHN0YXRpc3RpY2lhbnMgY2xhc3NpZnkgZGF0YSBpbnRvIHRocmVlIG1haW4gdHlwZXMgYmFzZWQgb24gdGhlIG5hdHVyZSBvZiB0aGUgc3BhdGlhbCBwcm9jZXNzIGJlaW5nIG9ic2VydmVkLiBVbmRlcnN0YW5kaW5nIHRoaXMgY2xhc3NpZmljYXRpb24gaXMga2V5IHRvIGNob29zaW5nIHRoZSBjb3JyZWN0IHN0YXRpc3RpY2FsIG1ldGhvZHMgbGF0ZXIgb24uDQoNCiMjIyAzLjEgQXJlYWwgKG9yIExhdHRpY2UpIERhdGENCg0KKipXaGF0IGl0IGlzOioqIEFyZWFsIGRhdGEgY29uc2lzdHMgb2YgdmFsdWVzIHRoYXQgYXJlICoqYWdncmVnYXRlZCBvdmVyIHBvbHlnb25zKiouIFRoZSBkb21haW4gaXMgYSBmaXhlZCBzZXQgb2YgYXJlYXMsIGFuZCB3ZSBoYXZlIGEgc3VtbWFyeSBzdGF0aXN0aWMgKGxpa2UgYSBjb3VudCwgYXZlcmFnZSwgb3IgcmF0ZSkgZm9yIGVhY2ggb25lLiBUaGlzIGlzIHBlcmhhcHMgdGhlIG1vc3QgY29tbW9uIHR5cGUgb2Ygc3BhdGlhbCBkYXRhIGluIHB1YmxpYyBoZWFsdGggYW5kIHNvY2lhbCBzY2llbmNlcy4NCg0KKipUaGUgS2V5IFF1ZXN0aW9uIGl0IEFuc3dlcnM6KiogIkhvdyBkb2VzIGEgdmFsdWUgb3IgY291bnQgdmFyeSBmcm9tIGFyZWEgdG8gYXJlYSwgYW5kIGFyZSBuZWlnaGJvcmluZyBhcmVhcyBtb3JlIHNpbWlsYXIgdGhhbiBkaXN0YW50IG9uZXM/Ig0KDQoqKldoZW4gdG8gVXNlIEl0IGFuZCBXaHk6KioNCiogICAqKlByaXZhY3k6KiogV2hlbiBpbmRpdmlkdWFsLWxldmVsIGRhdGEgKGxpa2UgcGF0aWVudCBhZGRyZXNzZXMpIGlzIHRvbyBzZW5zaXRpdmUgdG8gc2hhcmUsIGFnZ3JlZ2F0aW5nIHRvIGEgZGlzdHJpY3Qgb3IgcmVnaW9uYWwgbGV2ZWwgcHJvdGVjdHMgY29uZmlkZW50aWFsaXR5Lg0KKiAgICoqQWRtaW5pc3RyYXRpdmUgRGF0YToqKiBEYXRhIGlzIG9mdGVuIGNvbGxlY3RlZCBhbmQgcmVwb3J0ZWQgYnkgYWRtaW5pc3RyYXRpdmUgdW5pdHMgKGUuZy4sIGNlbnN1cyBidXJlYXVzLCBtaW5pc3RyaWVzIG9mIGhlYWx0aCkuDQoqICAgKipTdGFibGUgUmF0ZXM6KiogQ2FsY3VsYXRpbmcgcmF0ZXMgKGUuZy4sIGRpc2Vhc2UgaW5jaWRlbmNlKSByZXF1aXJlcyBhIGRlbm9taW5hdG9yIChwb3B1bGF0aW9uKSwgd2hpY2ggaXMgdXN1YWxseSBhdmFpbGFibGUgYXQgYW4gYXJlYWwgbGV2ZWwuDQoNCioqU29tYWxpYS9Tb21hbGlsYW5kIEV4YW1wbGU6IE1hcHBpbmcgTWFsbnV0cml0aW9uIENhc2VzIGJ5IFJlZ2lvbioqDQpJbWFnaW5lIHdlIGhhdmUgdGhlIG51bWJlciBvZiBzZXZlcmUgYWN1dGUgbWFsbnV0cml0aW9uIChTQU0pIGNhc2VzIHJlcG9ydGVkIGJ5IGhlYWx0aCBmYWNpbGl0aWVzIGluIGVhY2ggcmVnaW9uIG9mIFNvbWFsaWxhbmQuIFdlIHdhbnQgdG8gc2VlIGlmIHRoZXJlIGFyZSByZWdpb25hbCBob3RzcG90cy4NCg0KYGBge3IgYXJlYWxfZXhhbXBsZX0NCiMgTG9hZCBTb21hbGlhIGFkbWluaXN0cmF0aXZlIGJvdW5kYXJpZXMgKHdlJ2xsIHVzZSB0aGlzIGFzIG91ciBiYXNlKQ0KIyBFbnN1cmUgInNvbV9hZG1ibmRhX2FkbTFfb2NoYV8yMDI1MDEwOC5zaHAiIGlzIGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnkNCnNvbV9hZG0xIDwtIHN0X3JlYWQoInNvbV9hZG1ibmRhX2FkbTFfb2NoYV8yMDI1MDEwOC5zaHAiKQ0KDQojIEZpbHRlciBmb3IgU29tYWxpbGFuZCByZWdpb25zDQpzb21hbGlsYW5kX3JlZ2lvbnMgPC0gc29tX2FkbTEgJT4lDQogIGZpbHRlcihBRE0xX0VOICVpbiUgYygiQXdkYWwiLCAiV29xb295aSBHYWxiZWVkIiwgIlRvZ2RoZWVyIiwgIlNhbmFhZyIsICJTb29sIikpDQoNCiMgQ3JlYXRlIHNvbWUgZmljdGlvbmFsIG1hbG51dHJpdGlvbiBkYXRhIHRvIGpvaW4NCm1hbG51dHJpdGlvbl9kYXRhIDwtIGRhdGEuZnJhbWUoDQogIEFETTFfRU4gPSBjKCJBd2RhbCIsICJXb3Fvb3lpIEdhbGJlZWQiLCAiVG9nZGhlZXIiLCAiU2FuYWFnIiwgIlNvb2wiKSwNCiAgU0FNX2Nhc2VzID0gYygxNTAsIDMyMCwgMjEwLCAxODAsIDI1MCkNCikNCg0KIyBKb2luIHRoZSBkYXRhIHRvIHRoZSBzcGF0aWFsIG9iamVjdA0Kc29tYWxpbGFuZF9tYXBfZGF0YSA8LSBsZWZ0X2pvaW4oc29tYWxpbGFuZF9yZWdpb25zLCBtYWxudXRyaXRpb25fZGF0YSwgYnkgPSAiQURNMV9FTiIpDQoNCiMgUGxvdCB0aGUgYXJlYWwgZGF0YQ0KZ2dwbG90KGRhdGEgPSBzb21hbGlsYW5kX21hcF9kYXRhKSArDQogIGdlb21fc2YoYWVzKGZpbGwgPSBTQU1fY2FzZXMpKSArDQogIGdlb21fc2ZfdGV4dChhZXMobGFiZWwgPSBBRE0xX0VOKSwgc2l6ZSA9IDMpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJTQU0gQ2FzZXMiKSArDQogIGdndGl0bGUoIkFyZWFsIERhdGE6IE1hbG51dHJpdGlvbiBDYXNlcyBieSBSZWdpb24gaW4gU29tYWxpbGFuZCIpICsNCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0KIyMjIDMuMiBHZW9zdGF0aXN0aWNhbCBEYXRhDQoNCioqV2hhdCBpdCBpczoqKiBHZW9zdGF0aXN0aWNhbCBkYXRhIGNvbnNpc3RzIG9mIG1lYXN1cmVtZW50cyBvZiBhICoqY29udGludW91cyBwaGVub21lbm9uIHRha2VuIGF0IHNwZWNpZmljIHBvaW50IGxvY2F0aW9ucyoqLiBXZSBhc3N1bWUgdGhlIHVuZGVybHlpbmcgcGhlbm9tZW5vbiAoZS5nLiwgdGVtcGVyYXR1cmUsIHBvbGx1dGlvbikgZXhpc3RzIGV2ZXJ5d2hlcmUsIGJ1dCB3ZSBjYW4gb25seSBhZmZvcmQgdG8gc2FtcGxlIGl0IGF0IGEgZmluaXRlIG51bWJlciBvZiBzaXRlcy4NCg0KKipUaGUgS2V5IFF1ZXN0aW9uIGl0IEFuc3dlcnM6KiogIkdpdmVuIHRoZXNlIHNhbXBsZSBwb2ludHMsIGNhbiB3ZSBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgcGhlbm9tZW5vbiBhdCB1bi1zYW1wbGVkIGxvY2F0aW9ucz8gKFRoaXMgaXMgY2FsbGVkIGludGVycG9sYXRpb24gb3Iga3JpZ2luZykuIg0KDQoqKldoZW4gdG8gVXNlIEl0IGFuZCBXaHk6KioNCiogICAqKkVudmlyb25tZW50YWwgTW9uaXRvcmluZzoqKiBJdCdzIGltcG9zc2libGUgdG8gbWVhc3VyZSBhaXIgcXVhbGl0eSBvciBzb2lsIGNvbnRhbWluYXRpb24gZXZlcnl3aGVyZS4gV2UgdXNlIG1vbml0b3Jpbmcgc3RhdGlvbnMgKHBvaW50cykgdG8gc2FtcGxlIHRoZSBjb250aW51b3VzIGZpZWxkLg0KKiAgICoqUmVzb3VyY2UgRXhwbG9yYXRpb246KiogR2VvbG9naXN0cyBkcmlsbCBhdCBzcGVjaWZpYyBsb2NhdGlvbnMgKHBvaW50cykgdG8gaW5mZXIgdGhlIGV4dGVudCBvZiBhbiB1bmRlcmdyb3VuZCBvaWwgcmVzZXJ2ZSAoYSBjb250aW51b3VzIGZpZWxkKS4NCiogICAqKldoZW4gdGhlIHVuZGVybHlpbmcgcHJvY2VzcyBpcyB0cnVseSBjb250aW51b3VzLioqDQoNCioqU29tYWxpYS9Tb21hbGlsYW5kIEV4YW1wbGU6IE1lYXN1cmluZyBXYXRlciBTYWxpbml0eSBhdCBXZWxscyoqDQpJbWFnaW5lIHdlIGFyZSBtb25pdG9yaW5nIHRoZSBzYWxpbml0eSBvZiBncm91bmR3YXRlciBhdCBzZXZlcmFsIHdlbGxzIGFsb25nIHRoZSBTaGFiZWxsZSBSaXZlciB0byBjaGVjayBmb3Igc2FsdHdhdGVyIGludHJ1c2lvbi4gV2Ugd2FudCB0byBjcmVhdGUgYSBjb250aW51b3VzIG1hcCBvZiBzYWxpbml0eSBmcm9tIHRoZXNlIHBvaW50IG1lYXN1cmVtZW50cy4NCg0KYGBge3IgZ2Vvc3RhdGlzdGljYWxfZXhhbXBsZX0NCiMgQ3JlYXRlIGEgZmljdGlvbmFsIGRhdGFzZXQgb2Ygd2VsbCBsb2NhdGlvbnMgYW5kIHNhbGluaXR5IG1lYXN1cmVtZW50cw0Kd2VsbHNfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICB3ZWxsX2lkID0gYygiVzEiLCAiVzIiLCAiVzMiLCAiVzQiLCAiVzUiKSwNCiAgbG9uZ2l0dWRlID0gYyg0NS4wLCA0NS4yLCA0NS41LCA0NS44LCA0Ni4xKSwNCiAgbGF0aXR1ZGUgPSBjKDIuMiwgMi41LCAyLjksIDMuMiwgMy41KSwNCiAgc2FsaW5pdHlfcHBtID0gYyg4MDAsIDk1MCwgMTEwMCwgMTUwMCwgMjIwMCkgIyBQYXJ0cyBQZXIgTWlsbGlvbg0KKQ0KDQojIENvbnZlcnQgdGhlIGRhdGEgZnJhbWUgdG8gYSBzcGF0aWFsIHNmIG9iamVjdA0Kd2VsbHNfc2YgPC0gc3RfYXNfc2Yod2VsbHNfZGF0YSwgY29vcmRzID0gYygibG9uZ2l0dWRlIiwgImxhdGl0dWRlIiksIGNycyA9IDQzMjYpDQoNCiMgUGxvdCB0aGUgcG9pbnRzIG9uIHRoZSBtYXAgb2YgU29tYWxpYQ0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBzb21fYWRtMSwgZmlsbCA9ICJraGFraSIsIGNvbG9yID0gImdyZXkiKSArICMgQmFzZSBtYXANCiAgZ2VvbV9zZihkYXRhID0gd2VsbHNfc2YsIGFlcyhjb2xvciA9IHNhbGluaXR5X3BwbSksIHNpemUgPSA0KSArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhuYW1lID0gIlNhbGluaXR5IChQUE0pIikgKw0KICBnZ3RpdGxlKCJHZW9zdGF0aXN0aWNhbCBEYXRhOiBXYXRlciBTYWxpbml0eSBhdCBXZWxscyIpICsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCiMjIyAzLjMgUG9pbnQgUGF0dGVybiBEYXRhDQoNCioqV2hhdCBpdCBpczoqKiBJbiBhIHBvaW50IHBhdHRlcm4sIHRoZSAqKmxvY2F0aW9ucyBvZiB0aGUgZXZlbnRzIGFyZSB0aGUgZGF0YSB0aGVtc2VsdmVzKiouIFdlIGFyZSBub3QgaW50ZXJlc3RlZCBpbiBhIHZhbHVlICphdCogdGhlIHBvaW50LCBidXQgcmF0aGVyIGluIHRoZSBzcGF0aWFsIGFycmFuZ2VtZW50IG9mIHRoZSBwb2ludHMuIFRoZSB1bmRlcmx5aW5nIHByb2Nlc3MgaXMgd2hhdCBnZW5lcmF0ZXMgdGhlIGxvY2F0aW9ucy4NCg0KKipUaGUgS2V5IFF1ZXN0aW9uIGl0IEFuc3dlcnM6KiogIkFyZSB0aGUgZXZlbnRzIGNsdXN0ZXJlZCwgcmFuZG9tbHkgZGlzdHJpYnV0ZWQsIG9yIHJlZ3VsYXJseSBzcGFjZWQ/IFdoYXQgcHJvY2VzcyBtaWdodCBiZSBnZW5lcmF0aW5nIHRoaXMgcGF0dGVybj8iDQoNCioqV2hlbiB0byBVc2UgSXQgYW5kIFdoeToqKg0KKiAgICoqRXBpZGVtaW9sb2d5OioqIFRvIHNlZSBpZiBkaXNlYXNlIGNhc2VzIGFyZSBjbHVzdGVyZWQgYXJvdW5kIGEgc291cmNlIG9mIGluZmVjdGlvbiAoZS5nLiwgYSBjb250YW1pbmF0ZWQgd2F0ZXIgcHVtcCkuDQoqICAgKipDcmltaW5vbG9neToqKiBUbyBpZGVudGlmeSBjcmltZSBob3RzcG90cy4NCiogICAqKkVjb2xvZ3k6KiogVG8gc3R1ZHkgdGhlIHRlcnJpdG9yaWFsIHBhdHRlcm5zIG9mIHBsYW50cyBvciBhbmltYWxzLg0KDQoqKlNvbWFsaWEvU29tYWxpbGFuZCBFeGFtcGxlOiBNYXBwaW5nIFNlY3VyaXR5IEluY2lkZW50cyBpbiBNb2dhZGlzaHUqKg0KQW4gTkdPIGlzIGFuYWx5emluZyB0aGUgbG9jYXRpb25zIG9mIHJlcG9ydGVkIHNlY3VyaXR5IGluY2lkZW50cyBpbiB0aGUgQmFuYWFkaXIgcmVnaW9uICh3aGljaCBjb250YWlucyBNb2dhZGlzaHUpIHRvIHVuZGVyc3RhbmQgaWYgdGhleSBhcmUgY29uY2VudHJhdGVkIGluIHNwZWNpZmljIGFyZWFzLg0KDQpgYGB7ciBwb2ludF9wYXR0ZXJuX2V4YW1wbGV9DQojIEdldCB0aGUgcG9seWdvbiBmb3IgdGhlIEJhbmFkaXIgcmVnaW9uDQpiYW5hZGlyX3JlZ2lvbiA8LSBzb21fYWRtMSAlPiUgZmlsdGVyKEFETTFfRU4gPT0gIkJhbmFkaXIiKQ0KDQojIEdlbmVyYXRlIDEwMCByYW5kb20gcG9pbnRzICp3aXRoaW4qIHRoZSBCYW5hZGlyIHBvbHlnb24gdG8gc2ltdWxhdGUgaW5jaWRlbnRzDQojIEluIGEgcmVhbCBhbmFseXNpcywgdGhlc2Ugd291bGQgYmUgYWN0dWFsIGNvb3JkaW5hdGVzIG9mIGluY2lkZW50cw0Kc2V0LnNlZWQoMTIzKSAjIGZvciByZXByb2R1Y2liaWxpdHkNCmluY2lkZW50X3BvaW50cyA8LSBzdF9zYW1wbGUoYmFuYWRpcl9yZWdpb24sIHNpemUgPSAxMDApDQoNCiMgUGxvdCB0aGUgcG9pbnQgcGF0dGVybg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBiYW5hZGlyX3JlZ2lvbiwgZmlsbCA9ICJncmV5ODAiKSArDQogIGdlb21fc2YoZGF0YSA9IGluY2lkZW50X3BvaW50cywgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjYsIHNpemUgPSAyKSArDQogIGdndGl0bGUoIlBvaW50IFBhdHRlcm46IFNpbXVsYXRlZCBTZWN1cml0eSBJbmNpZGVudHMgaW4gQmFuYWRpciIpICsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCiMjIDQuIFN1bW1hcnkgYW5kIEEgR2xpbXBzZSBBaGVhZA0KDQpVbmRlcnN0YW5kaW5nIHRoZXNlIGRhdGEgdHlwZXMgaXMgdGhlIGZpcnN0IGFuZCBtb3N0IGltcG9ydGFudCBzdGVwIGluIGFueSBzcGF0aWFsIGFuYWx5c2lzLiBDaG9vc2luZyB0aGUgd3JvbmcgY2xhc3NpZmljYXRpb24gY2FuIGxlYWQgdG8gdXNpbmcgaW5hcHByb3ByaWF0ZSBtZXRob2RzIGFuZCBkcmF3aW5nIGluY29ycmVjdCBjb25jbHVzaW9ucy4NCg0KfCBEYXRhIFR5cGUgfCBXaGF0IGl0IFJlcHJlc2VudHMgfCBLZXkgUXVlc3Rpb24gfCBTb21hbGlhL1NvbWFsaWxhbmQgRXhhbXBsZSB8IENvbW1vbiBHb2FsIHwNCnwgOi0tLSB8IDotLS0gfCA6LS0tIHwgOi0tLSB8IDotLS0gfA0KfCAqKkFyZWFsKiogfCBBZ2dyZWdhdGVkIHZhbHVlcyBpbiBwb2x5Z29ucyB8IEhvdyBkbyB2YWx1ZXMgdmFyeSBieSBhcmVhPyB8IENob2xlcmEgY2FzZXMgcGVyIGRpc3RyaWN0IHwgRGlzZWFzZSBtYXBwaW5nLCBob3RzcG90IGRldGVjdGlvbiB8DQp8ICoqR2Vvc3RhdGlzdGljYWwqKnwgU2FtcGxlcyBvZiBhIGNvbnRpbnVvdXMgZmllbGQgfCBDYW4gd2UgcHJlZGljdCB2YWx1ZXMgZXZlcnl3aGVyZT8gfCBSYWluZmFsbCBhdCB3ZWF0aGVyIHN0YXRpb25zIHwgSW50ZXJwb2xhdGlvbiAoS3JpZ2luZyksIHN1cmZhY2UgY3JlYXRpb24gfA0KfCAqKlBvaW50IFBhdHRlcm4qKnwgTG9jYXRpb25zIG9mIGV2ZW50cyB8IElzIHRoZXJlIGNsdXN0ZXJpbmc/IHwgTG9jYXRpb25zIG9mIElEUCBjYW1wcyB8IENsdXN0ZXIgYW5hbHlzaXMsIGRlbnNpdHkgZXN0aW1hdGlvbiB8DQoNCkluIHRoZSB1cGNvbWluZyBtb2R1bGVzLCB3ZSB3aWxsIGxlYXJuIGhvdyB0byB1c2UgUiBwYWNrYWdlcyBsaWtlIGBzZmAgYW5kIGB0ZXJyYWAgdG8gbWFuaXB1bGF0ZSB0aGVzZSBkYXRhIHR5cGVzIGFuZCB0aGVuIGFwcGx5IHBvd2VyZnVsIHN0YXRpc3RpY2FsIHRlY2huaXF1ZXMgdG8gYW5zd2VyIHRoZXNlIGtleSBxdWVzdGlvbnMuIFdlIHdpbGwgYWxzbyB0b3VjaCB1cG9uIG1vcmUgYWR2YW5jZWQgY29uY2VwdHMgbGlrZSAqKnNwYXRpby10ZW1wb3JhbCBkYXRhKiosIHdoaWNoIHRyYWNrcyB0aGVzZSBwYXR0ZXJucyBvdmVyIHRpbWXigJRmb3IgZXhhbXBsZSwgbWFwcGluZyB0aGUgc3ByZWFkIG9mIGEgbWVhc2xlcyBvdXRicmVhayBhY3Jvc3MgZGlzdHJpY3RzIG92ZXIgc2V2ZXJhbCBtb250aHMuDQpgYGA=