Week 4

Raster Data

Learning Objectives

  • Understand: difference between vector (objects) and raster (fields)
  • Describe: raster structure (extent, resolution, CRS, layers)
  • Demonstrate: basic terra workflows (read, crop, mask, aggregate)
  • Apply: simple raster algebra and zonal/focal/global operations
  • Interpret: examples of raster analyses (elevation, clustering)

Recap: sf and spatial concepts

  • Spatial phenomena can be thought of as discrete objects with clear boundaries or as continuous phenomena that can be observed everywhere, with no natural boundaries.

  • We have described these as objects and fields (Kuhn, 2012)

  • Objects are usually represented by vector data consisting of:

    • a geometry (simple features (sfc, sfg))
    • some attribute information (data.frame)
  • In R these are unified as a sf object

  • Field data is typically represented by raster data

  • For this, we will begin our discussions using the terra package

terra

  • Like sf, terra is an implementation of the standard raster data model

  • The model is used by all GIS platforms

  • Continuous data can be represented either as continuous or categorical values on a regular grid of cells (a matrix).

  • Cells have: (1) a resolution, (2) an inferred coordinate, typically referenced by centroid, and (3) a value that applies to the entire cell area.

Recap: R data structures

  • Vector:

    • A vector can have dimensions
      • A 1D vector is a collection of values
      • A 2D vector is a matrix
      • A 3D vector is an array
  • List: a collection of objects

  • data.frame: a list with requirement of equal length column (vectors)

  • data.frames and lists (sfc) defined our vector model

  • Arrays will define our raster model

Spatial Extent

One last topic with respect to vector data (that will carry us into raster) is the idea of an extent:

(ny <- AOI::aoi_get(state = "NY") |> 
   st_transform(5070) |> 
   dplyr::select(name))
#> Simple feature collection with 1 feature and 1 field
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 1319503 ymin: 2149150 xmax: 1997508 ymax: 2658544
#> Projected CRS: NAD83 / Conus Albers
#>       name                       geometry
#> 1 New York MULTIPOLYGON (((1661336 263...

In geometry, the minimum bounding box for a point set (stored as POINT, POLYLINE, POLYGON) in N dimensions is “…the box with the smallest measure within which all the points lie.”

We can extract bounding box coordinates with st_bbox

  • returns: an object of class bbox of length 4.
(bb = st_bbox(ny))
#>    xmin    ymin    xmax    ymax 
#> 1319503 2149150 1997508 2658544

class(bb)
#> [1] "bbox"

typeof(bb)
#> [1] "double"

There is a method for creating an sfc from a bbox object

(bb = st_as_sfc(bb))
#> Geometry set for 1 feature 
#> Geometry type: POLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 1319503 ymin: 2149150 xmax: 1997508 ymax: 2658544
#> Projected CRS: NAD83 / Conus Albers

class(bb)
#> [1] "sfc_POLYGON" "sfc"

typeof(bb)
#> [1] "list"

Result:

plot(bb, border = rgb(0,0,1))
plot(ny, add = TRUE, col = rgb(1,0,0, .5))

Extents can be discretized in a number of ways:

grid = st_make_grid(bb)
plot(ny$geometry)
plot(grid, add = TRUE)

grid1km = st_make_grid(bb, cellsize = 10000)
plot(ny$geometry)
plot(grid1km, add = TRUE)

What makes a regular tessellation

A regular tessellation has three key properties:

  • all cells have the same size and shape
  • there are no gaps or overlaps
  • the full extent is covered
length(grid1km) # how many grid cells?
#> [1] 3468
sqrt(st_area(grid1km)[1]) # side length of each cell
#> 10000 [m]
st_bbox(grid1km) # extent of the grid
#>    xmin    ymin    xmax    ymax 
#> 1319503 2149150 1999503 2659150
mapview::npts(grid1km) # how many points?
#> [1] 17340
mapview::npts(grid1km) * 2 # how many X and Y?
#> [1] 34680
mapview::npts(grid1km) / length(grid1km) # how many points per tile?
#> [1] 5
sqrt(st_area(grid1km)[1]) # length of each tile?
#> 10000 [m]
st_bbox(grid1km) # extent of grid
#>    xmin    ymin    xmax    ymax 
#> 1319503 2149150 1999503 2659150

Alternative representation

Regular grids can also be indexed by their centroids

cent <- st_centroid(grid1km)

plot(ny$geometry)
plot(cent, add = TRUE, pch = 16, cex = .25)
length(cent) # how many grid tiles
#> [1] 3468

mapview::npts(grid1km) # how many points?
#> [1] 17340

mapview::npts(grid1km) * 2 # how many X and Y?
#> [1] 34680

Equal area from centroid

We can use our voronoi diagram to show that the area closest to a cell centroid is the cell itself.

vor = st_union(cent) |> 
  st_voronoi() |> 
  st_cast() |> 
  st_intersection(bb)

plot(ny$geometry); plot(vor, add = TRUE)

Raster Model

  • The raster model is one of the earliest and most widely used data models within geographic information systems (Tomlin, 1990; Goodchild, 1992, Maguire, 1992).

  • Typically used to record, analyze and visualize data with a continuous nature such as elevation, temperature (“GIS”), or reflected or emitted electromagnetic radiation (“Remote Sensing”)

  • Quotes are used because you’ll find from a data perspective these differences are artificial and a product of the ESRI/ENVI/ERDAS divide

  • The term raster originated from the German word for screen, implying a series of orthogonality oriented parallel lines.

  • Digital raster objects most often take the form of a regularly spaced, grid-like pattern of rows and columns

  • Each element referred to as a cell, pixel, or grid point.

Many terms mean the same thing …

  • The entire raster is sometimes referred to as an “image”, “array”, “surface”, “matrix”, or “lattice” (Wise, 2000).

  • They all mean the same thing.

  • Cells of the raster are most often square, but may be rectangular (with differing resolutions in x and y directions) or other shapes that can be tessellated such as triangles and hexagons (Figure below from Peuquet, 1984).

Photos and Computers …

Aerial Imagery (really just a photo 😄)

What is stored in these cells?

Categorical Values (integer/factor)

Continuous Values (numeric)

Spectral Values

  • Either Color, or sensor

Any digital image contains an RGB channel for color:

  • Red, green, and blue are the three additive colors (primary colors of light)

  • In R, colors can be defined using the RGB channels

(rgb(1,0,0)) # red
#> [1] "#FF0000"
(rgb(0,.54,.96)) # UCSB navy
#> [1] "#008AF5"
(rgb(254,188,17, maxColorValue = 255)) # UCSB navy
#> [1] "#FEBC11"

Pure RGB

par(mfrow = c(1,3), mar = c(0,0,0,0))
plot(ny$geometry,   col = rgb(1,0,0)) # red
plot(ny$geometry,   col = rgb(0,1,0)) # green
plot(ny$geometry,   col = rgb(0,0,1)) # blue

RGB and bytes/bits

  • The red, green and blue use 8 bits each (1 byte), which each have integer values from 0 to 255.

  • This makes 256^3 = 16,777,216 possible colors.

  • See more here

  • How does this relate to the selection of 256x256 pixel tiles in web maps?

