# Introduction to the sarp.snowprofile package

Functions to import/export various formats of snow profiles, with basic formatting and visualization functions.

    library(sarp.snowprofile)

## 1. Snowprofile objects

The package uses S3 classes for individual snow profiles (class `snowprofile`) or lists of multiple snow profiles (class `snowprofileSet`). Objects with these classes can be created, manipulated, and visualized.

A `snowprofile` object contains data about a snow stratigraphy profile. It is structured as a `list` with metadata (e.g. profile name and location) and a `data.frame` containing layer properties. Mandatory parts of a `snowprofile` object include:

- `station` and `station_id` provide a profile name
- `datetime` timestamp
- `latlon`, `elev`, `angle`, `aspect` location information
- `hs` total snow height
- `layers` a `data.frame` of class `snowprofileLayers` that contains layer properties (each row is a layer and each column is a property such as depth or grain size).

A `snowprofileSet` object is simply a `list` of multiple `snowprofile` objects.

The package includes sample data packaged into three `snowprofileSet` objects:

- `SPgroup` contains 12 profiles from different locations with the same timestamp
- `SPtimeline` contains 11 profiles from the same location with different timestamps
- `SPpairs` contains various other snow profiles

    ## Print the structure of a single `snowprofile` object
    Profile <- SPpairs$C_day1
    str(Profile)

    ## List of 14
    ##  $ station         : int 112233
    ##  $ station_id      : chr "VIR112233"
    ##  $ datetime        : POSIXct[1:1], format: "2018-11-21 05:00:00"
    ##  $ latlon          : num [1, 1:2] 52.3 -119
    ##   ..- attr(*, "dimnames")=List of 2
    ##   .. ..$ : chr ""
    ##   .. ..$ : chr [1:2] "latitude" "longitude"
    ##  $ elev            : int 1917
    ##  $ angle           : num 0
    ##  $ aspect          : num 0
    ##  $ hs              : num 111
    ##  $ type            : chr "vstation"
    ##  $ layers          :Classes 'snowprofileLayers' and 'data.frame':    30 obs. of  11 variables:
    ##   ..$ height     : num [1:30] 1.8 3.54 5.08 5.42 6.83 ...
    ##   ..$ ddate      : POSIXct[1:30], format: "2018-09-12 17:00:00" "2018-09-15 17:00:00" ...
    ##   ..$ density    : int [1:30] 422 354 408 332 404 357 313 294 312 359 ...
    ##   ..$ temperature: num [1:30] -0.1 -0.1 -0.2 -0.2 -0.3 -1 -1.1 -1.1 -1.4 -1.5 ...
    ##   ..$ lwc        : int [1:30] 0 0 0 0 0 0 0 0 0 0 ...
    ##   ..$ gsize      : num [1:30] 1.37 1.62 0.96 1.69 0.82 0.98 1.38 1.93 1.25 1.32 ...
    ##   ..$ hardness   : num [1:30] 4 5 4 2 4 5 5 5 2.15 3 ...
    ##   ..$ ssi        : num [1:30] 5.43 3.93 1.37 1.39 4.12 5.59 4.68 1.57 3.4 3.03 ...
    ##   ..$ gtype      : Factor w/ 8 levels "DF","DH","FC",..: 5 6 4 2 4 6 6 6 3 4 ...
    ##   ..$ depth      : num [1:30] 109 107 106 105 104 ...
    ##   ..$ thickness  : num [1:30] 1.8 1.74 1.54 0.34 1.41 ...
    ##  $ zone            : chr "BONE_NORTH"
    ##  $ band            : chr "TL"
    ##  $ date            : Date[1:1], format: "2018-11-21"
    ##  $ maxObservedDepth: num 111
    ##  - attr(*, "class")= chr "snowprofile"

Check out an empty snowprofile object to understand which information can potentially go where:

    snowprofile(dropNAs = FALSE)

    ##                  MetaData
    ## station                NA
    ## station_id             NA
    ## datetime               NA
    ## latlon              NA NA
    ## elev                   NA
    ## angle                  NA
    ## aspect                 NA
    ## hs                     NA
    ## maxObservedDepth       NA
    ## type               manual
    ## band                   NA
    ## zone                   NA
    ## comment                NA
    ## hn24                   NA
    ## hn72                   NA
    ## ski_pen                NA
    ## date                   NA
    ## layers
    ##   depth height thickness temperature density lwc gsize gsize_max gsize_avg
    ## 1    NA     NA        NA          NA      NA  NA    NA        NA        NA
    ##   gtype gtype_sec hardness ddate bdate datetag ssi sphericity v_strain_rate
    ## 1  <NA>      <NA>       NA  <NA>  <NA>    <NA>  NA         NA            NA
    ##   crit_cut_length tsa tsa_interface rta rta_interface layerOfInterest comment
    ## 1              NA  NA            NA  NA            NA              NA    <NA>
    ## tests
    ## [1] type       result     score      fract_char depth      comment
    ## <0 rows> (or 0-length row.names)
    ## instabilitySigns
    ## [1] type    present comment
    ## <0 rows> (or 0-length row.names)

