require(tidyr)
require(dplyr)
library(ggplot2)
library(data.table)
library(here)
library(ggforce)
library(ggthemes)
devtools::install_github("r4atlantis/atlantisom")
These packages have more recent versions available.
Which would you like to update?

 1:   All
 2:   CRAN packages only
 3:   None
 4:   chron     (2.3-53  -> 2.3-54) [CRAN]
 5:   cli       (1.1.0   -> 2.0.0 ) [CRAN]
 6:   digest    (0.6.20  -> 0.6.23) [CRAN]
 7:   ellipsis  (0.2.0.1 -> 0.3.0 ) [CRAN]
 8:   pkgconfig (2.0.2   -> 2.0.3 ) [CRAN]
 9:   purrr     (0.3.2   -> 0.3.3 ) [CRAN]
10:   R6        (2.4.0   -> 2.4.1 ) [CRAN]
11:   Rcpp      (1.0.1   -> 1.0.3 ) [CRAN]
12:   rlang     (0.4.0   -> 0.4.2 ) [CRAN]
13:   RNetCDF   (1.9-1   -> 2.1-1 ) [CRAN]
14:   xml2      (1.2.0   -> 1.2.2 ) [CRAN]
Enter one or more numbers separated by spaces, or an empty line to cancel
trying URL 'https://cran.cnr.berkeley.edu/bin/windows/contrib/3.5/tidyr_1.0.0.zip'
Content type 'application/zip' length 1292969 bytes (1.2 MB)
downloaded 1.2 MB
package ‘tidyr’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\chris\AppData\Local\Temp\RtmpSw1oMF\downloaded_packages
  
  
  
√  checking for file 'C:\Users\chris\AppData\Local\Temp\RtmpSw1oMF\remotes27e422e0570b\r4atlantis-atlantisom-b43c34e/DESCRIPTION' (380ms)

  
  
  
-  preparing 'atlantisom': (1.1s)
   checking DESCRIPTION meta-information ...
  
√  checking DESCRIPTION meta-information

  
  
  
-  checking for LF line-endings in source and make files and shell scripts (501ms)

  
-  checking for empty or unneeded directories

  
     NB: this package now depends on R (>= 3.5.0)
     WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3catchN_census_sard_hake.rds'  WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3catchage_census_sard_hake.rds'  WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3catchlengthwt_census_sard_hake.rds'  WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3lengthwt_census_sard_hake.rds'  WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3natage_census_sard_hake.rds'  WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3surveyBcensus.rds'  WARNING: Added dependency on R >= 3.5.0 because serialized objects in  serialize/load version 3 cannot be read in older versions of R.  File(s) containing such objects:  'atlantisom/nemow_demo/CC_2063_OA_OFF_22/CCV3surveyNcensus.rds'
-  building 'atlantisom_0.1.tar.gz'

  
   

* installing *source* package 'atlantisom' ...
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
  converting help for package 'atlantisom'
    finding HTML links ... done
    SS_write_biol                           html  
    SS_write_comps                          html  
    SS_write_ts                             html  
    aggregateData                           html  
    aggregateDensityData                    html  
    aggregate_comps                         html  
    calc_Z                                  html  
    calc_age2length                         html  
    calc_biomass_age                        html  
    calc_pred_diet                          html  
    calc_stage2age                          html  
    calc_timestep2time                      html  
    create_env                              html  
    create_fishery_subset                   html  
    finding level-2 HTML links ... done

Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/create_fishery_subset.Rd:20: missing link 'create_fishery_data'
    create_survey                           html  
Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/create_survey.Rd:20: missing link 'create_fishery_data'
    get_boundary                            html  
    load_biolprm                            html  
    load_box                                html  
    load_boxarea                            html  
    load_bps                                html  
    load_catch                              html  
    load_diet_comp                          html  
    load_fgs                                html  
    load_meta                               html  
    load_nc                                 html  
    load_nc_physics                         html  
    load_runprm                             html  
    load_yoy                                html  
    reformat_compositions                   html  
Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/reformat_compositions.Rd:22: missing link 'create_fishery_data'
    run_stocksynthesis                      html  
    run_truth                               html  
    sample_ages                             html  
Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/sample_ages.Rd:20: missing link 'create_fishery_data'
    sample_diet                             html  
    sample_fish                             html  
Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/sample_fish.Rd:20: missing link 'create_fishery_data'
    sample_survey_biomass                   html  
Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/sample_survey_biomass.Rd:20: missing link 'create_fishery_data'
    sample_survey_numbers                   html  
Rd warning: C:/Users/chris/AppData/Local/Temp/RtmpCOxRni/R.INSTALL660541e4c54/atlantisom/man/sample_survey_numbers.Rd:20: missing link 'create_fishery_data'
    vbgf_func                               html  
    write_meta                              html  