RGB values are what matter most for raster imagery in this course.

  • Digital images store color with red, green, and blue channels.
  • Printers use a different system (CMYK), but the core idea is the same: color is encoded numerically.
  • For us, the important takeaway is that image rasters store values by channel.
par(mfrow = c(1,4), mar = c(0,0,0,0))
plot(ny$geometry, col = rgb(0,1,1))  # cyan
plot(ny$geometry, col = rgb(1,0,1)) # Magenta
plot(ny$geometry, col = rgb(1,1,0)) # Yellow
plot(ny$geometry, col = rgb(0,0,0)) # black

Why do we care?

  • Pixels are the base unit of raster data and have a resolution

  • This is the X and the Y dimension of each cell in the units of the CRS

Resolution drives image clarity (granularity)

  • Higher resolution (smaller cells) = more detail, but bigger data!

Raster images seek to discretize the real world into cell-based values

  • Again either integer (categorical), continuous, or signal

All rasters have an extent!

  • This is the same extent as a bounding box
  • Can be described as 4 values (xmin,ymin,xmax,ymax)

Implicit Coordinates

  • Unlike vector data, the raster data model stores cell coordinates indirectly.

  • Coordinates are derived from the raster origin, the resolution, and the cell index (for example, row 100 and column 150).

  • In practice, the column position determines movement in the x-direction and the row position determines movement in the y-direction. Cell-center coordinates are inferred from that structure rather than stored one by one.

  • So, any image (.png, .tif, .gif) can be read as a raster…

  • The raster is defined by the extent and resolution of the cells

  • To be spatial, the extent (and thus the coordinates) must be grounded in a CRS

(img = terra::rast('img/17-raster-extent.png'))
#> class       : SpatRaster 
#> size        : 788, 1067, 4  (nrow, ncol, nlyr)
#> resolution  : 1, 1  (x, y)
#> extent      : 0, 1067, 0, 788  (xmin, xmax, ymin, ymax)
#> coord. ref. :  
#> source      : 17-raster-extent.png 
#> names       : 17-rast~xtent_1, 17-rast~xtent_2, 17-rast~xtent_3, 17-rast~xtent_4
terra::plotRGB(img, r = 1, g = 2, b = 3)

Raster Data in R

A SpatRast represents single-layer (variable) raster data.

A SpatRast always stores the fundamental parameters that describe it. - The number of columns and rows, - The spatial extent - The Coordinate Reference System.

In addition, a SpatRast can store information about the file where raster values are stored (if there is such a file).

Here we construct an empty raster:

(r <- rast(ncol=20, nrow=20, xmax=-80, xmin=-120, ymin=20, ymax=60))
#> class       : SpatRaster 
#> size        : 20, 20, 1  (nrow, ncol, nlyr)
#> resolution  : 2, 2  (x, y)
#> extent      : -120, -80, 20, 60  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84)

Extract Dimensionality …

nrow(r)
#> [1] 20
ncol(r)
#> [1] 20
ncell(r)
#> [1] 400
nlyr(r)
#> [1] 1

Raster Values

values can be extracted with values()

head(values(r))
#>      lyr.1
#> [1,]   NaN
#> [2,]   NaN
#> [3,]   NaN
#> [4,]   NaN
#> [5,]   NaN
#> [6,]   NaN

Assigning values as a vector

values(r) <- 1:ncell(r)

r
#> class       : SpatRaster 
#> size        : 20, 20, 1  (nrow, ncol, nlyr)
#> resolution  : 2, 2  (x, y)
#> extent      : -120, -80, 20, 60  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84) 
#> source(s)   : memory
#> name        : lyr.1 
#> min value   :     1 
#> max value   :   400

head(values(r))
#>      lyr.1
#> [1,]     1
#> [2,]     2
#> [3,]     3
#> [4,]     4
#> [5,]     5
#> [6,]     6
plot(r)

Raster is S4

  • Compared to S3, the S4 object system is stricter and closer to other object-oriented systems.

  • What does this mean for us?

  • A SpatRaster is a formal object with a defined representation.

  • In practice, that means it has structured components and methods for things like extent, CRS, dimensions, and values. Slots can be accessed with @, even though we will usually prefer accessor functions.

str(r, max.level = 2)
#> S4 class 'SpatRaster' [package "terra"]
r@pntr
#> C++ object <0x11f011920> of class 'SpatRaster' <0x162343ab0>
r@pntr$ncol
#> Class method definition for method ncol()
#> function () 
#> {
#>     " unsigned long ncol()  \n   docstring : ncol"
#>     .External(list(name = "CppMethod__invoke_notvoid", address = <pointer: 0x10306d100>, 
#>         dll = list(name = "Rcpp", path = "/Users/mikejohnson/Library/R/arm64/4.4/library/Rcpp/libs/Rcpp.so", 
#>             dynamicLookup = TRUE, handle = <pointer: 0x73c71650>, 
#>             info = <pointer: 0x1030088d0>, forceSymbols = FALSE), 
#>         numParameters = -1L), <pointer: 0x162343ab0>, <pointer: 0x16233b560>, 
#>         .pointer)
#> }
#> <environment: 0x17552e3c8>

Access via Function

ext(r)
#> SpatExtent : -120, -80, 20, 60 (xmin, xmax, ymin, ymax)
crs(r)
#> [1] "GEOGCRS[\"WGS 84 (CRS84)\",\n    DATUM[\"World Geodetic System 1984\",\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"unknown\"],\n        AREA[\"World\"],\n        BBOX[-90,-180,90,180]],\n    ID[\"OGC\",\"CRS84\"]]"
nrow(r)
#> [1] 20
ncol(r)
#> [1] 20
head(values(r))
#>      lyr.1
#> [1,]     1
#> [2,]     2
#> [3,]     3
#> [4,]     4
#> [5,]     5
#> [6,]     6

Multi-layers

In many cases, multi-variable raster datasets are used. Variables can be related to time or measurement.

A SpatRaster is a collection of objects with the same spatial extent and resolution.

In essence it is a list of objects, or a 3D array.

Remember our Array data?

(v = 1:27)
#>  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#> [26] 26 27
(arr = array(v, dim = c(3,3,3)))
#> , , 1
#> 
#>      [,1] [,2] [,3]
#> [1,]    1    4    7
#> [2,]    2    5    8
#> [3,]    3    6    9
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3]
#> [1,]   10   13   16
#> [2,]   11   14   17
#> [3,]   12   15   18
#> 
#> , , 3
#> 
#>      [,1] [,2] [,3]
#> [1,]   19   22   25
#> [2,]   20   23   26
#> [3,]   21   24   27

An array is a single file so it can be “rasterized”

b = rast(arr)
plot(b)

Core Raster Principles

1. Bounding Box / Extents

Geometries have extents that define the maximum and minimum coverage of the shape in a coordinate reference system

Image Source: National Ecological Observatory Network (NEON)