## 2. Profile creation

The package includes functions to create a `snowprofile` object by importing common file formats as well as provides constructor functions to manually create a `snowprofile`.

### 2.1 Import profiles from file

Import functions for generic snow profiles include::

- CAAML (`snowprofileCaaml`)
- csv (`snowprofileCsv`)

and import functions for simulated profiles produced with the snow cover model SNOWPACK include:

- prf (`snowprofilePrf`)
- pro (`snowprofilePro`)
- sno (`snowprofileSno`)

Note that prf and pro files contain multiple profiles and thus the import functions return a `snowprofileSet`, while CAAML, csv, and sno files return a single `snowprofile`.

    ## Import a CAAML file
    # Filename <- "path/to/file.caaml"
    # Profile <- snowprofileCaaml(Filename)

    # ## Import all profiles from a directory of CAAML files and create a `snowprofileSet`
    # CaamlFiles <- list.files('path/to/caamlprofiles', full.names = T)
    # Profiles <- lapply(CaamlFiles, snowprofileCaaml)
    # Profiles <- snowprofileSet(Profiles)

An additional parser `readSmet` is also provided to read other input and output files from SNOWPACK.

### 2.2 Manually construct profiles

To manually create a `snowprofile` object see the help pages for the constructor functions `snowprofile()` and `snowprofileLayers()` where metadata and layer properties are provided as function arguments.

### 2.3 Formatting profiles

Import and constructor functions perform several validation checks for consistent structure (e.g. variable names, consistent layer thickness/depth/height). Sometimes profiles may be malformatted (e.g. files have different formatting than the functions in this package, future changes to this R package), so this package provides functions for checking profiles for formatting discrepancies and reformatting them if necessary. `validate_snowprofile` raises errors (or silently print error messages) in case of formatting discrepancies and `reformat_snowprofile` can conveniently correct data types or rename metadata / layer properties. See examples in the help files for these functions for examples of how it identify and correct errors in malformatted profiles

## 3. Profile manipulation

`print`, `summary`, and `rbind` methods exist to summarize and extract contents from `snowprofile` and `snowprofileSet` objects.

### 3.1 Print

Print contents of a `snowprofile` to the console.

    Profile <- SPpairs$A_manual
    print(Profile)

    ##                                    MetaData
    ## station                   SarpOfficeStation
    ## station_id                    niviz_station
    ## datetime                2019-02-22 09:24:00
    ## latlon              49.2765643 -122.9139272
    ## elev                                    339
    ## angle                                    38
    ## aspect                                  180
    ## hs                                      260
    ## type                                 manual
    ## observer                            Sarp|FH
    ## comment_general  don't feel like commenting
    ## comment_location            test caaml file
    ## date                             2019-02-22
    ## maxObservedDepth                        260
    ## layers
    ##    depth thickness height hardness gtype gsize_avg gsize_max lwc gtype_sec
    ## 1    250        10     10     5.00  MFcr       1.5       1.5   D      <NA>
    ## 2    230        20     30     3.00    FC       2.0       2.0   D      <NA>
    ## 3    220        10     40     5.00  MFcr       1.5       1.5   D      <NA>
    ## 4    157        63    103     4.00    RG       0.3       0.3   D      <NA>
    ## 5    155         5    105     2.00    SH       5.0       5.0   D      <NA>
    ## 6     95        60    165     4.00    RG       0.3       0.3   D      <NA>
    ## 7     75        20    185     3.00    RG       0.3       0.3   D      <NA>
    ## 8     60        15    200     1.00    FC       2.0       2.0   D      <NA>
    ## 9     42        18    218     2.00    RG       1.0       1.0   D      <NA>
    ## 10    40         2    220     1.50    FC       2.0       2.5   D      <NA>
    ## 11    38         2    222     1.00    SH       5.0       5.0   D        DH
    ## 12     0        35    260     1.25    DF       1.5       1.5   D      <NA>
    ##         ddate
    ## 1        <NA>
    ## 2        <NA>
    ## 3        <NA>
    ## 4        <NA>
    ## 5        <NA>
    ## 6        <NA>
    ## 7        <NA>
    ## 8        <NA>
    ## 9        <NA>
    ## 10       <NA>
    ## 11 2019-02-20
    ## 12       <NA>

### 3.2 Summary