** building package indices
** installing vignettes
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (atlantisom)
In R CMD INSTALL
library(atlantisom)

Introduction

This demonstrates the Atlantis to atlantisom to SS3 workflow with the California Current run that includes climate forcing, recruitment variability, and the fishing scenario outlined for our project in Norway: “output_CC_2063_OA_OFF_22”.

We will use Atlantis model output to generate time series and composition data for a species “sardine”, that doesn’t require any age class splitting.

species_ss <- c("Pacific_sardine")
age_classes <- 1:10
source(here("config/NEMOWConfig.R"))
needed.files <- ls()
print(unlist(lapply(needed.files, FUN=get)))
 [1] "1"                                                                      
 [2] "2"                                                                      
 [3] "3"                                                                      
 [4] "4"                                                                      
 [5] "5"                                                                      
 [6] "6"                                                                      
 [7] "7"                                                                      
 [8] "8"                                                                      
 [9] "9"                                                                      
[10] "10"                                                                     
[11] "outputCCV3BiomIndx.txt"                                                 
[12] "CalCurrentV3_Biol.prm"                                                  
[13] "DIVCalCurrentV3_Biol.nc"                                                
[14] "CalCurrentV3_utm.bgm"                                                   
[15] "outputCCV3Catch.txt"                                                    
[16] "C:/Users/chris/Documents/GitHub/atlantisom/nemow_demo/CC_2063_OA_OFF_22"
[17] "CalCurrentV3Groups.csv"                                                 
[18] "DIVCalCurrentV3_Biol.nc"                                                
[19] "TRUE"                                                                   
[20] "CalCurrentV3_run.xml"                                                   
[21] "CCV3"                                                                   
[22] "Pacific_sardine"                                                        

The below example requires a folder in your project directory named “atlantisom” containing the above files from an Atlantis output.

#Check for needed files
#Load functional groups
funct.groups <- load_fgs(dir=d.name,
                         file_fgs = functional.groups.file)
#Get just the names of active functional groups
funct.group.names <- funct.groups %>% 
  filter(IsTurnedOn == 1) %>%
  select(Name) %>%
  .$Name

This can be run with species_ss in select_groups to get results only for that species. WARNING: running with all species takes a long time! (50 minutes for this output)

  #Store all loaded results into an R object
sardine_truth <- if(!file.exists(file.path(d.name, 
                          "sardine_truth.RData"))){
  #Store all loaded results into an R object
  sardine_truth <- run_truth(scenario = scenario.name,
                     dir = d.name,
                     file_fgs = functional.groups.file,
                     file_bgm = box.file,
                     select_groups = "Pacific_sardine",
                     file_init = initial.conditions.file,
                     file_biolprm = biol.prm.file,
                     file_runprm = run.prm.file,
                     verbose = TRUE
  )
} else {
  sardine_truth <- get(load(file.path(d.name,
                              "sardine_truth.RData")))
}

This truth object shows the true population dynamics for sardine from Atlantis which we need for reference to compare with estimated population dynamics from the stock assessment estimation models.

Then we will have a function that implements the “survey” that produces the stock assessment inputs and sends those to the SS file writing functions. Here the survey functions are still separate.

Derive “Data” from Atlantis to give to SS3

Specify our survey sampling. This could come from other information such as the overlap of actual survey stations with OM polygons, experiments evaluating survey selectivity and efficiency, actual sample-based survey cv, etc.

Here are specifications which approximate the true sardine acoustic survey

# generalized timesteps all models
runpar <- load_runprm(d.name, run.prm.file)
noutsteps <- runpar$tstop/runpar$outputstep
stepperyr <- if(runpar$outputstepunit=="days") 365/runpar$toutinc
midptyr <- round(median(seq(0,stepperyr)))
# a survey that takes place once per year mid year
annualmidyear <- seq(midptyr, noutsteps, stepperyr)
# learned the hard way this can be different from ecosystem outputs
fstepperyr <- if(runpar$outputstepunit=="days") 365/runpar$toutfinc
# should return all model areas
boxpars <- load_box(d.name, box.file)
boxall <- c(0:(boxpars$nbox - 1))
source(here("config/sardine_survey.R"))

Get input survey biomass for SS (these have q, selectivity, cv)

#Sample survey - 3rd timestep simulates a summer survey
survey_out <- create_survey(dat=sardine_truth$nums, 
                            time=survey_sample_full, 
                            species=species, 
                            boxes=boxall, 
                            effic=effic, 
                            selex=sel)
#Try a biomass based survey for comparison
survey_outB <- create_survey(dat=sardine_truth$biomass_ages,
                            time=survey_sample_full,
                            species=species,
                            boxes=boxall,
                            effic=effic,
                            selex=sel)