2. Extent

  • When dealing with objects, the extent (or bbox) is derived from the coordinate set

  • When dealing with raster data, the extent is a foundational component of the raster data structure

    • That is, we need to know the area the raster is covering!

Image Source: National Ecological Observatory Network (NEON)

3. Discretization

Once we know the extent, we need to know how that space is split up

Two complementary pieces of information tell us this:

  • Resolution (res)
  • Number of row and number of columns (nrow/ncol)

Image Source: National Ecological Observatory Network (NEON)

So,

A raster is made of an extent and a resolution / row-column structure

  • A vector of values fills that structure (the same way a vector in R can have dimensions)

    • These values are often scaled to integers to reduce file size
  • Values are referenced in Cartesian space based on cell index

  • A CRS, together with the extent, provides spatial reference / coordinates

General Process

Almost all remote sensing / image analysis begins with the same basic steps:

  1. Identifying an area of interest (AOI)

  2. Identifying and downloading the relevant images or products

  3. Analyzing the raster products

The definition of an AOI is critical because raster data are continuous, so we define the bounds of the study rather than the bounds of objects.

  • But, objects often (even typically) define our bounds

Find elevation data for Fort Collins:

  1. Define the AOI
bb = read_csv("../labs/data/uscities.csv") |>
  st_as_sf(coords = c("lng", "lat"), crs = 4326) |> 
  filter(city == "Fort Collins") |> 
  st_transform(5070) |> 
  st_buffer(50000) |> 
  st_bbox() |> 
  st_as_sfc() |> 
  st_as_sf()
  • Read data from elevation map tiles, for a specific zoom, and crop to the AOI
elev = elevatr::get_elev_raster(bb, z = 11) |> crop(bb)
writeRaster(elev, filename = "data/foco-elev.tif", overwrite = TRUE)
  • The resulting raster …
(elev = rast("data/foco-elev.tif"))
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source      : foco-elev.tif 
#> name        : foco-elev 
#> min value   :      1382 
#> max value   :      4346

Raster Values Continuity

v = values(elev)
class(v)
#> [1] "matrix" "array"
length(v)
#> [1] 11902500
elev
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source      : foco-elev.tif 
#> name        : foco-elev 
#> min value   :      1382 
#> max value   :      4346

Raster Values

# The length of the vector is equal to the rows * columns
length(v) == nrow(elev) * ncol(elev)
#> [1] TRUE
# The span of the x extent divided by the resolution equals the raster rows
((xmax(elev) - xmin(elev)) / res(elev)[1]) == ncol(elev) 
#> [1] TRUE
# The span of the x extent divided by the number of rows equals the raster resolution
((xmax(elev) - xmin(elev)) / ncol(elev)) == res(elev)[1] 
#> [1] TRUE

All image files are the same!

download.file(url = "https://a.tile.openstreetmap.org/18/43803/104352.png",
              destfile = "data/104352.png")
img = png::readPNG("data/104352.png")
class(img)
#> [1] "array"
typeof(img)
#> [1] "double"
dim(img)
#> [1] 256 256   3

img[1,1,1:3]
#> [1] 1.0000000 1.0000000 0.9333333
rgb(1.0000000, 0.9607843, 0.8980392)
#> [1] "#FFF5E5"

Google Color Picker

Raster Algebra

  • So our raster data is stored as a large numeric array/vector

  • Many generic functions allow for simple algebra on Raster objects,

  • These include:

    • normal algebraic operators such as +, -, *, /

    • logical operators such as >, >=, <,==, !

    • functions like abs, round, ceiling, floor, trunc, sqrt, log, log10, exp, cos, sin, atan, tan, max, min, range, prod, sum, any, all

Raster Algebra

  • Raster algebra works cell by cell, while preserving the raster’s extent, resolution, and CRS.

  • You can combine raster objects with constants, logical comparisons, and many mathematical functions.

For example:

elev + 100
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source(s)   : memory
#> varname     : foco-elev 
#> name        : foco-elev 
#> min value   :      1482 
#> max value   :      4446
log10(elev)
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source(s)   : memory
#> varname     : foco-elev 
#> name        : foco-elev 
#> min value   :  3.140508 
#> max value   :  3.638090
elev > 2000
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source(s)   : memory
#> varname     : foco-elev 
#> name        : foco-elev 
#> min value   :     FALSE 
#> max value   :      TRUE

Replacement

  • Raster values can be replaced using conditional statements
  • Doing this changes the underlying data!
  • If you want to retain the original data, you must make a copy of the base layer
plot(elev)

elev2 = elev #<<
elev2[elev2 <= 1500] = NA #<<
plot(elev2)

Modifying a raster

When we want to modify the extent of a raster we can clip it to a new bounds

crop: lets you reduce the extent of a raster to the extent of another, overlapping object:

#remotes::install_github("mikejohnson51/AOI")
fc = AOI::geocode("Fort Collins", bbox = TRUE) |> 
  st_transform(crs(elev))

plot(elev)
plot(fc, add = TRUE, col = NA)

fc_elev = crop(elev, fc) #<<
plot(fc_elev)

Modifying the underlying data:

mask: mask takes an input object (sf, sp, or raster) and sets anything not underlying the input to a new value (default = NA)

library(osmdata)

# Note: Wrapped in try() because Overpass API may timeout
osm <- try({
  osmdata::opq(st_bbox(st_transform(fc, 4326))) |> 
    add_osm_feature("water") |> 
    osmdata_sf()
}, silent = FALSE)
#> Error in httr2::req_perform(req) : HTTP 504 Gateway Timeout.

# If successful, extract polygons
if (!inherits(osm, "try-error") && !is.null(osm$osm_polygons)) {
  poly <- osm$osm_polygons |> st_transform(crs(elev))
  cat("Water features loaded from OpenStreetMap\n")
} else {
  cat("Note: Overpass API unavailable; using demo water feature instead\n")
  # Fallback: create a simple water feature within the Fort Collins extent
  fc_center <- st_centroid(fc)
  poly <- st_buffer(fc_center, 500) |>  # 500m buffer around city center
    st_as_sf()
}
#> Note: Overpass API unavailable; using demo water feature instead