Extract metadata from a single profile or set of profiles into a `data.frame`.

    summary(Profile)

    ##             station    station_id            datetime      lat       lon elev
    ## 1 SarpOfficeStation niviz_station 2019-02-22 09:24:00 49.27656 -122.9139  339
    ##   angle aspect  hs   type nLayers observer            comment_general
    ## 1    38    180 260 manual      12  Sarp|FH don't feel like commenting
    ##   comment_location       date maxObservedDepth
    ## 1  test caaml file 2019-02-22              260

    summary(SPgroup)

    ##    station station_id            datetime elev angle aspect     hs     type
    ## 1   116093  VIR116093 2019-02-02 05:00:00 1907     0      0 156.48 vstation
    ## 2   116094  VIR116094 2019-02-02 05:00:00 1979     0      0 150.41 vstation
    ## 3   116095  VIR116095 2019-02-02 05:00:00 2011     0      0 117.89 vstation
    ## 4   116096  VIR116096 2019-02-02 05:00:00 1859     0      0 102.42 vstation
    ## 5   116643  VIR116643 2019-02-02 05:00:00 1867     0      0 179.87 vstation
    ## 6   116644  VIR116644 2019-02-02 05:00:00 1969     0      0 179.22 vstation
    ## 7   116645  VIR116645 2019-02-02 05:00:00 2019     0      0 156.85 vstation
    ## 8   116646  VIR116646 2019-02-02 05:00:00 1983     0      0 113.26 vstation
    ## 9   117194  VIR117194 2019-02-02 05:00:00 1915     0      0 156.02 vstation
    ## 10  117197  VIR117197 2019-02-02 05:00:00 1941     0      0 116.94 vstation
    ## 11  117746  VIR117746 2019-02-02 05:00:00 1911     0      0 142.78 vstation
    ## 12  117747  VIR117747 2019-02-02 05:00:00 1957     0      0 128.56 vstation
    ##       zone band       date maxObservedDepth
    ## 1  ALBREDA   TL 2019-02-02           156.48
    ## 2  ALBREDA   TL 2019-02-02           150.41
    ## 3  ALBREDA   TL 2019-02-02           117.89
    ## 4  ALBREDA   TL 2019-02-02           102.42
    ## 5  ALBREDA   TL 2019-02-02           179.87
    ## 6  ALBREDA   TL 2019-02-02           179.22
    ## 7  ALBREDA   TL 2019-02-02           156.85
    ## 8  ALBREDA   TL 2019-02-02           113.26
    ## 9  ALBREDA   TL 2019-02-02           156.02
    ## 10 ALBREDA   TL 2019-02-02           116.94
    ## 11 ALBREDA   TL 2019-02-02           142.78
    ## 12 ALBREDA   TL 2019-02-02           128.56

Summary methods are useful to extract subsets of a `snowprofileSet` based on some attribute (e.g. location, time).

    ## Subset all profiles from SPgroup with elevation > 2000 m
    Metadata <- summary(SPgroup)
    Alpine <- SPgroup[Metadata$elev > 2000]
    print(paste(length(Alpine), 'of', length(SPgroup), 'profiles in SPgroup are above 2000 m'))

    ## [1] "2 of 12 profiles in SPgroup are above 2000 m"

### 3.3 Rbind

`rbind` methods merge metadata and layer properties from one or many profiles into a large `data.frame` that is convenient for analysis tasks.

    ## Rbind SPgroup
    TabularProfile <- rbind(SPgroup)
    names(TabularProfile)

    ##  [1] "station"          "station_id"       "datetime"         "lat"
    ##  [5] "lon"              "elev"             "angle"            "aspect"
    ##  [9] "hs"               "type"             "nLayers"          "zone"
    ## [13] "band"             "date"             "maxObservedDepth" "height"
    ## [17] "ddate"            "density"          "temperature"      "lwc"
    ## [21] "gtype"            "hardness"         "ssi"              "gsize"
    ## [25] "depth"            "thickness"

    ## Tabulate all grain types
    table(TabularProfile$gtype)

    ##
    ##   DF   DH   FC FCxr   MF MFcr   PP   RG   SH
    ##   29   45  148   96    1   73   24   63   12

    ## Get elevations of profiles with SH layers > 5 mm
    SH_layers <- subset(TabularProfile, gtype == 'SH' & gsize > 5)
    sort(SH_layers$elev)

    ## [1] 1859 1911 1941 1957

## 4. Profile visualization

Plot methods exist for individual profiles and sets of profiles:

- `plot.snowprofile` produces a hardness profile for a single `snowprofile` object
- `plot.snowprofileSet` produces several types of plots for a `snowprofileSet` including timelines and side-by-side stratigraphies

    ## Plot a single hardness profile
    plot(Profile)

    ## Plot a timeline
    plot(SPtimeline)

    ## Plot all profiles in the group and sort by height
    plot(SPgroup, SortMethod = 'hs')

The package also includes several `getColour...` and `setColour...` functions to define colour palettes for various profile properties.