#Set effective sample size for age compositions
effN <- surveyEffN
highEffN <- data.frame(species=species, effN=rep(effN, length(species)))
#Sample fish for age composition
age_comp_data <- sample_fish(survey_out, highEffN)
# aggregate true resn per survey design
survey_aggresnstd <- aggregateDensityData(dat = sardine_truth$resn,
                                          time = survey_sample_full,
                                          species = species,
                                          boxes = boxall)
# aggregate true structn per survey design
survey_aggstructnstd <- aggregateDensityData(dat =sardine_truth$structn,
                                             time = survey_sample_full,
                                             species = species,
                                             boxes = boxall)
ss_structnstd <- sample_fish(survey_aggstructnstd,
                             effN,
                             sample=FALSE)
ss_resnstd <- sample_fish(survey_aggresnstd,
                          effN,
                          sample=FALSE)
#Extract length composition data
ss_length_stdsurv <- calc_age2length(structn = ss_structnstd,
                                     resn = ss_resnstd,
                                     nums = age_comp_data,
                                     biolprm = sardine_truth$biolprm, fgs = sardine_truth$fgs,
                                     CVlenage = CVs$lenage, remove.zeroes=TRUE)
#Need to replace with interp function
wtAtAge <- ss_length_stdsurv$muweight %>%
  select(species, agecl, time, wtAtAge = atoutput) %>%
  mutate(wtAtAge = wtAtAge/1000)
# CV function
cv <- data.frame(species=species_ss, cv=CVs$survey)
#Sample survey biomass
survObsBiom <- sample_survey_biomass(dat=survey_out,cv=cv,wtAtAge)
# check against survey with truth$biomass_ages output
wtage1 <- data.frame(species=rep(species_ss, each=max(age_classes)),
                    agecl=rep(c(age_classes),length(species_ss)),
                    wtAtAge=rep(1000.0,length(species_ss)*max(age_classes)))
survObsBiomB <- sample_survey_biomass(dat=survey_outB,cv=cv,wtage1)
# survey numbers, not sure which SS needs?
survObsNum <- sample_survey_numbers(dat=survey_out,cv=cv)

Get composition inputs for SS (survey and fishery catch at age, survey and fishery lengths, survey and fishey weight at age).

Because catch composition information goes in to the assessment as a proportion, we can use fishery catch at age from this legacy codebase even with absolute catch numbers likely half what they should be overall.

# Survey length comps and wtage done above to get survey ts using nums*wtage approach
#We end up using CAAL for the survey below, so let's generate fishery age comps instead
effN <- fisheryEffN/fstepperyr
effN <- data.frame(species=species, effN=effN)
#catch at age each timestep summed over polygons
# catch at age by area and timestep
catch_numbers <-  create_fishery_subset(dat = sardine_truth$catch,
                                         time = fish_times,
                                         species = species,
                                         boxes = boxall)