poly
#> Simple feature collection with 1 feature and 5 fields
#> Geometry type: POLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -761615.9 ymin: 1988855 xmax: -760615.9 ymax: 1989855
#> Projected CRS: PROJCRS["unknown",
#>     BASEGEOGCRS["NAD83",
#>         DATUM["North American Datum 1983",
#>             ELLIPSOID["GRS 1980",6378137,298.257222101004,
#>                 LENGTHUNIT["metre",1]]],
#>         PRIMEM["Greenwich",0,
#>             ANGLEUNIT["degree",0.0174532925199433]],
#>         ID["EPSG",4269]],
#>     CONVERSION["Albers Equal Area",
#>         METHOD["Albers Equal Area",
#>             ID["EPSG",9822]],
#>         PARAMETER["Latitude of false origin",23,
#>             ANGLEUNIT["degree",0.0174532925199433],
#>             ID["EPSG",8821]],
#>         PARAMETER["Longitude of false origin",-96,
#>             ANGLEUNIT["degree",0.0174532925199433],
#>             ID["EPSG",8822]],
#>         PARAMETER["Latitude of 1st standard parallel",29.5,
#>             ANGLEUNIT["degree",0.0174532925199433],
#>             ID["EPSG",8823]],
#>         PARAMETER["Latitude of 2nd standard parallel",45.5,
#>             ANGLEUNIT["degree",0.0174532925199433],
#>             ID["EPSG",8824]],
#>         PARAMETER["Easting at false origin",0,
#>             LENGTHUNIT["metre",1],
#>             ID["EPSG",8826]],
#>         PARAMETER["Northing at false origin",0,
#>             LENGTHUNIT["metre",1],
#>             ID["EPSG",8827]]],
#>     CS[Cartesian,2],
#>         AXIS["easting",east,
#>             ORDER[1],
#>             LENGTHUNIT["metre",1,
#>                 ID["EPSG",9001]]],
#>         AXIS["northing",north,
#>             ORDER[2],
#>             LENGTHUNIT["metre",1,
#>                 ID["EPSG",9001]]]]
#>        request score         arcgis_address         x        y
#> 1 Fort Collins   100 Fort Collins, Colorado -105.0825 40.58897
#>                         geometry
#> 1 POLYGON ((-760615.9 1989355...

plot(fc_elev)
plot(poly, col = "blue", add  = TRUE)

ma =  mask(fc_elev, poly)
ma2 = mask(fc_elev, poly, inverse = TRUE)
plot(c(fc_elev, ma, ma2))

What is mask doing?

NA * 7
#> [1] NA
mask_r = rasterize(poly, fc_elev, background = NA)
plot(mask_r)

base_mask = mask_r * fc_elev
plot(base_mask)

Crop or/and mask

  • Crop is more efficient then mask
  • Often you will want to mask and crop a raster
  • The correct way to do this is crop then mask
cm = crop(fc_elev, poly) |>  
  mask(poly)

plot(cm)

Aggregate and disaggregate

  • aggregate and disaggregate allow for changing the resolution of a Raster object.

  • This is similar to the zoom scaling on a web map except the scale factor is not set to 2

  • For aggregate, you need to specify a function determining what to do with the grouped cell values (default = mean).

plot(fc_elev)
plot(rpoly, add = T)

agg = aggregate(fc_elev, 10, fun = max) #<<
plot(agg)
plot(rpoly, add = T)

app

Just like a vector, we can apply functions over a raster with app

These types of formulas are very useful for thresholding analysis

Question: separate Fort Collins into the higher and lower elevations

FUN = function(x){ ifelse(x < mean(x), 1, 2) }
elev3 = app(elev, FUN) #<<
plot(elev3, col = c("red", "blue"))

Read in the saved raster file

(r = rast("data/foco-elev.tif"))
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source      : foco-elev.tif 
#> name        : foco-elev 
#> min value   :      1382 
#> max value   :      4346

Create a conditional (threshold) mask

threshold = function(x) {ifelse(x <= 1520 , NA, 1)}
threshold(1600)
#> [1] 1
threshold(-100)
#> [1] NA
(m = app(r, threshold))
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source(s)   : memory
#> name        : lyr.1 
#> min value   :     1 
#> max value   :     1

Results

plot(r)

plot(m)

Multiply cell-wise

  • algebraic, logical, and functional operations act on a raster cell-wise
elev_cut = m * r
plot(elev_cut, col = viridis::viridis(256))

Reclassify

  • Reclassify is a function that allows you to change the values of a raster based on a set of rules

  • The rules are defined in a data frame with three columns:

    • min = the minimum value of the range
    • max = the maximum value of the range
    • lab = the new value to assign to that range
(rcl = data.frame(min = seq(1500,1590,10), max =  seq(1510,1600,10), lab = c(0:9)))
#>     min  max lab
#> 1  1500 1510   0
#> 2  1510 1520   1
#> 3  1520 1530   2
#> 4  1530 1540   3
#> 5  1540 1550   4
#> 6  1550 1560   5
#> 7  1560 1570   6
#> 8  1570 1580   7
#> 9  1580 1590   8
#> 10 1590 1600   9
(rc = classify(elev_cut, rcl, include.lowest = TRUE))
#> class       : SpatRaster 
#> size        : 3450, 3450, 1  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> source(s)   : memory
#> name        : lyr.1 
#> min value   :     2 
#> max value   :  4346

(s = c(r, m, elev_cut, rc) |> 
  setNames(c("elevation", "elev-mask", "terrain", "topography")))
#> class       : SpatRaster 
#> size        : 3450, 3450, 4  (nrow, ncol, nlyr)
#> resolution  : 28.98965, 28.98965  (x, y)
#> extent      : -810156.6, -710142.3, 1934613, 2034627  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs 
#> sources     : foco-elev.tif  
#>               memory  
#>               memory  
#>               memory  
#> names       : elevation, elev-mask, terrain, topography 
#> min values  :      1382,         1,    1521,          2 
#> max values  :      4346,         1,    4346,       4346

plot(s, col = viridis::viridis(256))

Real Example: Classify Rainfall Regions of Colorado

#remotes::install_github("mikejohnson51/climateR")
library(climateR)

AOI = AOI::aoi_get(state = 'CO') 

# Wrapped in try() to handle potential API timeouts
prcp <- try({
  climateR::getTerraClim(AOI, "ppt", 
                        startDate = "2000-01-01", endDate = '2005-12-31')
}, silent = FALSE)

# Check if successful
if (inherits(prcp, "try-error")) {
  cat("Note: Climate data API unavailable; skipping prcp analysis\n")
} else {
  system.time(print(prcp))
}
#> $ppt
#> class       : SpatRaster 
#> size        : 99, 170, 73  (nrow, ncol, nlyr)
#> resolution  : 0.04166667, 0.04166667  (x, y)
#> extent      : -109.0833, -102, 36.95833, 41.08333  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=longlat +ellps=WGS84 +no_defs 
#> source(s)   : memory
#> names       : ppt_2~total, ppt_2~total, ppt_2~total, ppt_2~total, ppt_2~total, ppt_2~total, ... 
#> min values  :         2.7,         0.6,        12.2,         2.6,         1.3,         1.1, ... 
#> max values  :        86.7,        83.5,       176.2,        68.0,        72.7,        68.4, ... 
#> unit        : mm 
#> time        : 2000-01-01 to 2006-01-01 UTC (73 steps)
#>    user  system elapsed 
#>   0.003   0.000   0.005
# More on global below ...
if (!inherits(prcp, "try-error")) {
  quarts = global(prcp$ppt, fivenum)
  (quarts = colMeans(quarts))
}
#>         X1         X2         X3         X4         X5 
#>   4.294521  14.904110  23.913014  36.983562 101.754795

(rcl = data.frame(quarts[1:4], quarts[2:5], 1:4))
#>    quarts.1.4. quarts.2.5. X1.4
#> X1    4.294521    14.90411    1
#> X2   14.904110    23.91301    2
#> X3   23.913014    36.98356    3
#> X4   36.983562   101.75479    4

terra::classify(mean(prcp$ppt), rcl, include.lowest=TRUE) |> 
   plot(col = blues9)

Object/Field Interaction

For this example, we used OSM to extract the river data for the area of interest. We will talk more about OSM next week:

foco_rivers <- read_sf("data/foco-rivers-osm.gpkg")

Lets find the longest river segment IN our extent

river = foco_rivers |> 
  st_transform(crs(r)) |> 
  st_intersection(st_as_sfc(st_bbox(r))) %>% 
  mutate(length = st_length(.)) |> 
  slice_max(length, n = 1)
plot(r)
plot(river, add = TRUE, col = "blue", lwd = 2)

Value Extraction

  • Often, we want to know the profile and sinousity of a river

  • To do this, we need to know the inlet and outlet as well as the straight line connector

inlet  = head(st_cast(river, "POINT"), 1)
outlet = tail(st_cast(river, "POINT"), 1) 
pts    = bind_rows(inlet, outlet) 

line = st_cast(st_union(pts), "LINESTRING")

plot(r)
plot(river, add = TRUE, col = "blue", lwd = 2)
plot(line, add = TRUE, col = "black", lwd = 2)
plot(outlet$geom, add = TRUE, pch = 16, col = "red")
plot(inlet$geom,  add = TRUE, pch = 16, col = "green")

Sinuosity

Channel sinuosity is calculated by dividing the length of the stream channel by the straight line distance between the end points of the selected channel reach.

(sin = st_length(river) / st_length(line))
#> 1.400511 [1]

River Slope:

The change in elevation between the inlet/outlet divided by the length (rise/run) give us the slope of the river:

To calculate this, we must extract elevation values at the inlet and outlet:

(elev = extract(r, pts))
#>   ID foco-elev
#> 1  1      1813
#> 2  2      1675
100 * (elev$`foco-elev`[1] - elev$`foco-elev`[2]) / units::drop_units(st_length(river))
#> [1] 0.6004422

River profile

What does the elevation profile of the river look like?

profile = extract(r, river)$`foco-elev`
plot(profile, type = "l")
lines(zoo::rollmean(profile,k = 10), 
      col = "darkred", lwd = 3)

Map Algebra vs Matrix Algebra

Map Algebra

  • Dana Tomlin (Tomlin 1990) defined a framework for the analyizing field data stored as grided values.

  • He called this framework map algebra.

  • Map algebra operations and functions are broken down into four types:

    • local

    • focal

    • zonal

    • global

Local

  • Local operations and functions are applied to each individual cell and only involve those cells sharing the same location.

  • More than one raster can be involved in a local operation.

  • For example, rasters can be summed ( each overlapping pixels is added)

  • Local operations also include reclassification of values.

s = c(mean(prcp$ppt), app(prcp$ppt, sd), min(prcp$ppt), max(prcp$ppt)) |> 
  setNames(c("Mean", "StDev", "Min", "Max"))

rasterVis::levelplot(s)

Focal

  • Also referred to as “neighborhood” operations.

  • Assigns summary values to the output cells based on the neighboring cells in the input raster.

  • For example, a cell output value can be the average of 9 neighboring input cells (including the center cell) - this acts as a smoothing function.

Focal

  • Focal operations require a window (also known as a kernel) to work over

  • Additionally a kernel also defines the weight each neighboring cell contributes to the summary statistic.

  • For example, all cells in a 3x3 neighbor could each contribute 1/9th of their value to the summarized value (i.e. equal weight).

  • The weight can take on a more complex form defined by a function; such weights are defined by a kernel function.

  • One popular function is a Gaussian weighted function which assigns greater weight to nearby cells than those further away (Toblers first law)

Example: Focal

Lets apply a smoothing kernel to our Fort Collins elevation data over an 25x25 window, using the mean operator

foco = AOI::geocode("Fort Collins", bbox = TRUE) |> st_transform(crs(r))

foco_elev = crop(r, foco)
f1 <- focal(foco_elev, w= matrix(1,nrow=25,ncol=25), fun=mean)

Results

plot(foco_elev)

plot(f1)

What did we do?

matrix(1,nrow=5,ncol=5)
#>      [,1] [,2] [,3] [,4] [,5]
#> [1,]    1    1    1    1    1
#> [2,]    1    1    1    1    1
#> [3,]    1    1    1    1    1
#> [4,]    1    1    1    1    1
#> [5,]    1    1    1    1    1
mean(foco_elev[1:5, 1:5][,1])
#> [1] 1746.72

na.omit(values(f1))[1]
#> [1] 1831.795

Zonal

  • Zonal operations compute a summary values (such as the mean) from cells aggregated to some zonal unit.

  • Like focal operations, a zone and a summary function must be defined

  • The most basis example of a zonal function is aggregation!

aggregate(foco_elev, 10) |> plot()

Zonal Statisics (More advanced)

  • For more complicated object zones, exactextractr is a fast and efficient R utility that binds the C++ exactextract tool.

  • What is the county level mean January rainfall in Colorado?

AOI = AOI::aoi_get(state = "CO", county = "all")
AOI$janPTT = exactextractr::exact_extract(prcp$ppt$`ppt_2000-01-01_total`, AOI, "mean", progress = FALSE)
plot(AOI['janPTT'])

What about the US?

counties <-  AOI::aoi_get(state = "conus", county = "all")
  
jan <- climateR::getTerraClim(counties, "ppt", startDate = "2000-01-01") 
  
counties$janPTT <-  exactextractr::exact_extract(jan$ppt, counties, "mean", progress = FALSE)
plot(counties['janPTT'], border = NA, key.pos = 4)

Global

  • Global operations make use of some or all input cells when computing an output cell value.

  • They are a special case of zonal operations with the entire raster represents a single zone.

  • Examples include generating descriptive statistics for the entire raster dataset

Summary Values

global: computes statistics for the values of each layer in a Raster* object.

elev <- rast('data/foco-elev.tif')
global(elev, mean)
#>               mean
#> foco-elev 1887.874
mean(values(elev), na.rm = TRUE)
#> [1] 1887.874

Why not just mean()

In the terra package, functions like max, min, and mean, return a new SpatRast* object (with a value computed for each cell).

In contrast, global returns a single value, computed from the all the values of a layer.

s = c(elev, elev^2, elev*.5)
mean(s) |> plot()

global(s, mean)
#>                     mean
#> foco-elev      1887.8738
#> foco-elev.1 3802035.3412
#> foco-elev.2     943.9369

Mean Monthly Rainfall for Colorado

global

plot(global(prcp$ppt, max)$max, type = "l", 
     ylab = "rainfall", xlab = "month since 2000-01")
lines(global(prcp$ppt, min)$min, type = "l", col = "blue")
lines(global(prcp$ppt, mean)$mean, type = "l", col = "darkred", lwd = 2)

mean()

plot(mean(prcp$ppt), col = blues9)
plot(AOI, add =TRUE, col = NA, lwd = 2)

Kmeans over to Raster Data!

  • each layer of a SpatRaster is a layer
  • each layer is a vector of values