catch_numsss_samp <- sample_fish(catch_numbers, effN)
rm(catch_numbers)
gc()
           used  (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells  1182750  63.2   20832527 1112.6  40688531 2173.1
Vcells 46855901 357.5  128263088  978.6 250506075 1911.3
#Get weights
# aggregate true resn per fishery subset design
catch_aggresnss <- aggregateDensityData(dat = sardine_truth$resn,
                                 time = fish_times,
                                 species = species,
                                 boxes = boxall)
# aggregate true structn fishery subsetdesign
catch_aggstructnss <- aggregateDensityData(dat = sardine_truth$structn,
                                 time = fish_times,
                                 species = species,
                                 boxes = boxall)
#dont sample these, just aggregate them using median
catch_structnss_samp <- sample_fish(catch_aggstructnss, effN, sample = FALSE)
catch_resnss_samp <-  sample_fish(catch_aggresnss, effN, sample = FALSE)
# these fishery lengths and weight at age are each output timestep
catch_lengthwt_samp <- calc_age2length(structn = catch_structnss_samp,
                                 resn = catch_resnss_samp,
                                 nums = catch_numsss_samp,
                                 biolprm = sardine_truth$biolprm, 
                                 fgs = sardine_truth$fgs,
                                 maxbin = maxbin,
                                 CVlenage = CVs$lenage, remove.zeroes=TRUE)
LS0tDQp0aXRsZTogImF0bGFudGlzb20gZGVtbyBub3RlYm9vayINCmF1dGhvcjogIlNhcmFoIEdhaWNoYXMgYW5kIENocmlzdGluZSBTdGF3aXR6Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIg0Kb3V0cHV0Og0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpyZXF1aXJlKHRpZHlyKQ0KcmVxdWlyZShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZ2dmb3JjZSkNCmxpYnJhcnkoZ2d0aGVtZXMpDQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInI0YXRsYW50aXMvYXRsYW50aXNvbSIpDQpsaWJyYXJ5KGF0bGFudGlzb20pDQpgYGANCg0KIyMgSW50cm9kdWN0aW9uDQoNClRoaXMgZGVtb25zdHJhdGVzIHRoZSBBdGxhbnRpcyB0byBgYXRsYW50aXNvbWAgdG8gU1MzIHdvcmtmbG93IHdpdGggdGhlIENhbGlmb3JuaWEgQ3VycmVudCBydW4gdGhhdCBpbmNsdWRlcyBjbGltYXRlIGZvcmNpbmcsIHJlY3J1aXRtZW50IHZhcmlhYmlsaXR5LCBhbmQgdGhlIGZpc2hpbmcgc2NlbmFyaW8gb3V0bGluZWQgZm9yIG91ciBwcm9qZWN0IGluIE5vcndheTogIm91dHB1dF9DQ18yMDYzX09BX09GRl8yMiIuIA0KDQpXZSB3aWxsIHVzZSBBdGxhbnRpcyBtb2RlbCBvdXRwdXQgdG8gZ2VuZXJhdGUgdGltZSBzZXJpZXMgYW5kIGNvbXBvc2l0aW9uIGRhdGEgZm9yIGEgc3BlY2llcyAic2FyZGluZSIsIHRoYXQgZG9lc24ndCByZXF1aXJlIGFueSBhZ2UgY2xhc3Mgc3BsaXR0aW5nLiANCg0KDQpgYGB7ciBpbml0aWFsaXplfQ0KDQpzcGVjaWVzX3NzIDwtIGMoIlBhY2lmaWNfc2FyZGluZSIpDQphZ2VfY2xhc3NlcyA8LSAxOjEwDQoNCnNvdXJjZShoZXJlKCJjb25maWcvTkVNT1dDb25maWcuUiIpKQ0KbmVlZGVkLmZpbGVzIDwtIGxzKCkNCnByaW50KHVubGlzdChsYXBwbHkobmVlZGVkLmZpbGVzLCBGVU49Z2V0KSkpDQoNCmBgYA0KDQpUaGUgYmVsb3cgZXhhbXBsZSByZXF1aXJlcyBhIGZvbGRlciBpbiB5b3VyIHByb2plY3QgZGlyZWN0b3J5IG5hbWVkICJhdGxhbnRpc29tIiBjb250YWluaW5nIHRoZSBhYm92ZSBmaWxlcyBmcm9tIGFuIEF0bGFudGlzIG91dHB1dC4NCg0KYGBge3IgZ2V0X25hbWVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI0NoZWNrIGZvciBuZWVkZWQgZmlsZXMNCg0KDQojTG9hZCBmdW5jdGlvbmFsIGdyb3Vwcw0KZnVuY3QuZ3JvdXBzIDwtIGxvYWRfZmdzKGRpcj1kLm5hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9mZ3MgPSBmdW5jdGlvbmFsLmdyb3Vwcy5maWxlKQ0KI0dldCBqdXN0IHRoZSBuYW1lcyBvZiBhY3RpdmUgZnVuY3Rpb25hbCBncm91cHMNCmZ1bmN0Lmdyb3VwLm5hbWVzIDwtIGZ1bmN0Lmdyb3VwcyAlPiUgDQogIGZpbHRlcihJc1R1cm5lZE9uID09IDEpICU+JQ0KICBzZWxlY3QoTmFtZSkgJT4lDQogIC4kTmFtZQ0KDQpgYGANCg0KVGhpcyBjYW4gYmUgcnVuIHdpdGggYHNwZWNpZXNfc3NgIGluIGBzZWxlY3RfZ3JvdXBzYCB0byBnZXQgcmVzdWx0cyBvbmx5IGZvciB0aGF0IHNwZWNpZXMuIFdBUk5JTkc6IHJ1bm5pbmcgd2l0aCBhbGwgc3BlY2llcyB0YWtlcyBhIGxvbmcgdGltZSEgKDUwIG1pbnV0ZXMgZm9yIHRoaXMgb3V0cHV0KQ0KDQpgYGB7ciBnZXRfdHJ1dGhfc3N9DQogICNTdG9yZSBhbGwgbG9hZGVkIHJlc3VsdHMgaW50byBhbiBSIG9iamVjdA0Kc2FyZGluZV90cnV0aCA8LSBpZighZmlsZS5leGlzdHMoZmlsZS5wYXRoKGQubmFtZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJzYXJkaW5lX3RydXRoLlJEYXRhIikpKXsNCiAgI1N0b3JlIGFsbCBsb2FkZWQgcmVzdWx0cyBpbnRvIGFuIFIgb2JqZWN0DQogIHNhcmRpbmVfdHJ1dGggPC0gcnVuX3RydXRoKHNjZW5hcmlvID0gc2NlbmFyaW8ubmFtZSwNCiAgICAgICAgICAgICAgICAgICAgIGRpciA9IGQubmFtZSwNCiAgICAgICAgICAgICAgICAgICAgIGZpbGVfZmdzID0gZnVuY3Rpb25hbC5ncm91cHMuZmlsZSwNCiAgICAgICAgICAgICAgICAgICAgIGZpbGVfYmdtID0gYm94LmZpbGUsDQogICAgICAgICAgICAgICAgICAgICBzZWxlY3RfZ3JvdXBzID0gIlBhY2lmaWNfc2FyZGluZSIsDQogICAgICAgICAgICAgICAgICAgICBmaWxlX2luaXQgPSBpbml0aWFsLmNvbmRpdGlvbnMuZmlsZSwNCiAgICAgICAgICAgICAgICAgICAgIGZpbGVfYmlvbHBybSA9IGJpb2wucHJtLmZpbGUsDQogICAgICAgICAgICAgICAgICAgICBmaWxlX3J1bnBybSA9IHJ1bi5wcm0uZmlsZSwNCiAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFDQogICkNCn0gZWxzZSB7DQogIHNhcmRpbmVfdHJ1dGggPC0gZ2V0KGxvYWQoZmlsZS5wYXRoKGQubmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzYXJkaW5lX3RydXRoLlJEYXRhIikpKQ0KfQ0KDQpgYGANCg0KVGhpcyB0cnV0aCBvYmplY3Qgc2hvd3MgdGhlIHRydWUgcG9wdWxhdGlvbiBkeW5hbWljcyBmb3Igc2FyZGluZSBmcm9tIEF0bGFudGlzIHdoaWNoIHdlIG5lZWQgZm9yIHJlZmVyZW5jZSB0byBjb21wYXJlIHdpdGggZXN0aW1hdGVkIHBvcHVsYXRpb24gZHluYW1pY3MgZnJvbSB0aGUgc3RvY2sgYXNzZXNzbWVudCBlc3RpbWF0aW9uIG1vZGVscy4gDQoNClRoZW4gd2Ugd2lsbCBoYXZlIGEgZnVuY3Rpb24gdGhhdCBpbXBsZW1lbnRzIHRoZSAic3VydmV5IiB0aGF0IHByb2R1Y2VzIHRoZSBzdG9jayBhc3Nlc3NtZW50IGlucHV0cyBhbmQgc2VuZHMgdGhvc2UgdG8gdGhlIFNTIGZpbGUgd3JpdGluZyBmdW5jdGlvbnMuIEhlcmUgdGhlIHN1cnZleSBmdW5jdGlvbnMgYXJlIHN0aWxsIHNlcGFyYXRlLg0KDQoNCiMjIERlcml2ZSDigJxEYXRh4oCdIGZyb20gQXRsYW50aXMgdG8gZ2l2ZSB0byBTUzMNCg0KU3BlY2lmeSBvdXIgc3VydmV5IHNhbXBsaW5nLiBUaGlzIGNvdWxkIGNvbWUgZnJvbSBvdGhlciBpbmZvcm1hdGlvbiBzdWNoIGFzIHRoZSBvdmVybGFwIG9mIGFjdHVhbCBzdXJ2ZXkgc3RhdGlvbnMgd2l0aCBPTSBwb2x5Z29ucywgZXhwZXJpbWVudHMgZXZhbHVhdGluZyBzdXJ2ZXkgc2VsZWN0aXZpdHkgYW5kIGVmZmljaWVuY3ksIGFjdHVhbCBzYW1wbGUtYmFzZWQgc3VydmV5IGN2LCBldGMuIA0KDQpIZXJlIGFyZSBzcGVjaWZpY2F0aW9ucyB3aGljaCBhcHByb3hpbWF0ZSB0aGUgdHJ1ZSBzYXJkaW5lIGFjb3VzdGljIHN1cnZleQ0KDQpgYGB7ciBzYXJkaW5lLXN1cnZleS1zcGVjfQ0KDQojIGdlbmVyYWxpemVkIHRpbWVzdGVwcyBhbGwgbW9kZWxzDQpydW5wYXIgPC0gbG9hZF9ydW5wcm0oZC5uYW1lLCBydW4ucHJtLmZpbGUpDQpub3V0c3RlcHMgPC0gcnVucGFyJHRzdG9wL3J1bnBhciRvdXRwdXRzdGVwDQpzdGVwcGVyeXIgPC0gaWYocnVucGFyJG91dHB1dHN0ZXB1bml0PT0iZGF5cyIpIDM2NS9ydW5wYXIkdG91dGluYw0KbWlkcHR5ciA8LSByb3VuZChtZWRpYW4oc2VxKDAsc3RlcHBlcnlyKSkpDQoNCiMgYSBzdXJ2ZXkgdGhhdCB0YWtlcyBwbGFjZSBvbmNlIHBlciB5ZWFyIG1pZCB5ZWFyDQphbm51YWxtaWR5ZWFyIDwtIHNlcShtaWRwdHlyLCBub3V0c3RlcHMsIHN0ZXBwZXJ5cikNCiMgbGVhcm5lZCB0aGUgaGFyZCB3YXkgdGhpcyBjYW4gYmUgZGlmZmVyZW50IGZyb20gZWNvc3lzdGVtIG91dHB1dHMNCmZzdGVwcGVyeXIgPC0gaWYocnVucGFyJG91dHB1dHN0ZXB1bml0PT0iZGF5cyIpIDM2NS9ydW5wYXIkdG91dGZpbmMNCg0KIyBzaG91bGQgcmV0dXJuIGFsbCBtb2RlbCBhcmVhcw0KYm94cGFycyA8LSBsb2FkX2JveChkLm5hbWUsIGJveC5maWxlKQ0KYm94YWxsIDwtIGMoMDooYm94cGFycyRuYm94IC0gMSkpDQoNCg0Kc291cmNlKGhlcmUoImNvbmZpZy9zYXJkaW5lX3N1cnZleS5SIikpDQoNCmBgYA0KDQpHZXQgaW5wdXQgc3VydmV5IGJpb21hc3MgZm9yIFNTICh0aGVzZSBoYXZlIHEsIHNlbGVjdGl2aXR5LCBjdikNCg0KYGBge3IgdG9TUy1zdXJ2ZXl0cy1jb21wc30NCg0KI1NhbXBsZSBzdXJ2ZXkgLSAzcmQgdGltZXN0ZXAgc2ltdWxhdGVzIGEgc3VtbWVyIHN1cnZleQ0Kc3VydmV5X291dCA8LSBjcmVhdGVfc3VydmV5KGRhdD1zYXJkaW5lX3RydXRoJG51bXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWU9c3VydmV5X3NhbXBsZV9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPXNwZWNpZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJveGVzPWJveGFsbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWZmaWM9ZWZmaWMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGV4PXNlbCkNCg0KI1RyeSBhIGJpb21hc3MgYmFzZWQgc3VydmV5IGZvciBjb21wYXJpc29uDQpzdXJ2ZXlfb3V0QiA8LSBjcmVhdGVfc3VydmV5KGRhdD1zYXJkaW5lX3RydXRoJGJpb21hc3NfYWdlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lPXN1cnZleV9zYW1wbGVfZnVsbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPXNwZWNpZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94ZXM9Ym94YWxsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmljPWVmZmljLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGV4PXNlbCkNCg0KDQojU2V0IGVmZmVjdGl2ZSBzYW1wbGUgc2l6ZSBmb3IgYWdlIGNvbXBvc2l0aW9ucw0KZWZmTiA8LSBzdXJ2ZXlFZmZODQpoaWdoRWZmTiA8LSBkYXRhLmZyYW1lKHNwZWNpZXM9c3BlY2llcywgZWZmTj1yZXAoZWZmTiwgbGVuZ3RoKHNwZWNpZXMpKSkNCg0KI1NhbXBsZSBmaXNoIGZvciBhZ2UgY29tcG9zaXRpb24NCmFnZV9jb21wX2RhdGEgPC0gc2FtcGxlX2Zpc2goc3VydmV5X291dCwgaGlnaEVmZk4pDQoNCiMgYWdncmVnYXRlIHRydWUgcmVzbiBwZXIgc3VydmV5IGRlc2lnbg0Kc3VydmV5X2FnZ3Jlc25zdGQgPC0gYWdncmVnYXRlRGVuc2l0eURhdGEoZGF0ID0gc2FyZGluZV90cnV0aCRyZXNuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZSA9IHN1cnZleV9zYW1wbGVfZnVsbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNpZXMgPSBzcGVjaWVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94ZXMgPSBib3hhbGwpDQoNCiMgYWdncmVnYXRlIHRydWUgc3RydWN0biBwZXIgc3VydmV5IGRlc2lnbg0Kc3VydmV5X2FnZ3N0cnVjdG5zdGQgPC0gYWdncmVnYXRlRGVuc2l0eURhdGEoZGF0ID1zYXJkaW5lX3RydXRoJHN0cnVjdG4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lID0gc3VydmV5X3NhbXBsZV9mdWxsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llcyA9IHNwZWNpZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3hlcyA9IGJveGFsbCkNCg0Kc3Nfc3RydWN0bnN0ZCA8LSBzYW1wbGVfZmlzaChzdXJ2ZXlfYWdnc3RydWN0bnN0ZCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWZmTiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlPUZBTFNFKQ0Kc3NfcmVzbnN0ZCA8LSBzYW1wbGVfZmlzaChzdXJ2ZXlfYWdncmVzbnN0ZCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZWZmTiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlPUZBTFNFKQ0KDQojRXh0cmFjdCBsZW5ndGggY29tcG9zaXRpb24gZGF0YQ0Kc3NfbGVuZ3RoX3N0ZHN1cnYgPC0gY2FsY19hZ2UybGVuZ3RoKHN0cnVjdG4gPSBzc19zdHJ1Y3Ruc3RkLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc24gPSBzc19yZXNuc3RkLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bXMgPSBhZ2VfY29tcF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpb2xwcm0gPSBzYXJkaW5lX3RydXRoJGJpb2xwcm0sIGZncyA9IHNhcmRpbmVfdHJ1dGgkZmdzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENWbGVuYWdlID0gQ1ZzJGxlbmFnZSwgcmVtb3ZlLnplcm9lcz1UUlVFKQ0KDQojTmVlZCB0byByZXBsYWNlIHdpdGggaW50ZXJwIGZ1bmN0aW9uDQp3dEF0QWdlIDwtIHNzX2xlbmd0aF9zdGRzdXJ2JG11d2VpZ2h0ICU+JQ0KICBzZWxlY3Qoc3BlY2llcywgYWdlY2wsIHRpbWUsIHd0QXRBZ2UgPSBhdG91dHB1dCkgJT4lDQogIG11dGF0ZSh3dEF0QWdlID0gd3RBdEFnZS8xMDAwKQ0KDQojIENWIGZ1bmN0aW9uDQpjdiA8LSBkYXRhLmZyYW1lKHNwZWNpZXM9c3BlY2llc19zcywgY3Y9Q1ZzJHN1cnZleSkNCg0KI1NhbXBsZSBzdXJ2ZXkgYmlvbWFzcw0Kc3Vydk9ic0Jpb20gPC0gc2FtcGxlX3N1cnZleV9iaW9tYXNzKGRhdD1zdXJ2ZXlfb3V0LGN2PWN2LHd0QXRBZ2UpDQoNCiMgY2hlY2sgYWdhaW5zdCBzdXJ2ZXkgd2l0aCB0cnV0aCRiaW9tYXNzX2FnZXMgb3V0cHV0DQp3dGFnZTEgPC0gZGF0YS5mcmFtZShzcGVjaWVzPXJlcChzcGVjaWVzX3NzLCBlYWNoPW1heChhZ2VfY2xhc3NlcykpLA0KICAgICAgICAgICAgICAgICAgICBhZ2VjbD1yZXAoYyhhZ2VfY2xhc3NlcyksbGVuZ3RoKHNwZWNpZXNfc3MpKSwNCiAgICAgICAgICAgICAgICAgICAgd3RBdEFnZT1yZXAoMTAwMC4wLGxlbmd0aChzcGVjaWVzX3NzKSptYXgoYWdlX2NsYXNzZXMpKSkNCg0Kc3Vydk9ic0Jpb21CIDwtIHNhbXBsZV9zdXJ2ZXlfYmlvbWFzcyhkYXQ9c3VydmV5X291dEIsY3Y9Y3Ysd3RhZ2UxKQ0KDQojIHN1cnZleSBudW1iZXJzLCBub3Qgc3VyZSB3aGljaCBTUyBuZWVkcz8NCnN1cnZPYnNOdW0gPC0gc2FtcGxlX3N1cnZleV9udW1iZXJzKGRhdD1zdXJ2ZXlfb3V0LGN2PWN2KQ0KDQoNCmBgYA0KDQoNCkdldCBjb21wb3NpdGlvbiBpbnB1dHMgZm9yIFNTIChzdXJ2ZXkgYW5kIGZpc2hlcnkgY2F0Y2ggYXQgYWdlLCBzdXJ2ZXkgYW5kIGZpc2hlcnkgbGVuZ3Rocywgc3VydmV5IGFuZCBmaXNoZXkgd2VpZ2h0IGF0IGFnZSkuDQoNCkJlY2F1c2UgY2F0Y2ggY29tcG9zaXRpb24gaW5mb3JtYXRpb24gZ29lcyBpbiB0byB0aGUgYXNzZXNzbWVudCBhcyBhIHByb3BvcnRpb24sIHdlIGNhbiB1c2UgZmlzaGVyeSBjYXRjaCBhdCBhZ2UgZnJvbSB0aGlzIGxlZ2FjeSBjb2RlYmFzZSBldmVuIHdpdGggYWJzb2x1dGUgY2F0Y2ggbnVtYmVycyBsaWtlbHkgaGFsZiB3aGF0IHRoZXkgc2hvdWxkIGJlIG92ZXJhbGwuDQoNCg0KYGBge3IgdG9TUy1maXNoZXJ5Y29tcHN9DQoNCiMgU3VydmV5IGxlbmd0aCBjb21wcyBhbmQgd3RhZ2UgZG9uZSBhYm92ZSB0byBnZXQgc3VydmV5IHRzIHVzaW5nIG51bXMqd3RhZ2UgYXBwcm9hY2gNCg0KI1dlIGVuZCB1cCB1c2luZyBDQUFMIGZvciB0aGUgc3VydmV5IGJlbG93LCBzbyBsZXQncyBnZW5lcmF0ZSBmaXNoZXJ5IGFnZSBjb21wcyBpbnN0ZWFkDQplZmZOIDwtIGZpc2hlcnlFZmZOL2ZzdGVwcGVyeXINCmVmZk4gPC0gZGF0YS5mcmFtZShzcGVjaWVzPXNwZWNpZXMsIGVmZk49ZWZmTikNCg0KI2NhdGNoIGF0IGFnZSBlYWNoIHRpbWVzdGVwIHN1bW1lZCBvdmVyIHBvbHlnb25zDQojIGNhdGNoIGF0IGFnZSBieSBhcmVhIGFuZCB0aW1lc3RlcA0KY2F0Y2hfbnVtYmVycyA8LSAgY3JlYXRlX2Zpc2hlcnlfc3Vic2V0KGRhdCA9IHNhcmRpbmVfdHJ1dGgkY2F0Y2gsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWUgPSBmaXNoX3RpbWVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzID0gc3BlY2llcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94ZXMgPSBib3hhbGwpDQoNCmNhdGNoX251bXNzc19zYW1wIDwtIHNhbXBsZV9maXNoKGNhdGNoX251bWJlcnMsIGVmZk4pDQoNCnJtKGNhdGNoX251bWJlcnMpDQpnYygpDQojR2V0IHdlaWdodHMNCiMgYWdncmVnYXRlIHRydWUgcmVzbiBwZXIgZmlzaGVyeSBzdWJzZXQgZGVzaWduDQpjYXRjaF9hZ2dyZXNuc3MgPC0gYWdncmVnYXRlRGVuc2l0eURhdGEoZGF0ID0gc2FyZGluZV90cnV0aCRyZXNuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZSA9IGZpc2hfdGltZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzID0gc3BlY2llcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJveGVzID0gYm94YWxsKQ0KDQojIGFnZ3JlZ2F0ZSB0cnVlIHN0cnVjdG4gZmlzaGVyeSBzdWJzZXRkZXNpZ24NCmNhdGNoX2FnZ3N0cnVjdG5zcyA8LSBhZ2dyZWdhdGVEZW5zaXR5RGF0YShkYXQgPSBzYXJkaW5lX3RydXRoJHN0cnVjdG4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lID0gZmlzaF90aW1lcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNpZXMgPSBzcGVjaWVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94ZXMgPSBib3hhbGwpDQoNCiNkb250IHNhbXBsZSB0aGVzZSwganVzdCBhZ2dyZWdhdGUgdGhlbSB1c2luZyBtZWRpYW4NCmNhdGNoX3N0cnVjdG5zc19zYW1wIDwtIHNhbXBsZV9maXNoKGNhdGNoX2FnZ3N0cnVjdG5zcywgZWZmTiwgc2FtcGxlID0gRkFMU0UpDQoNCmNhdGNoX3Jlc25zc19zYW1wIDwtICBzYW1wbGVfZmlzaChjYXRjaF9hZ2dyZXNuc3MsIGVmZk4sIHNhbXBsZSA9IEZBTFNFKQ0KDQojIHRoZXNlIGZpc2hlcnkgbGVuZ3RocyBhbmQgd2VpZ2h0IGF0IGFnZSBhcmUgZWFjaCBvdXRwdXQgdGltZXN0ZXANCmNhdGNoX2xlbmd0aHd0X3NhbXAgPC0gY2FsY19hZ2UybGVuZ3RoKHN0cnVjdG4gPSBjYXRjaF9zdHJ1Y3Ruc3Nfc2FtcCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc24gPSBjYXRjaF9yZXNuc3Nfc2FtcCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bXMgPSBjYXRjaF9udW1zc3Nfc2FtcCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpb2xwcm0gPSBzYXJkaW5lX3RydXRoJGJpb2xwcm0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmdzID0gc2FyZGluZV90cnV0aCRmZ3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhiaW4gPSBtYXhiaW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDVmxlbmFnZSA9IENWcyRsZW5hZ2UsIHJlbW92ZS56ZXJvZXM9VFJVRSkNCg0KDQpgYGANCg0K