library(climateR)
params <-  c("ppt", "tmax", "tmin", "srad", "q")
AOI   <-  AOI::aoi_get(state = "CO")

co <- try({
  climateR::getTerraClim(AOI, params, startDate = "2018-10-01")  %>% 
    unlist() %>% 
    rast() |> 
    setNames(params)
}, silent = FALSE)

if (!inherits(co, "try-error")) {
  cat("Climate data loaded successfully\n")
  print(co)
}
#> Climate data loaded successfully
#> class       : SpatRaster 
#> size        : 99, 170, 5  (nrow, ncol, nlyr)
#> resolution  : 0.04166667, 0.04166667  (x, y)
#> extent      : -109.0833, -102, 36.95833, 41.08333  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=longlat +ellps=WGS84 +no_defs 
#> source(s)   : memory
#> names       :   ppt, tmax,  tmin, srad,    q 
#> min values  :  14.9,  0.7, 126.2,  3.8, -7.5 
#> max values  : 132.4, 23.7, 158.2, 21.4,  5.8 
#> unit        :    mm,   mm, W/m^2, degC, degC 
#> time        : 2018-10-01 UTC

Colorado October 2018 climate

plot(co)

Raster layers are vectors!

values = values(co)
head(values)
#>       ppt tmax  tmin srad    q
#> [1,] 40.8  2.0 140.3 11.1 -3.4
#> [2,] 42.5  2.1 139.5  9.7 -3.8
#> [3,] 42.6  2.1 139.8  9.6 -3.9
#> [4,] 41.0  2.0 140.2 10.5 -3.4
#> [5,] 39.4  2.0 140.6 11.2 -3.2
#> [6,] 37.8  1.9 140.7 11.9 -3.0

Data Prep

  • Identify NA indices for latter reference
  • Remove NA values
  • Scale
idx <- which(!apply(is.na(values), 1, any))
v   <- na.omit(values)
vs  <- scale(v)

(E <- kmeans(vs, 5, iter.max = 100))
#> K-means clustering with 5 clusters of sizes 3261, 3532, 5298, 3464, 1275
#> 
#> Cluster means:
#>          ppt       tmax       tmin       srad          q
#> 1  0.3055515  0.1430936  1.2625890  0.5933944  0.7605688
#> 2 -1.1756219 -0.8906646 -0.5796876  0.4119374  0.4452057
#> 3  0.1562612  0.1168894 -0.2241122 -0.9671713 -1.0866622
#> 4 -0.1410004 -0.1686439 -0.7569182  0.9323295  0.8366062
#> 5  2.2089777  2.0738051  1.3642864 -1.1729708 -0.9361167
#> 
#> Clustering vector:
#>     [1] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>    [37] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>    [73] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [109] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [145] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
#>   [181] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [217] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [253] 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [289] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [325] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [361] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [397] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2
#>   [433] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [469] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [505] 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [541] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [577] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [613] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [649] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3
#>   [685] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [721] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [757] 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [793] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [829] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
#>   [865] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [901] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>   [937] 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>   [973] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1009] 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1045] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1081] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2
#>  [1117] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1153] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1189] 2 2 3 3 3 3 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1225] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 5 3
#>  [1261] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1297] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1333] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 2 2 2 2
#>  [1369] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1405] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 5 5 5 3 3 3 3 3 3 3 3 3 3 3
#>  [1441] 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1477] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1513] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 2 2 3 3 3 3 3 3 3 3 3 3
#>  [1549] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1585] 3 3 3 3 3 3 3 3 3 3 3 5 5 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2
#>  [1621] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1657] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1693] 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1729] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1765] 3 3 5 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1801] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1837] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3
#>  [1873] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1909] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [1945] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [1981] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2017] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2053] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2089] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2125] 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2161] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2197] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2233] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2269] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2
#>  [2305] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2341] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2377] 2 2 2 2 3 3 3 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2413] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2449] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2485] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2521] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3
#>  [2557] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2593] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2629] 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2665] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2701] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2737] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2773] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2809] 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2845] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [2881] 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2917] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [2953] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2
#>  [2989] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3025] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3061] 4 4 3 3 3 3 3 3 3 3 3 3 4 3 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3097] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3133] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3169] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3205] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4
#>  [3241] 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3277] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3313] 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3349] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3385] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3
#>  [3421] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3457] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2
#>  [3493] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3529] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3565] 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3601] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3637] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3673] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3709] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4
#>  [3745] 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3781] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3817] 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3853] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [3889] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3
#>  [3925] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3961] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [3997] 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4033] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4069] 2 2 2 4 4 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4105] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4141] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2
#>  [4177] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4213] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4
#>  [4249] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4285] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4321] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4357] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4393] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [4429] 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4465] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4501] 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4537] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4573] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3
#>  [4609] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4645] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4681] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4717] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4
#>  [4753] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4789] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4825] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2
#>  [4861] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [4897] 2 2 2 2 2 2 2 2 4 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [4933] 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [4969] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5005] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5041] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5077] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [5113] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5149] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5185] 3 3 3 3 3 3 3 2 2 4 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5221] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [5257] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3
#>  [5293] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5329] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 4 4
#>  [5365] 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5401] 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [5437] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5473] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5509] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 4 4 4 2 2 2 2 2 2 2 2
#>  [5545] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5581] 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [5617] 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5653] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5689] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5725] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4
#>  [5761] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5797] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5833] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5869] 3 3 3 3 3 4 4 4 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [5905] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [5941] 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [5977] 3 3 3 3 1 1 4 3 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6013] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 4 4 4 2
#>  [6049] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [6085] 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [6121] 3 3 4 4 4 4 4 4 4 4 3 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1
#>  [6157] 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6193] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 4 4 2 2 2 2 2 2 2 2 2 2 2
#>  [6229] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4
#>  [6265] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 4 4 4 4 1 1 1 1 1
#>  [6301] 4 3 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3
#>  [6337] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6373] 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [6409] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4
#>  [6445] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 3 4 4 4 4 4 4 4 4
#>  [6481] 4 3 4 4 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6517] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6553] 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [6589] 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [6625] 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 1 1 1 1 3 3 3
#>  [6661] 3 3 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6697] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2
#>  [6733] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [6769] 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1
#>  [6805] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6841] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [6877] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [6913] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4
#>  [6949] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#>  [6985] 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7021] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7057] 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [7093] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [7129] 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#>  [7165] 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7201] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3
#>  [7237] 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [7273] 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [7309] 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3
#>  [7345] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7381] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 3 3 3 2 2 2 2 2 2 2 2 2
#>  [7417] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4
#>  [7453] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1
#>  [7489] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7525] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7561] 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [7597] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [7633] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#>  [7669] 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7705] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7741] 3 2 3 3 2 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [7777] 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [7813] 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3
#>  [7849] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7885] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [7921] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4
#>  [7957] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1
#>  [7993] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8029] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8065] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2
#>  [8101] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4
#>  [8137] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1
#>  [8173] 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8209] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8245] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [8281] 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [8317] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3
#>  [8353] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8389] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8425] 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [8461] 2 4 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [8497] 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3
#>  [8533] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8569] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2
#>  [8605] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4
#>  [8641] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1
#>  [8677] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 1 1 1 1 1 1 3 3 3 3 3 3 1 1 3 3 3
#>  [8713] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8749] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [8785] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [8821] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 5 5 5 5 5 5 5 5 5 1 1 1 1 1
#>  [8857] 1 1 1 1 1 1 3 3 1 1 1 1 1 1 1 1 3 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8893] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [8929] 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [8965] 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [9001] 4 4 4 4 4 4 4 4 4 4 1 1 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#>  [9037] 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9073] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9109] 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4
#>  [9145] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [9181] 1 1 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#>  [9217] 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9253] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2
#>  [9289] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [9325] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1
#>  [9361] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3
#>  [9397] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9433] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#>  [9469] 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [9505] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 5 5 5 5 5 1 1 1 1 1 1 1 1 1
#>  [9541] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9577] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2
#>  [9613] 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4
#>  [9649] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [9685] 4 4 4 4 4 4 1 1 1 1 1 1 1 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#>  [9721] 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9757] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 3 3 3 3 3 3 3 3 2
#>  [9793] 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#>  [9829] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1
#>  [9865] 1 1 1 1 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3
#>  [9901] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#>  [9937] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 3 3 3 3 3 3 2 2 2 2 4 2 4 4 2 4 4 4
#>  [9973] 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10009] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 1 1 1 1 1 1 1 1 5 5 5 5 1
#> [10045] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [10081] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [10117] 3 2 3 3 2 2 2 2 3 3 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 2 2 2 2 4 2 2 2 4
#> [10153] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10189] 4 4 4 4 4 4 4 4 4 4 4 4 5 1 1 1 1 1 1 1 1 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1
#> [10225] 1 1 1 1 1 1 1 1 1 1 3 3 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [10261] 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2
#> [10297] 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 2 2 2 2 4 4 2 4 4 4 4 4 4 4 4 4
#> [10333] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10369] 4 4 5 1 1 1 1 1 1 1 1 1 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [10405] 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [10441] 3 3 2 2 2 3 3 2 3 3 3 3 3 3 3 3 3 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4
#> [10477] 4 4 4 4 4 4 4 4 4 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10513] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 1 1 1 1 1 1 1
#> [10549] 1 1 1 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3
#> [10585] 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 3
#> [10621] 3 3 3 3 3 3 4 2 4 4 4 4 4 4 4 4 4 4 2 4 4 2 4 2 4 4 4 4 4 4 4 4 4 4 4 4
#> [10657] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10693] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5
#> [10729] 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [10765] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3 3 2 2 2 3 3 2 2 2 2 2 2 2 4
#> [10801] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10837] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [10873] 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 1 1 1 1 1 1
#> [10909] 1 1 1 1 1 1 1 3 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [10945] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 3 2 2 2 4 2 4 4 4 4 4 4 4 4
#> [10981] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11017] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1
#> [11053] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 3 3 1 1
#> [11089] 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [11125] 3 3 5 3 3 2 2 2 2 2 2 3 3 2 2 2 3 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11161] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11197] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1
#> [11233] 1 1 1 1 1 1 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [11269] 3 3 3 3 3 3 3 3 3 3 3 3 3 5 5 3 3 5 3 3 5 5 3 5 3 3 3 3 3 3 3 3 3 3 2 2
#> [11305] 3 3 3 2 3 2 3 3 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11341] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11377] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5
#> [11413] 5 5 5 5 5 1 1 1 1 1 1 1 3 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 5 3 3 3 3
#> [11449] 3 5 5 3 3 5 5 5 3 3 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [11485] 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11521] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11557] 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 1 1 1 1
#> [11593] 1 1 1 3 3 3 3 3 3 5 3 3 3 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3
#> [11629] 3 3 3 3 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4
#> [11665] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11701] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1
#> [11737] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 1 1 1 1 1 1 1 3 3 3 5 3 5
#> [11773] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
#> [11809] 3 3 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11845] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [11881] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [11917] 1 1 1 1 1 1 5 5 5 5 5 5 1 1 1 1 1 1 1 3 5 5 5 5 5 5 3 3 5 5 5 3 3 3 3 5
#> [11953] 3 3 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 3 3 3 1 1 1 1 1 3 3 5 5 3 3 3 3 3 3
#> [11989] 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12025] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12061] 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5
#> [12097] 5 5 5 1 1 1 1 1 3 3 5 5 5 5 5 5 3 3 5 5 5 5 3 3 5 5 5 5 5 5 5 5 5 3 3 3
#> [12133] 3 3 3 3 3 3 1 1 1 1 1 1 1 1 1 1 1 3 3 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4
#> [12169] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12205] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12241] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 1 5 5 5 5 5 5 5 5 5 5 1 5 5
#> [12277] 5 5 5 5 5 5 3 3 5 5 5 3 3 5 5 5 5 5 5 5 5 5 5 3 3 3 3 3 3 3 3 3 1 1 1 1
#> [12313] 1 1 1 1 1 1 1 1 3 5 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 4 4 4 4 4 4 4 4 4
#> [12349] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12385] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1
#> [12421] 1 1 1 1 1 5 5 5 5 5 5 5 5 1 1 5 5 5 5 5 5 5 5 3 5 5 5 5 5 5 5 5 3 5 5 5
#> [12457] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 3 5 5 5 5 5 5 3 1 1 1 1 1 1 1 1 1 1 1 1 1 3
#> [12493] 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12529] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12565] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5
#> [12601] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [12637] 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 5 5 3 3 3 3 3 3 3
#> [12673] 3 3 3 3 3 3 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12709] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12745] 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [12781] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 3 5
#> [12817] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 5 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4
#> [12853] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [12889] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1
#> [12925] 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [12961] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 5 1 1 1 1 1 1 1 1 1 1
#> [12997] 1 1 1 1 1 1 1 3 5 5 5 3 3 1 1 3 3 1 3 3 3 3 3 1 1 4 1 4 1 1 1 1 4 4 4 4
#> [13033] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13069] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [13105] 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [13141] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 5
#> [13177] 5 3 3 1 1 1 1 1 1 1 3 3 3 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4
#> [13213] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13249] 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 5 5 5 5 5 5 5 5 5
#> [13285] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 3 3 3 3 5 5 5 5 5 5
#> [13321] 5 1 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 1 1 1 1 1 1 1
#> [13357] 1 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13393] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13429] 4 4 1 1 1 1 1 1 1 1 1 1 5 5 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [13465] 5 5 5 5 5 5 5 5 5 5 5 5 3 3 5 5 5 5 5 3 3 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1
#> [13501] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 5 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [13537] 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13573] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1
#> [13609] 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [13645] 5 5 5 5 5 3 5 5 5 5 5 5 1 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [13681] 1 1 1 1 1 1 5 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [13717] 1 1 1 4 4 4 4 4 4 4 4 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13753] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5
#> [13789] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [13825] 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 5 3 3 3
#> [13861] 3 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [13897] 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [13933] 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5
#> [13969] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 5 1 1 1
#> [14005] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 3 5 3 3 1 1 1 1 1 1
#> [14041] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14077] 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1
#> [14113] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [14149] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1
#> [14185] 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 3 5 3 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14221] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4
#> [14257] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1
#> [14293] 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [14329] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14365] 1 5 5 5 5 5 3 3 5 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14401] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [14437] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5
#> [14473] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [14509] 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 1 1 1 3
#> [14545] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14581] 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [14617] 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 1 5
#> [14653] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1
#> [14689] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 3 3 1 1 1 1 1 1 1 1 1
#> [14725] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14761] 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1
#> [14797] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 1 1 5 5 5 5 5 5 5 5 5 5 5
#> [14833] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1
#> [14869] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14905] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4
#> [14941] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [14977] 1 1 1 1 1 5 5 5 5 5 5 5 5 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [15013] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15049] 1 1 1 5 5 5 5 3 1 3 3 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15085] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [15121] 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5
#> [15157] 5 1 5 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 5 5 5 5 5 5 5 5 5 5
#> [15193] 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 3 3 5
#> [15229] 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15265] 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [15301] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1
#> [15337] 5 5 5 5 5 1 5 5 5 5 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1
#> [15373] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 3 3 3 1 1 1 1 1 1 1 1 1
#> [15409] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4
#> [15445] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1
#> [15481] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 1 5 5 1 1
#> [15517] 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15553] 1 1 1 1 1 1 1 5 5 5 5 5 5 5 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15589] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [15625] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15661] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5
#> [15697] 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5
#> [15733] 5 5 5 5 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15769] 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [15805] 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15841] 1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5
#> [15877] 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 3 1 1 1 1 1
#> [15913] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [15949] 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1
#> [15985] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16021] 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1
#> [16057] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16093] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4
#> [16129] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16165] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16201] 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16237] 1 5 1 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16273] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [16309] 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16345] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5
#> [16381] 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5
#> [16417] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16453] 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> [16489] 4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16525] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 1 1
#> [16561] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1
#> [16597] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4
#> [16633] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 1 1 1 1 1
#> [16669] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16705] 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1
#> [16741] 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#> [16777] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4
#> [16813] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
#> 
#> Within cluster sum of squares by cluster:
#> [1] 7041.189 2053.652 9545.981 2785.975 7727.402
#>  (between_SS / total_SS =  65.4 %)
#> 
#> Available components:
#> 
#> [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
#> [6] "betweenss"    "size"         "iter"         "ifault"

Copying a raster structure

clus_raster <- co$tmax
values(clus_raster) <- NA

Assign values

clus_raster[idx] <- E$cluster
plot(clus_raster, col = RColorBrewer::brewer.pal(5, "Spectral"))

Merging across data sources

# Get elevations data
elev = elevatr::get_elev_raster(AOI, z = 5) %>% 
  crop(AOI) |> 
  rast()

# Align Raster extents and resolutions
elev = project(elev, co$ppt)

# Extract Values
values = c(co$ppt, elev) %>% values()

# Prep data
idx = which(!apply(is.na(values), 1, any))
v = na.omit(values)
vs = scale(v)

# Cluster
E = kmeans(vs, 5, iter.max = 100)

clus_raster = elev
values(clus_raster) = NA
clus_raster[idx] <- E$cluster

par(mfrow = c(2,1))
plot(elev)
plot(co$ppt)

plot(clus_raster, col = RColorBrewer::brewer.pal(5, "Spectral"))

Clustering at larger scales

counties =  AOI::aoi_get(state = "conus", county = "all")
params = c("tmax", "tmin", "ppt", "srad")

dat = climateR::getTerraClim(counties, params, startDate = "2018-06-01") %>% 
  unlist() |> 
  rast() %>% 
  setNames(params) |> 
  exactextractr::exact_extract(counties, "mean", progress = FALSE)
dat = scale(dat)

counties$clust8 = kmeans(dat, 8)$cluster

plot(st_transform(counties["clust8"], 5070), border = NA)

Extra! Animating Rasters…

Install and load the gifski package

  • save_gif: combines many individual plots

  • A for loop build the plots

  • The plot is what we have been doing all along (if you want a ggplot you must print the object!)

  • gif_file: the path to save the image

  • width/height: the image dimensions

  • delay: the pause between frames

  • loop: should the gif play over and over?

library(gifski)

save_gif(
  {for(i in 1:nlyr(prcp$ppt)) {
      plot(prcp$ppt[[i]], col = blues9, 
           legend = FALSE, 
           main = names(prcp$ppt)[i])}
  }, 
  gif_file = "img/ppt.gif", 
  width = 800, height = 600, delay = .33, loop = TRUE)

Result

Advanced Topic: Raster Reprojection

Rasters often need to be transformed from one Coordinate Reference System (CRS) to another to match vector data, other rasters, or regional standards.

Example: Landsat data (UTM) needs reprojection to match state plane or your analysis CRS.

# Original raster: UTM zone 12N
original_crs <- crs(elev)
str(original_crs)
#>  chr "GEOGCRS[\"unknown\",\n    DATUM[\"Unknown based on WGS 84 ellipsoid\",\n        ELLIPSOID[\"WGS 84\",6378137,29"| __truncated__
res(elev)[1]
#> [1] 0.04166667

# Reproject to geographic (WGS84)
elev_wgs84 <- project(elev, "EPSG:4326")
str(crs(elev_wgs84))
#>  chr "GEOGCRS[\"WGS 84\",\n    ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n        MEMBER[\"World Geodetic Sys"| __truncated__
res(elev_wgs84)[1]
#> [1] 0.04166667

Risk: Reprojection changes infered pixel coordinates AND resolution—always inspect results!

Resampling Methods: The Hidden Cost

When reprojecting (or changing resolution), terra must resample pixels to fit the new grid that have been sheered, or changed in size:

g = st_make_grid(ext(elev), n = 100) |> 
  st_as_sf(crs = crs(elev))

g2 = st_make_grid(ext(elev), n = 10) |> 
  st_as_sf(crs = crs(elev)) |> 
  st_transform(4326)
plot(g)

plot(g2)

Different methods produce very different results.

  • Fall back to GDAL

  • Main question: “how do you select and/or reduce value to a new grid value knowing each grid has 0:n contributors, and each contributor has a different weight (distance, area, etc)

Rule of Thumb: Use nearest for categories, bilienar/cubic for continuous data. But, projection is always “lossy” and is slow.

Summary: Raster Reprojection & Resampling

Task Method Key Consideration
Reproject to new CRS project(rast, crs) Choose method: nearest (categorical) or cubic (continuous)
Change resolution aggregate() or resample() Coarse = fast but lose detail; fine = slow
Inspect quality plot() side-by-side Always visually verify reprojected/resampled output
Convert vector → raster rasterize() Only when needed; many operations are faster in raster
Many analyses benefit from raster Map algebra, zonal stats, focal ops But some tasks require vector topology

Best practice: Start with the appropriate format (vector or raster) for your analysis—don’t convert back and forth.