-
Notifications
You must be signed in to change notification settings - Fork 0
/
offline-search-index.cb25daf7d72d00f7e1a55b2710a18f9e.json
83 lines (1 loc) · 928 KB
/
offline-search-index.cb25daf7d72d00f7e1a55b2710a18f9e.json
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
[{"body":"To start, we use the same workflow instance like the last section.\nsal \u003c- SPRproject(logs.dir= \".SPRproject\", sys.file=\".SPRproject/SYSargsList.yml\") ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' sal ## Instance of 'SYSargsList': ## No workflow steps added Adding the first step The first step is R code based, and we are splitting the iris dataset by Species and for each Species will be saved on file. Please note that this code will not be executed now; it is just store in the container for further execution.\nThis constructor function requires the step_name and the R-based code under the code argument. The R code should be enclosed by braces ({}) and separated by a new line.\nappendStep(sal) \u003c- LineWise(code = { mapply(function(x, y) write.csv(x, y), split(iris, factor(iris$Species)), file.path(\"results\", paste0(names(split(iris, factor(iris$Species))), \".csv\")) ) }, step_name = \"export_iris\") For a brief overview of the workflow, we can check the object as follows:\nsal ## Instance of 'SYSargsList': ## WF Steps: ## 1. export_iris --\u003e Status: Pending ## Also, for printing and double-check the R code in the step, we can use the codeLine method:\ncodeLine(sal) ## export_iris ## mapply(function(x, y) write.csv(x, y), split(iris, factor(iris$Species)), file.path(\"results\", paste0(names(split(iris, factor(iris$Species))), \".csv\"))) Adding more steps Next, an example of how to compress the exported files using gzip command-line.\nThe constructor function creates an SYSargsList S4 class object using data from three input files:\n- CWL command-line specification file (`wf_file` argument); - Input variables (`input_file` argument); - Targets file (`targets` argument). In CWL, files with the extension .cwl define the parameters of a chosen command-line step or workflow, while files with the extension .yml define the input variables of command-line steps.\nThe targets file is optional for workflow steps lacking input files. The connection between input variables and the targets file is defined under the inputvars argument. It is required a named vector, where each element name needs to match with column names in the targets file, and the value must match the names of the input variables defined in the *.yml files (see Figure ??).\nA detailed description of the dynamic between input variables and targets files can be found here. In addition, the CWL syntax overview can be found here.\nBesides all the data form targets, wf_file, input_file and dir_path arguments, SYSargsList constructor function options include:\n step_name: a unique name for the step. This is not mandatory; however, it is highly recommended. If no name is provided, a default step_x, where x reflects the step index, will be added. dir: this option allows creating an exclusive subdirectory for the step in the workflow. All the outfiles and log files for this particular step will be generated in the respective folders. dependency: after the first step, all the additional steps appended to the workflow require the information of the dependency tree. The appendStep\u003c- method is used to append a new step in the workflow.\ntargetspath \u003c- system.file(\"extdata/cwl/gunzip\", \"targets_gunzip.txt\", package = \"systemPipeR\") appendStep(sal) \u003c- SYSargsList(step_name = \"gzip\", targets = targetspath, dir = TRUE, wf_file = \"gunzip/workflow_gzip.cwl\", input_file = \"gunzip/gzip.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(FileName = \"_FILE_PATH_\", SampleName = \"_SampleName_\"), dependency = \"export_iris\") Note: This will not work if the gzip is not available on your system (installed and exported to PATH) and may only work on Windows systems using PowerShell.\nFor a overview of the workflow, we can check the object as follows:\nsal ## Instance of 'SYSargsList': ## WF Steps: ## 1. export_iris --\u003e Status: Pending ## 2. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 2.1. gzip ## cmdlist: 3 | Pending: 3 ## Note that we have two steps, and it is expected three files from the second step. Also, the workflow status is Pending, which means the workflow object is rendered in R; however, we did not execute the workflow yet. In addition to this summary, it can be observed this step has three command lines.\nFor more details about the command-line rendered for each target file, it can be checked as follows:\ncmdlist(sal, step = \"gzip\") ## $gzip ## $gzip$SE ## $gzip$SE$gzip ## [1] \"gzip -c results/setosa.csv \u003e results/SE.csv.gz\" ## ## ## $gzip$VE ## $gzip$VE$gzip ## [1] \"gzip -c results/versicolor.csv \u003e results/VE.csv.gz\" ## ## ## $gzip$VI ## $gzip$VI$gzip ## [1] \"gzip -c results/virginica.csv \u003e results/VI.csv.gz\" Using the outfiles for the next step For building this step, all the previous procedures are being used to append the next step. However, here, we can observe power features that build the connectivity between steps in the workflow.\nIn this example, we would like to use the outfiles from gzip Step, as input from the next step, which is the gunzip. In this case, let’s look at the outfiles from the first step:\noutfiles(sal) ## $export_iris ## DataFrame with 0 rows and 0 columns ## ## $gzip ## DataFrame with 3 rows and 1 column ## gzip_file ## \u003ccharacter\u003e ## SE results/SE.csv.gz ## VE results/VE.csv.gz ## VI results/VI.csv.gz The column we want to use is “gzip_file”. For the argument targets in the SYSargsList function, it should provide the name of the correspondent step in the Workflow and which outfiles you would like to be incorporated in the next step. The argument inputvars allows the connectivity between outfiles and the new targets file. Here, the name of the previous outfiles should be provided it. Please note that all outfiles column names must be unique.\nIt is possible to keep all the original columns from the targets files or remove some columns for a clean targets file. The argument rm_targets_col provides this flexibility, where it is possible to specify the names of the columns that should be removed. If no names are passing here, the new columns will be appended.\nappendStep(sal) \u003c- SYSargsList(step_name = \"gunzip\", targets = \"gzip\", dir = TRUE, wf_file = \"gunzip/workflow_gunzip.cwl\", input_file = \"gunzip/gunzip.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(gzip_file = \"_FILE_PATH_\", SampleName = \"_SampleName_\"), rm_targets_col = \"FileName\", dependency = \"gzip\") We can check the targets automatically create for this step, based on the previous outfiles:\ntargetsWF(sal[3]) ## $gunzip ## DataFrame with 3 rows and 2 columns ## gzip_file SampleName ## \u003ccharacter\u003e \u003ccharacter\u003e ## SE results/SE.csv.gz SE ## VE results/VE.csv.gz VE ## VI results/VI.csv.gz VI We can also check all the expected outfiles for this particular step, as follows:\noutfiles(sal[3]) ## $gunzip ## DataFrame with 3 rows and 1 column ## gunzip_file ## \u003ccharacter\u003e ## SE results/SE.csv ## VE results/VE.csv ## VI results/VI.csv Now, we can observe that the third step has been added and contains one substep.\nsal ## Instance of 'SYSargsList': ## WF Steps: ## 1. export_iris --\u003e Status: Pending ## 2. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 2.1. gzip ## cmdlist: 3 | Pending: 3 ## 3. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gunzip ## cmdlist: 3 | Pending: 3 ## In addition, we can access all the command lines for each one of the substeps.\ncmdlist(sal[\"gzip\"], targets = 1) ## $gzip ## $gzip$SE ## $gzip$SE$gzip ## [1] \"gzip -c results/setosa.csv \u003e results/SE.csv.gz\" Getting data from a workflow instance The final step in this simple workflow is an R code step. For that, we are using the LineWise constructor function as demonstrated above.\nOne interesting feature showed here is the getColumn method that allows extracting the information for a workflow instance. Those files can be used in an R code, as demonstrated below.\ngetColumn(sal, step = \"gunzip\", 'outfiles') ## SE VE VI ## \"results/SE.csv\" \"results/VE.csv\" \"results/VI.csv\" appendStep(sal) \u003c- LineWise(code = { df \u003c- lapply(getColumn(sal, step = \"gunzip\", 'outfiles'), function(x) read.delim(x, sep = \",\")[-1]) df \u003c- do.call(rbind, df) stats \u003c- data.frame(cbind(mean = apply(df[,1:4], 2, mean), sd = apply(df[,1:4], 2, sd))) stats$species \u003c- rownames(stats) plot \u003c- ggplot2::ggplot(stats, ggplot2::aes(x = species, y = mean, fill = species)) + ggplot2::geom_bar(stat = \"identity\", color = \"black\", position = ggplot2::position_dodge()) + ggplot2::geom_errorbar(ggplot2::aes(ymin = mean-sd, ymax = mean+sd), width = .2, position = ggplot2::position_dodge(.9)) }, step_name = \"iris_stats\", dependency = \"gzip\") Session sessionInfo() ## R version 4.2.0 (2022-04-22) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.4 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] systemPipeR_2.3.4 ShortRead_1.54.0 ## [3] GenomicAlignments_1.32.0 SummarizedExperiment_1.26.1 ## [5] Biobase_2.56.0 MatrixGenerics_1.8.0 ## [7] matrixStats_0.62.0 BiocParallel_1.30.2 ## [9] Rsamtools_2.12.0 Biostrings_2.64.0 ## [11] XVector_0.36.0 GenomicRanges_1.48.0 ## [13] GenomeInfoDb_1.32.2 IRanges_2.30.0 ## [15] S4Vectors_0.34.0 BiocGenerics_0.42.0 ## ## loaded via a namespace (and not attached): ## [1] lattice_0.20-45 png_0.1-7 assertthat_0.2.1 ## [4] digest_0.6.29 utf8_1.2.2 R6_2.5.1 ## [7] evaluate_0.15 ggplot2_3.3.6 blogdown_1.10 ## [10] pillar_1.7.0 zlibbioc_1.42.0 rlang_1.0.2 ## [13] rstudioapi_0.13 jquerylib_0.1.4 Matrix_1.4-1 ## [16] rmarkdown_2.14 stringr_1.4.0 htmlwidgets_1.5.4 ## [19] RCurl_1.98-1.6 munsell_0.5.0 DelayedArray_0.22.0 ## [22] compiler_4.2.0 xfun_0.31 pkgconfig_2.0.3 ## [25] htmltools_0.5.2 tidyselect_1.1.2 tibble_3.1.7 ## [28] GenomeInfoDbData_1.2.8 bookdown_0.26 fansi_1.0.3 ## [31] dplyr_1.0.9 crayon_1.5.1 bitops_1.0-7 ## [34] grid_4.2.0 DBI_1.1.2 jsonlite_1.8.0 ## [37] gtable_0.3.0 lifecycle_1.0.1 magrittr_2.0.3 ## [40] scales_1.2.0 cli_3.3.0 stringi_1.7.6 ## [43] hwriter_1.3.2.1 latticeExtra_0.6-29 bslib_0.3.1 ## [46] generics_0.1.2 ellipsis_0.3.2 vctrs_0.4.1 ## [49] RColorBrewer_1.1-3 tools_4.2.0 glue_1.6.2 ## [52] purrr_0.3.4 jpeg_0.1-9 parallel_4.2.0 ## [55] fastmap_1.1.0 yaml_2.3.5 colorspace_2.0-3 ## [58] knitr_1.39 sass_0.4.1 ","categories":"","description":"","excerpt":"To start, we use the same workflow instance like the last section.\nsal …","ref":"/sp/spr/sp_run/step_interactive/","tags":"","title":"Build workflow interactively"},{"body":"SPS has many options you can change. These options will determine how the app behaves.\n Config SPS Let us start by creating an example SPS project. For demo purpose, we are using the /tmp folder but one should use a regular location instead of the temp in a real case.\nsuppressPackageStartupMessages(library(systemPipeShiny)) spsInit(app_path = tempdir(), project_name = \"config_demo\", overwrite = TRUE, change_wd = FALSE) ## [SPS-DANGER] 2021-12-15 00:08:50 Done, Db created at '/tmp/Rtmpgas05w/config_demo/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-12-15 00:08:50 Key md5 405b200ceb5c90dbb5c097c88d582dcb ## [SPS-INFO] 2021-12-15 00:08:50 SPS project setup done! ## save project path (sps_dir \u003c- file.path(tempdir(), \"config_demo\")) ## [1] \"/tmp/Rtmpgas05w/config_demo\" To reproduce code locally, run the following chunk instead.\nlibrary(systemPipeShiny) spsInit() sps_dir \u003c- normalizePath(\".\") PRE.fansi SPAN {padding-top: .25em; padding-bottom: .25em}; SPS structure SPS_xx/ ├── server.R | ├── global.R | Most important server, UI and global files, unless special needs, `global.R` is the only file you need to edit manually ├── ui.R | ├── deploy.R | Deploy helper file ├── config | Important app config files. Do not edit them by hand if you don't know │ ├── sps.db | SPS database │ ├── sps_options.yaml | SPS default option list │ └── tabs.csv | SPS tab registration information ├── data | App example data files │ ├── xx.csv ├── R | All SPS additional tab files, helper R function, interactive guides files │ ├── tab_xx.R ├── README.md ├── results | Not in use for this current version, but you can store some data been generated from the app │ └── README.md └── www | Internet resources ├── css | CSS files │ └── sps.css ├── img | App image resources │ └── xx.png ├── js | Javascripts │ └── xx.js ├── loading_themes | Loading screen files │ └── xx.html └── plot_list | Image files for custom visualization tab thumbnails └── plot_xx.jpg This is a reminder of what you will get when a SPS project is initiated with spsInit().\n For most users, the global.R file is the only file that one needs to make change. The second important files are the files inside config folder. For normal users, these files are controlled by SPS functions. No need to make any modification. For advanced users, deep customization is possible. sps_options.yaml stores all default and valid values for SPS, details are listed below tabs.csv all SPS tab registration information. Read Manage tabs sps.db A SQLite database to store data generated in SPS. Read SPS database for more information. R folder stores all custom tab files, your helper functions. This .R or .r files under this folder will be automatically sourced when SPS starts. This is discussed in Manage tabs. www folder is where you add the internet resources, like images you want to show in the app, css style sheets to attach. Read more here. App options View/Set all options App options in SPS are controlled by “SPS options”. These options can change app appearance, debugging level, server behaviors, etc. The valid options can be found and change on the global.R file. They are similar to Shiny options, but unlike shiny options that are single values, SPS options are passed using the Option(sps = list(...)) function in global.R as a group. To view all options and their default, valid values('*' means any value is okay) see global.R from the line starting with ## SPS options. We provided some comments below that line to generally describe what each option is and valid values for options. Use function spsOptDefaults to see the default and other valid options.\nspsOptDefaults(app_path = sps_dir) ## title: ## Default: systemPipeShiny ## Other: * ## title_logo: ## Default: img/sps_small.png ## Other: * ## mode: ## Default: local ## Other: server ## login_screen: ## Default: FALSE ## Other: TRUE ## login_theme: ## Default: random ## Other: * ## use_crayon: ## Default: TRUE ## Other: FALSE ## verbose: ## Default: FALSE ## Other: TRUE ## admin_page: ## Default: TRUE ## Other: FALSE ## admin_url: ## Default: admin ## Other: * ## warning_toast: ## Default: FALSE ## Other: TRUE ## module_wf: ## Default: TRUE ## Other: FALSE ## module_rnaseq: ## Default: TRUE ## Other: FALSE ## module_ggplot: ## Default: TRUE ## Other: FALSE ## tab_welcome: ## Default: TRUE ## Other: FALSE ## tab_vs_main: ## Default: TRUE ## Other: FALSE ## tab_canvas: ## Default: TRUE ## Other: FALSE ## tab_about: ## Default: TRUE ## Other: FALSE ## note_url: ## Default: https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/remote_resource/notifications.yaml ## Other: * ## traceback: ## Default: FALSE ## Other: TRUE ## is_demo: ## Default: FALSE ## Other: TRUE ## welcome_guide: ## Default: TRUE ## Other: FALSE ## * means any value will be accepted After the app has started once, you can use spsOptions() to see all current settings.\nspsOptions(app_path = sps_dir) ## Current project option settings: ## title: ## systemPipeShiny ## title_logo: ## img/sps_small.png ## mode: ## local ## login_screen: ## FALSE ## login_theme: ## random ## use_crayon: ## TRUE ## verbose: ## FALSE ## admin_page: ## TRUE ## admin_url: ## admin ## warning_toast: ## FALSE ## module_wf: ## TRUE ## module_rnaseq: ## TRUE ## module_ggplot: ## TRUE ## tab_welcome: ## TRUE ## tab_vs_main: ## TRUE ## tab_canvas: ## TRUE ## tab_about: ## TRUE ## note_url: ## https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/remote_resource/notifications.yaml ## traceback: ## FALSE ## is_demo: ## FALSE ## welcome_guide: ## TRUE ## ******** ## Option legends: ## known options Hidden/custom options* and values+ ## Value legends: ## same as default values different from defaults+ A copy of options in global.R:\nspsOption(.list = list( title = \"systemPipeShiny\", title_logo = \"img/sps_small.png\", mode = \"local\", warning_toast = FALSE, login_screen = FALSE, login_theme = \"random\", use_crayon = TRUE, verbose = FALSE, admin_page = TRUE, admin_url = \"admin\", note_url = 'https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/remote_resource/notifications.yaml', tab_welcome = TRUE, tab_vs_main = TRUE, tab_canvas = TRUE, tab_about = TRUE, module_wf = TRUE, module_rnaseq = TRUE, module_ggplot = TRUE, traceback = FALSE, is_demo = FALSE, welcome_guide = TRUE )) Note: Do not worry if you set some invalid values, on app start, `sps()` will check all SPS options, ignore unknown values and set invalid values back to default. You will see warning messages on console to tell you specifically what is wrong with your options.\n Option Description Default Other mode running mode “local” “server” title App title “systemPipeShiny” any string title_logo App logo to display on browser tab “img/sps_small.png” any path warning_toast show security warnings? TRUE FALSE login_screen add login screen? TRUE FALSE login_theme login screen theme “random” see details use_crayon colorful console message? TRUE FALSE verbose more details for SPS functions? FALSE TRUE admin_page enable admin page? FALSE TRUE admin_url admin_page query url “admin” any string warning_toast for internal test only TRUE FALSE module_wf load workflow module? TRUE FALSE module_rnaseq load RNAseq module? TRUE FALSE module_ggplot load quick ggplot module? TRUE FALSE tab_welcome load welcome tab? TRUE FALSE tab_vs_main load custom visualization main tab? TRUE FALSE tab_canvas load Canvas tab? TRUE FALSE tab_about load about tab? TRUE FALSE note_url SPS notification remote URL see code above any URL is_demo useful if deploy the app as a demo FALSE TRUE welcome_guide enable the welcome guide TRUE FALSE app_path hidden, automatically added N.A. N.A. Details mode: see [App security] this option will change how the upload files are selected. title \u0026 title_logo: see [Other customizations] warning_toast: see [App security], A toast pop-up message to help you check pre-deploy for security problems. login_screen \u0026 login_theme \u0026 admin_page \u0026 admin_url: see [Accounts, Login and Admin]. verbose: Give you more information on debugging. Most SPS core functions has this option. If it is on, more debugging information will be printed on console. See [Debugging] module_xx – tab_xx: see [Toggle tabs] for loading and unloading tabs. tab_xx: see [Overwrite tabs] for customizing core SPS default tabs. note_url: see [Notification system] for customizing SPS notifications. is_demo: see [Workflow module]. welcome_guide: whether to enable the welcome guide on app start, see first image on SPS guide. app_path: a hidden option. This will be added after the app starts. If not specified in sps(), use current working directory. View/Set a single option SPS values are globally set, which means you can get/change the these options at inside any R code, R functions and while the app is running (change options after app started is not recommended).\nTo view a single option value, use spsOption(opt = \"OPTION_NAME\"); to overwrite a single option, use spsOption(opt = \"OPTION_NAME\", value = \"NEW_VALUE\").\nspsOption(opt = \"mode\") ## [1] \"local\" To overwrite the “mode” option:\nspsOption(opt = \"mode\", \"local\") Check again, the value has changed to “local”:\nspsOption(opt = \"mode\") ## [1] \"local\" If any option does not exist, or the value is “empty” or 0, when getting the value spsOption will return FALSE. Common “empty” values:\n NA NULL length(value) == 0 \"\" (empty string) Read the help file of ?emptyIsFalse for more information.\nspsOption(opt = \"random_opt\") ## [1] FALSE However, these “empty” values can be meaningful in some cases, so use empty_is_false = FALSE to return the original value instead of FALSE\nspsOption(opt = \"random_opt\", empty_is_false = FALSE) ## NULL Add your own options SPS is very flexible which allows you to add your own options. To do so, you need to edit the “config/sps_options.yaml” file under your project root.\nYou can use other options as templates to add more. There are two required entries:\n default: will be used as default when you load SPS package. other: Other valid options. If your user provided a value that is other than the default or the other, SPS will show warnings and use default instead. You can write \"*\" as the other value. It means any value will be accepted. SPS will skip to check other valid values for this option. Currently, the default value can only be length of 1 but other value can be a yaml array, which use [] to define: [value1, value2, ...].\nFor example, we can add some but opening the file with a text editor, here we do it programmatically:\nnew_options \u003c- ' my_opt1: default: true other: [false] my_opt2: default: \"a\" other: [\"*\"] ' write(x = new_options, file = file.path(sps_dir, \"config\", \"sps_options.yaml\"), append = TRUE) Then we can use spsOptDefaults to check\nspsOptDefaults(app_path = sps_dir) ## title: ## Default: systemPipeShiny ## Other: * ## title_logo: ## Default: img/sps_small.png ## Other: * ## mode: ## Default: local ## Other: server ## login_screen: ## Default: FALSE ## Other: TRUE ## login_theme: ## Default: random ## Other: * ## use_crayon: ## Default: TRUE ## Other: FALSE ## verbose: ## Default: FALSE ## Other: TRUE ## admin_page: ## Default: TRUE ## Other: FALSE ## admin_url: ## Default: admin ## Other: * ## warning_toast: ## Default: FALSE ## Other: TRUE ## module_wf: ## Default: TRUE ## Other: FALSE ## module_rnaseq: ## Default: TRUE ## Other: FALSE ## module_ggplot: ## Default: TRUE ## Other: FALSE ## tab_welcome: ## Default: TRUE ## Other: FALSE ## tab_vs_main: ## Default: TRUE ## Other: FALSE ## tab_canvas: ## Default: TRUE ## Other: FALSE ## tab_about: ## Default: TRUE ## Other: FALSE ## note_url: ## Default: https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/remote_resource/notifications.yaml ## Other: * ## traceback: ## Default: FALSE ## Other: TRUE ## is_demo: ## Default: FALSE ## Other: TRUE ## welcome_guide: ## Default: TRUE ## Other: FALSE ## my_opt1: ## Default: TRUE ## Other: FALSE ## my_opt2: ## Default: a ## Other: * ## * means any value will be accepted You can see the my_opt1 and my_opt2 have been added to SPS options.\n","categories":"","description":"","excerpt":"SPS has many options you can change. These options will determine how …","ref":"/sps/adv_features/config/","tags":"","title":"Configuration"},{"body":"document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i For complete documentation, please check the CommandLineTools documentation here and here for Workflows and the user guide here. CWL command-line specifications are written in YAML format.\nIn CWL, files with the extension .cwl define the parameters of a chosen command-line step or workflow, while files with the extension .yml define the input variables of command-line steps.\nCWL CommandLineTool CommandLineTool by CWL definition is a standalone process, with no interaction if other programs, execute a program, and produce output.\nLet’s explore the *.cwl file:\ndir_path \u003c- system.file(\"extdata/cwl\", package = \"systemPipeR\") cwl \u003c- yaml::read_yaml(file.path(dir_path, \"example/example.cwl\")) The cwlVersion component shows the CWL specification version used by the document. The class component shows this document describes a CommandLineTool. Note that CWL has another class, called Workflow which represents a union of one or more command-line tools together. cwl[1:2] ## $cwlVersion ## [1] \"v1.0\" ## ## $class ## [1] \"CommandLineTool\" baseCommand component provides the name of the software that we desire to execute. cwl[3] ## $baseCommand ## [1] \"echo\" The inputs section provides the input information to run the tool. Important components of this section are: id: each input has an id describing the input name; type: describe the type of input value (string, int, long, float, double, File, Directory or Any); inputBinding: It is optional. This component indicates if the input parameter should appear on the command-line. If this component is missing when describing an input parameter, it will not appear in the command-line but can be used to build the command-line. cwl[4] ## $inputs ## $inputs$message ## $inputs$message$type ## [1] \"string\" ## ## $inputs$message$inputBinding ## $inputs$message$inputBinding$position ## [1] 1 ## ## ## ## $inputs$SampleName ## $inputs$SampleName$type ## [1] \"string\" ## ## ## $inputs$results_path ## $inputs$results_path$type ## [1] \"Directory\" The outputs section should provide a list of the expected outputs after running the command-line tools. Important components of this section are: id: each input has an id describing the output name; type: describe the type of output value (string, int, long, float, double, File, Directory, Any or stdout); outputBinding: This component defines how to set the outputs values. The glob component will define the name of the output value. cwl[5] ## $outputs ## $outputs$string ## $outputs$string$type ## [1] \"stdout\" stdout: component to specify a filename to capture standard output. Note here we are using a syntax that takes advantage of the inputs section, using results_path parameter and also the SampleName to construct the output filename. cwl[6] ## $stdout ## [1] \"$(inputs.results_path.basename)/$(inputs.SampleName).txt\" CWL Workflow Workflow class in CWL is defined by multiple process steps, where can have interdependencies between the steps, and the output for one step can be used as input in the further steps.\ncwl.wf \u003c- yaml::read_yaml(file.path(dir_path, \"example/workflow_example.cwl\")) The cwlVersion component shows the CWL specification version used by the document. The class component shows this document describes a Workflow. cwl.wf[1:2] ## $class ## [1] \"Workflow\" ## ## $cwlVersion ## [1] \"v1.0\" The inputs section describes the inputs of the workflow. cwl.wf[3] ## $inputs ## $inputs$message ## [1] \"string\" ## ## $inputs$SampleName ## [1] \"string\" ## ## $inputs$results_path ## [1] \"Directory\" The outputs section describes the outputs of the workflow. cwl.wf[4] ## $outputs ## $outputs$string ## $outputs$string$outputSource ## [1] \"echo/string\" ## ## $outputs$string$type ## [1] \"stdout\" The steps section describes the steps of the workflow. In this simple example, we demonstrate one step. cwl.wf[5] ## $steps ## $steps$echo ## $steps$echo$`in` ## $steps$echo$`in`$message ## [1] \"message\" ## ## $steps$echo$`in`$SampleName ## [1] \"SampleName\" ## ## $steps$echo$`in`$results_path ## [1] \"results_path\" ## ## ## $steps$echo$out ## [1] \"[string]\" ## ## $steps$echo$run ## [1] \"example/example.cwl\" CWL Input Parameter Next, let’s explore the .yml file, which provide the input parameter values for all the components we describe above.\nFor this simple example, we have three parameters defined:\nyaml::read_yaml(file.path(dir_path, \"example/example_single.yml\")) ## $message ## [1] \"Hello World!\" ## ## $SampleName ## [1] \"M1\" ## ## $results_path ## $results_path$class ## [1] \"Directory\" ## ## $results_path$path ## [1] \"./results\" Note that if we define an input component in the .cwl file, this value needs to be also defined here in the .yml file.\nReference ","categories":"","description":"","excerpt":"document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/cwl/cwl_syntax/","tags":"","title":"CWL syntax"},{"body":" pre code { white-space: pre !important; overflow-x: scroll !important; word-break: keep-all !important; word-wrap: initial !important; } document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Data Visualization with systemPipeR systemPipeTools package extends the widely used systemPipeR (SPR) (H Backman and Girke 2016) workflow environment with enhanced toolkit for data visualization, including utilities to automate the analysis of differentially expressed genes (DEGs). systemPipeTools provides functions for data transformation and data exploration via scatterplots, hierarchical clustering heatMaps, principal component analysis, multidimensional scaling, generalized principal components, t-Distributed Stochastic Neighbor embedding (t-SNE), and MA and volcano plots. All these utilities can be integrated with the modular design of the systemPipeR environment that allows users to easily substitute any of these features and/or custom with alternatives.\nMetadata and Reads Counting Information The first step is importing the targets file and raw reads counting table.\n The targets file defines all FASTQ files and sample comparisons of the analysis workflow. The raw reads counting table represents all the reads that map to gene (row) for each sample (columns). ## Targets file targetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") targets \u003c- read.delim(targetspath, comment = \"#\") cmp \u003c- systemPipeR::readComp(file = targetspath, format = \"matrix\", delim = \"-\") ## Count table file countMatrixPath \u003c- system.file(\"extdata\", \"countDFeByg.xls\", package = \"systemPipeR\") countMatrix \u003c- read.delim(countMatrixPath, row.names = 1) showDT(countMatrix) {\"x\":{\"filter\":\"none\",\"extensions\":[\"FixedColumns\",\"Scroller\"],\"data\":[[\"AT1G01010\",\"AT1G01020\",\"AT1G01030\",\"AT1G01040\",\"AT1G01050\",\"AT1G01060\",\"AT1G01070\",\"AT1G01073\",\"AT1G01080\",\"AT1G01090\",\"AT1G01100\",\"AT1G01110\",\"AT1G01115\",\"AT2G01008\",\"AT2G01021\",\"AT2G01023\",\"AT3G01010\",\"AT3G01015\",\"AT3G01020\",\"AT3G01030\",\"AT3G01040\",\"AT3G01050\",\"AT3G01060\",\"AT3G01070\",\"AT3G01080\",\"AT3G01085\",\"AT3G01090\",\"AT3G01100\",\"AT3G01120\",\"AT3G01130\",\"AT3G01140\",\"AT3G01150\",\"AT3G01160\",\"AT3G01170\",\"AT4G00005\",\"AT4G00020\",\"AT4G00026\",\"AT4G00030\",\"AT4G00040\",\"AT4G00050\",\"AT4G00060\",\"AT4G00070\",\"AT4G00080\",\"AT4G00090\",\"AT4G00100\",\"AT4G00110\",\"AT4G00120\",\"AT4G00124\",\"AT4G00130\",\"AT4G00140\",\"AT5G01010\",\"AT5G01015\",\"AT5G01020\",\"AT5G01030\",\"AT5G01040\",\"AT5G01050\",\"AT5G01060\",\"AT5G01070\",\"AT5G01075\",\"AT5G01080\",\"AT5G01090\",\"AT5G01100\",\"AT5G01110\",\"AT5G01120\",\"AT5G01130\",\"AT5G01140\",\"AT5G01150\",\"AT5G01160\",\"ATCG00020\",\"ATCG00040\",\"ATCG00050\",\"ATCG00070\",\"ATCG00080\",\"ATCG00120\",\"ATCG00130\",\"ATCG00140\",\"ATCG00150\",\"ATCG00160\",\"ATCG00170\",\"ATCG00180\",\"ATCG00190\",\"ATCG00210\",\"ATCG00220\",\"ATCG00270\",\"ATCG00280\",\"ATCG00300\",\"ATCG00330\",\"ATCG00340\",\"ATCG00350\",\"ATCG00360\",\"ATCG00380\",\"ATCG00420\",\"ATCG00430\",\"ATCG00440\",\"ATCG00470\",\"ATCG00480\",\"ATCG00490\",\"ATCG00500\",\"ATCG00510\",\"ATMG00010\",\"ATMG00030\",\"ATMG00040\",\"ATMG00050\",\"ATMG00060\",\"ATMG00070\",\"ATMG00080\",\"ATMG00090\",\"ATMG00110\",\"ATMG00120\",\"ATMG00130\",\"ATMG00140\",\"ATMG00150\",\"ATMG00160\",\"ATMG00170\",\"ATMG00180\",\"ATMG00200\"],[57,23,41,180,60,26,0,0,98,331,230,6,0,28,6267,0,0,0,0,0,93,31,235,0,30,0,70,38,709,54,0,37,33,33,0,4,19,69,61,12,48,0,0,21,186,22,0,0,6,8,143,16,87,31,49,4,0,0,1,0,17,162,2,0,0,0,0,28,1917,9,0,5,15,52,34,36,17,7,7,5,37,6,3,105,283,4,52,147,192,1,2,7,21,12,54,180,856,8,10,2,60,11,0,0,8,7,5,6,3,1,0,0,5,3,18,0],[244,93,98,684,127,264,0,0,379,1027,432,10,0,68,3061,14,0,0,0,0,454,121,801,8,29,0,274,132,2358,140,14,126,238,131,0,25,89,106,176,138,359,0,0,59,384,78,0,0,9,6,442,26,227,170,125,7,0,4,28,0,103,1002,26,2,0,0,0,124,1696,28,3,23,50,210,127,46,53,8,39,49,145,5,83,300,723,34,103,412,480,6,21,97,312,44,339,1191,1029,13,1,0,40,56,0,3,18,18,72,27,0,4,7,1,31,15,59,3],[201,69,73,522,102,59,2,0,179,779,516,11,0,61,7559,6,0,0,0,0,364,108,553,6,151,0,315,87,2031,149,4,186,123,161,0,6,60,255,189,20,162,0,0,89,402,75,0,0,32,30,542,11,184,91,179,5,0,0,9,0,41,754,6,0,0,0,0,119,970,10,1,14,13,113,37,60,22,3,14,22,49,1,5,165,293,5,56,222,191,6,8,18,45,12,92,369,793,4,5,0,79,38,0,4,5,20,30,7,0,0,0,0,25,5,44,1],[169,126,58,664,166,56,1,0,456,1343,458,5,0,33,2203,10,0,1,0,0,578,167,674,2,14,0,373,126,2222,131,39,170,329,212,0,66,75,121,147,117,381,0,0,88,432,147,0,0,4,11,646,17,207,219,103,3,0,0,23,0,121,1185,27,2,0,0,0,127,661,19,1,59,53,190,167,42,88,14,94,68,208,16,75,212,641,45,135,530,520,10,24,147,347,34,423,1501,871,10,1,7,35,50,0,3,47,31,120,34,14,1,5,0,72,17,62,4],[365,107,94,585,125,8,6,0,287,647,468,4,0,48,3125,0,0,0,0,0,375,104,226,5,56,0,334,100,1674,242,2,138,133,110,0,16,41,127,158,23,275,0,0,56,403,81,0,0,28,30,606,4,165,97,150,7,0,0,2,0,62,819,11,2,0,0,0,103,2258,12,0,23,34,160,74,44,26,12,22,32,95,10,25,126,403,10,50,313,366,4,10,26,36,24,102,403,977,2,15,2,43,45,0,2,19,16,25,13,0,1,2,3,26,14,24,1],[229,88,156,680,303,26,6,0,538,1831,849,17,0,53,1168,3,0,1,0,0,735,146,366,6,97,0,349,203,2310,254,0,380,126,296,0,49,43,193,282,19,406,0,0,138,966,131,0,0,16,21,1031,8,463,106,427,10,2,0,5,1,89,2267,41,4,0,0,0,238,1232,6,0,24,56,277,66,33,54,11,55,61,186,3,29,250,375,23,58,509,455,1,10,63,112,15,347,984,1161,10,2,3,35,39,0,7,21,19,41,15,1,3,2,1,46,13,58,3],[41,18,9,162,116,5,2,0,102,350,522,3,0,39,12653,0,0,0,0,0,46,43,8,0,15,0,92,28,780,84,14,45,51,51,0,5,56,73,102,63,70,0,0,42,360,42,0,0,3,7,230,15,153,22,2,0,0,0,11,0,23,24,6,0,0,0,0,60,1677,4,0,5,4,37,8,41,2,0,1,11,18,2,4,63,186,2,19,121,116,0,0,7,8,2,19,73,592,0,2,1,89,19,0,2,4,8,11,5,0,1,0,0,8,6,27,2],[38,25,13,163,180,2,4,0,211,524,634,3,0,38,12386,1,0,0,0,0,76,55,59,0,25,0,139,50,1217,116,14,95,80,54,0,11,66,124,114,45,119,3,0,66,440,40,0,0,2,13,334,58,221,27,2,0,0,0,11,0,36,99,8,0,0,0,0,76,1184,6,0,1,7,42,20,18,16,1,6,15,22,2,2,59,190,4,13,152,168,0,3,11,9,1,30,163,681,2,1,0,35,37,0,4,9,4,9,3,0,1,2,0,16,8,26,2],[152,20,8,249,139,0,5,0,79,323,926,5,0,97,9799,0,0,0,0,0,80,52,13,0,72,0,148,74,1176,160,21,67,92,73,0,11,93,157,185,151,122,0,0,78,656,48,0,0,3,20,461,2,260,57,11,0,0,0,8,0,39,188,4,0,0,0,0,83,1201,0,0,1,11,41,7,23,5,0,6,2,15,2,0,56,132,2,23,75,122,0,2,4,10,4,22,93,475,4,0,0,117,31,0,5,1,5,12,7,2,1,3,0,19,9,33,0],[46,5,6,66,37,0,2,0,42,140,183,2,0,23,10386,1,0,0,0,0,23,21,1,0,7,0,48,19,270,27,7,14,20,22,0,1,12,21,48,8,43,0,0,22,113,12,0,0,1,3,109,10,50,29,2,3,0,0,1,0,13,42,0,0,0,0,0,33,1261,4,0,2,3,42,15,26,4,0,4,5,4,6,1,65,138,9,17,106,126,2,4,6,4,0,12,54,749,6,1,0,30,4,0,0,0,2,3,1,0,0,0,0,2,0,7,0],[294,88,36,697,236,0,5,0,150,600,1333,1,0,82,9414,3,0,2,0,0,162,112,14,0,57,0,236,126,1737,341,15,126,178,132,0,23,146,209,317,158,210,0,0,191,1005,46,0,0,12,22,731,0,423,100,7,0,0,0,12,0,68,277,5,0,0,0,0,128,1192,1,0,2,9,52,9,28,8,3,1,7,22,2,3,83,172,4,25,112,112,1,0,11,14,6,29,110,446,2,4,3,101,56,0,5,10,9,20,14,0,1,1,0,36,9,44,2],[405,151,147,1060,679,4,13,0,551,1693,2401,16,0,112,3265,4,0,0,0,0,260,292,41,2,33,0,468,280,2768,376,50,299,278,112,0,36,175,337,471,169,463,2,0,334,1831,107,0,0,12,13,1229,53,903,127,12,3,0,0,32,0,168,146,33,0,0,0,0,266,398,6,0,4,11,75,26,18,18,3,17,11,67,2,3,71,176,7,28,163,186,2,7,18,23,4,52,345,493,0,4,0,43,88,0,8,25,18,39,14,4,11,4,0,54,20,53,2],[117,43,32,338,362,89,9,0,250,800,762,7,0,142,6908,6,0,0,0,0,143,53,103,0,27,0,257,128,1998,110,52,130,65,95,0,19,38,245,362,472,298,0,0,74,703,51,0,0,5,23,449,6,732,62,2,0,0,0,12,0,46,42,2,2,0,0,0,157,1406,8,0,11,6,51,13,9,5,0,5,13,28,2,2,100,126,2,2,128,194,1,3,12,30,2,63,270,445,2,0,0,64,6,0,1,9,18,6,7,0,0,5,1,21,7,25,1],[139,74,29,604,746,203,43,0,612,1662,1805,38,0,230,3676,2,0,0,0,0,131,211,178,4,34,0,390,194,1861,323,81,191,125,93,0,28,132,397,598,499,414,1,0,166,1319,117,0,0,11,29,861,65,1008,100,2,0,0,2,29,0,128,80,35,0,0,0,0,274,473,0,0,3,16,91,32,23,13,0,5,19,51,2,7,65,167,1,26,121,132,1,0,8,23,1,65,346,377,0,0,0,75,49,0,2,20,16,23,25,1,5,7,0,29,10,26,0],[132,33,12,360,194,118,8,0,78,281,761,4,0,85,11154,2,0,0,0,0,79,87,39,2,88,0,176,121,781,184,19,74,59,80,0,11,52,164,203,239,176,0,0,91,600,37,0,0,6,13,599,2,265,70,0,0,0,0,5,0,41,85,0,0,0,0,0,91,1136,0,0,6,11,34,12,38,10,0,2,9,9,2,2,48,135,3,15,88,108,1,0,2,6,3,25,82,429,2,0,0,114,23,0,5,6,4,10,2,0,4,0,0,16,6,17,0],[64,18,9,80,50,24,0,0,26,122,102,0,0,18,3301,0,0,0,0,0,34,25,6,0,13,0,32,24,219,51,13,20,26,19,0,1,13,22,37,12,48,0,0,20,106,10,0,0,1,2,121,1,95,21,2,0,0,0,3,0,14,33,0,0,0,0,0,38,1860,8,0,3,4,40,26,13,0,0,1,4,1,5,0,61,259,1,28,147,176,2,3,21,11,0,17,84,662,2,2,1,23,15,0,2,9,3,1,3,1,1,0,0,5,0,8,0],[230,43,70,203,214,62,9,0,78,391,627,0,0,100,9421,5,0,0,0,0,105,43,52,0,56,0,127,79,734,97,18,70,28,61,0,4,33,92,112,178,140,0,0,93,565,17,0,0,1,5,331,4,283,29,0,0,0,0,9,0,33,155,4,0,0,0,0,118,1336,0,0,8,4,27,5,8,8,6,2,10,7,1,4,52,112,1,10,81,106,1,0,8,19,3,37,140,440,2,2,0,66,10,0,7,7,5,13,7,0,3,6,1,16,0,28,2],[120,31,85,171,181,32,1,0,55,273,476,4,0,46,8486,2,0,0,0,0,55,24,24,0,33,0,76,45,291,98,12,42,39,29,0,4,26,57,69,59,62,0,0,51,362,17,0,0,1,5,207,3,195,28,1,0,0,0,4,0,17,67,3,0,0,0,0,86,1236,3,0,1,5,39,14,31,12,0,2,2,18,5,1,48,172,0,14,118,118,0,7,0,8,1,19,116,529,4,0,0,46,18,0,3,3,4,5,6,0,0,2,2,12,2,10,0]],\"container\":\"\\n \\n \\n \\n M1A\\n M1B\\n A1A\\n A1B\\n V1A\\n V1B\\n M6A\\n M6B\\n A6A\\n A6B\\n V6A\\n V6B\\n M12A\\n M12B\\n A12A\\n A12B\\n V12A\\n V12B\\n \\n \\n\",\"options\":{\"scrollX\":true,\"fixedColumns\":true,\"deferRender\":true,\"scrollY\":200,\"scroller\":true,\"columnDefs\":[{\"className\":\"dt-right\",\"targets\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]},{\"orderable\":false,\"targets\":0}],\"order\":[],\"autoWidth\":false,\"orderClasses\":false}},\"evals\":[],\"jsHooks\":[]} Data Transformation For gene differential expression, raw counts are required, however for data visualization or clustering, it can be useful to work with transformed count data. exploreDDS function is convenience wrapper to transform raw read counts using the DESeq2 package transformations methods. The input file has to contain all the genes, not just differentially expressed ones. Supported methods include variance stabilizing transformation (vst) (Anders and Huber (2010)), and regularized-logarithm transformation or rlog (Love, Huber, and Anders (2014)).\nexploredds \u003c- exploreDDS(countMatrix, targets, cmp = cmp[[1]], preFilter = NULL, transformationMethod = \"rlog\") exploredds ## class: DESeqTransform ## dim: 116 18 ## metadata(1): version ## assays(1): '' ## rownames(116): AT1G01010 AT1G01020 ... ATMG00180 ATMG00200 ## rowData names(51): baseMean baseVar ... dispFit rlogIntercept ## colnames(18): M1A M1B ... V12A V12B ## colData names(2): condition sizeFactor Users are strongly encouraged to consult the DESeq2 vignette for more detailed information on this topic and how to properly run DESeq2 on data sets with more complex experimental designs.\nScatterplot To decide which transformation to choose, we can visualize the transformation effect comparing two samples or a grid of all samples, as follows:\nexploreDDSplot(countMatrix, targets, cmp = cmp[[1]], preFilter = NULL, samples = c(\"M12A\", \"M12A\", \"A12A\", \"A12A\"), scattermatrix = TRUE) ## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`. ## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`. ## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`. ## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`. The scatterplots are created using the log2 transform normalized reads count, variance stabilizing transformation (VST) (Anders and Huber (2010)), and regularized-logarithm transformation or rlog (Love, Huber, and Anders (2014)).\nHierarchical Clustering Dendrogram The following computes the sample-wise correlation coefficients using the stats::cor() function from the transformed expression values. After transformation to a distance matrix, hierarchical clustering is performed with the stats::hclust function and the result is plotted as a dendrogram, as follows:\nhclustplot(exploredds, method = \"spearman\") The function provides the utility to save the plot automatically.\nHierarchical Clustering HeatMap This function performs hierarchical clustering on the transformed expression matrix generated within the DESeq2 package. It uses, by default, a Pearson correlation-based distance measure and complete linkage for cluster join. If samples selected in the clust argument, it will be applied the stats::dist() function to the transformed count matrix to get sample-to-sample distances. Also, it is possible to generate the pheatmap or plotly plot format.\n## Samples plot heatMaplot(exploredds, clust = \"samples\", plotly = TRUE) {\"x\":{\"visdat\":{\"34341250a552\":[\"function () \",\"plotlyVisDat\"]},\"cur_data\":\"34341250a552\",\"attrs\":{\"34341250a552\":{\"x\":[\"M1A\",\"M1B\",\"A1A\",\"A1B\",\"V1A\",\"V1B\",\"M6A\",\"M6B\",\"A6A\",\"A6B\",\"V6A\",\"V6B\",\"M12A\",\"M12B\",\"A12A\",\"A12B\",\"V12A\",\"V12B\"],\"y\":[\"M1A\",\"M1B\",\"A1A\",\"A1B\",\"V1A\",\"V1B\",\"M6A\",\"M6B\",\"A6A\",\"A6B\",\"V6A\",\"V6B\",\"M12A\",\"M12B\",\"A12A\",\"A12B\",\"V12A\",\"V12B\"],\"z\":[[0,7.04650716301563,5.70678310405774,8.20976445672658,5.82667776225818,7.3279781790244,8.39986657356742,8.16733063204217,9.58637200173571,7.68841587215867,10.1640441508758,10.7676019921496,10.0039632569807,11.32498784981,9.8146750121175,7.74473230078491,9.45716343166999,7.95378561107353],[7.04650716301563,0,6.66154862259465,4.25865887783483,6.67960023884926,6.26668680998727,9.91630309634838,9.25451827523275,10.9564120825428,9.93575571094716,11.099388064366,10.6754670535994,9.90683653800534,10.9561298226477,10.7399675586854,9.18116169782986,9.77109863659917,9.40323019102986],[5.70678310405774,6.66154862259465,0,7.98994675562316,4.94593038167375,5.72836463615867,8.11235158724083,7.65256178153187,8.15065142907597,8.76007256265634,8.30988507282082,8.91309701678265,8.66629724080143,9.82426010379448,8.30870129249907,8.54268071001664,8.35323474316893,7.70897398227057],[8.20976445672658,4.25865887783483,7.98994675562316,0,6.99532785790822,6.43469620310431,10.4096764476556,9.51652950962973,11.1939050957909,10.4627147426448,11.1689702900908,10.546647320753,10.5708484745604,11.5547562063225,11.6160197603858,9.88406363111819,10.7020155017471,10.4675703563444],[5.82667776225818,6.67960023884926,4.94593038167375,6.99532785790822,0,4.8575131388009,8.46288752842871,8.0319315058583,8.726172089783,8.73161790330149,8.27286514155669,8.88152783442813,9.62675093908279,10.8109068917939,9.50867890759956,8.56129430593498,9.21166728284744,8.48571139105286],[7.3279781790244,6.26668680998727,5.72836463615867,6.43469620310431,4.8575131388009,0,10.051631844146,8.92833694901717,9.88801350128227,10.1968579735558,9.80606329541741,9.47694677716336,10.2032985748696,10.9502439173503,10.7118343889731,10.2485736407499,9.95124988126944,9.6455696901528],[8.39986657356742,9.91630309634838,8.11235158724083,10.4096764476556,8.46288752842871,10.051631844146,0,4.32289188181976,5.45401419571659,6.66929785847857,5.82333805363524,6.89960979808065,6.60846441830892,7.49378480640748,6.09490379797155,6.92856692552639,6.73658240504653,6.04084631483171],[8.16733063204217,9.25451827523275,7.65256178153187,9.51652950962973,8.0319315058583,8.92833694901717,4.32289188181976,0,5.86548263173596,6.92170483627566,6.43771467140554,5.936553276735,6.66918890392232,7.10201521498403,6.87338305585792,7.70858313971616,6.93977726065822,6.12205683109543],[9.58637200173571,10.9564120825428,8.15065142907597,11.1939050957909,8.726172089783,9.88801350128227,5.45401419571659,5.86548263173596,0,8.10337075683393,4.02970654063498,6.37598537189006,6.96355226928132,7.79890861008178,5.50539366529938,8.64913887544163,6.82883422186719,6.22801929982399],[7.68841587215867,9.93575571094716,8.76007256265634,10.4627147426448,8.73161790330149,10.1968579735558,6.66929785847857,6.92170483627566,8.10337075683393,0,9.22853479532283,10.1030591897721,9.35527845594351,11.0912154866989,8.92785474831708,6.32121021712703,9.14034499886722,7.20502415178336],[10.1640441508758,11.099388064366,8.30988507282082,11.1689702900908,8.27286514155669,9.80606329541741,5.82333805363524,6.43771467140554,4.02970654063498,9.22853479532283,0,5.40796455622463,7.23562402229216,8.05893271349359,5.83000947413891,8.94623155465764,6.52802367477244,6.94139936721835],[10.7676019921496,10.6754670535994,8.91309701678265,10.546647320753,8.88152783442813,9.47694677716336,6.89960979808065,5.936553276735,6.37598537189006,10.1030591897721,5.40796455622463,0,7.14309602773391,6.1610771391521,7.4911181113735,10.0381028337193,7.56298264238769,7.68916986877059],[10.0039632569807,9.90683653800534,8.66629724080143,10.5708484745604,9.62675093908279,10.2032985748696,6.60846441830892,6.66918890392232,6.96355226928132,9.35527845594351,7.23562402229216,7.14309602773391,0,5.69259437645614,5.58694500597765,8.50447659713418,5.53119139458227,6.33933832045536],[11.32498784981,10.9561298226477,9.82426010379448,11.5547562063225,10.8109068917939,10.9502439173503,7.49378480640748,7.10201521498403,7.79890861008178,11.0912154866989,8.05893271349359,6.1610771391521,5.69259437645614,0,6.42494730487994,10.5078546330517,7.19994521380774,7.82561653509729],[9.8146750121175,10.7399675586854,8.30870129249907,11.6160197603858,9.50867890759956,10.7118343889731,6.09490379797155,6.87338305585792,5.50539366529938,8.92785474831708,5.83000947413891,7.4911181113735,5.58694500597765,6.42494730487994,0,8.18110233128943,5.25899641633563,5.72577800197228],[7.74473230078491,9.18116169782986,8.54268071001664,9.88406363111819,8.56129430593498,10.2485736407499,6.92856692552639,7.70858313971616,8.64913887544163,6.32121021712703,8.94623155465764,10.0381028337193,8.50447659713418,10.5078546330517,8.18110233128943,0,7.99272460895717,6.58008064549415],[9.45716343166999,9.77109863659917,8.35323474316893,10.7020155017471,9.21166728284744,9.95124988126944,6.73658240504653,6.93977726065822,6.82883422186719,9.14034499886722,6.52802367477244,7.56298264238769,5.53119139458227,7.19994521380774,5.25899641633563,7.99272460895717,0,5.56397338345294],[7.95378561107353,9.40323019102986,7.70897398227057,10.4675703563444,8.48571139105286,9.6455696901528,6.04084631483171,6.12205683109543,6.22801929982399,7.20502415178336,6.94139936721835,7.68916986877059,6.33933832045536,7.82561653509729,5.72577800197228,6.58008064549415,5.56397338345294,0]],\"alpha_stroke\":1,\"sizes\":[10,100],\"spans\":[1,20],\"type\":\"heatmap\"}},\"layout\":{\"margin\":{\"b\":40,\"l\":60,\"t\":25,\"r\":10},\"xaxis\":{\"domain\":[0,1],\"automargin\":true,\"title\":[]},\"yaxis\":{\"domain\":[0,1],\"automargin\":true,\"title\":[]},\"scene\":{\"zaxis\":{\"title\":[]}},\"hovermode\":\"closest\",\"showlegend\":false,\"legend\":{\"yanchor\":\"top\",\"y\":0.5}},\"source\":\"A\",\"config\":{\"showSendToCloud\":false},\"data\":[{\"colorbar\":{\"title\":\"\",\"ticklen\":2,\"len\":0.5,\"lenmode\":\"fraction\",\"y\":1,\"yanchor\":\"top\"},\"colorscale\":[[\"0\",\"rgba(68,1,84,1)\"],[\"0.0416666666666667\",\"rgba(70,19,97,1)\"],[\"0.0833333333333333\",\"rgba(72,32,111,1)\"],[\"0.125\",\"rgba(71,45,122,1)\"],[\"0.166666666666667\",\"rgba(68,58,128,1)\"],[\"0.208333333333333\",\"rgba(64,70,135,1)\"],[\"0.25\",\"rgba(60,82,138,1)\"],[\"0.291666666666667\",\"rgba(56,93,140,1)\"],[\"0.333333333333333\",\"rgba(49,104,142,1)\"],[\"0.375\",\"rgba(46,114,142,1)\"],[\"0.416666666666667\",\"rgba(42,123,142,1)\"],[\"0.458333333333333\",\"rgba(38,133,141,1)\"],[\"0.5\",\"rgba(37,144,140,1)\"],[\"0.541666666666667\",\"rgba(33,154,138,1)\"],[\"0.583333333333333\",\"rgba(39,164,133,1)\"],[\"0.625\",\"rgba(47,174,127,1)\"],[\"0.666666666666667\",\"rgba(53,183,121,1)\"],[\"0.708333333333333\",\"rgba(79,191,110,1)\"],[\"0.75\",\"rgba(98,199,98,1)\"],[\"0.791666666666667\",\"rgba(119,207,85,1)\"],[\"0.833333333333333\",\"rgba(147,214,70,1)\"],[\"0.875\",\"rgba(172,220,52,1)\"],[\"0.916666666666667\",\"rgba(199,225,42,1)\"],[\"0.958333333333333\",\"rgba(226,228,40,1)\"],[\"1\",\"rgba(253,231,37,1)\"]],\"showscale\":true,\"x\":[\"M1A\",\"M1B\",\"A1A\",\"A1B\",\"V1A\",\"V1B\",\"M6A\",\"M6B\",\"A6A\",\"A6B\",\"V6A\",\"V6B\",\"M12A\",\"M12B\",\"A12A\",\"A12B\",\"V12A\",\"V12B\"],\"y\":[\"M1A\",\"M1B\",\"A1A\",\"A1B\",\"V1A\",\"V1B\",\"M6A\",\"M6B\",\"A6A\",\"A6B\",\"V6A\",\"V6B\",\"M12A\",\"M12B\",\"A12A\",\"A12B\",\"V12A\",\"V12B\"],\"z\":[[0,7.04650716301563,5.70678310405774,8.20976445672658,5.82667776225818,7.3279781790244,8.39986657356742,8.16733063204217,9.58637200173571,7.68841587215867,10.1640441508758,10.7676019921496,10.0039632569807,11.32498784981,9.8146750121175,7.74473230078491,9.45716343166999,7.95378561107353],[7.04650716301563,0,6.66154862259465,4.25865887783483,6.67960023884926,6.26668680998727,9.91630309634838,9.25451827523275,10.9564120825428,9.93575571094716,11.099388064366,10.6754670535994,9.90683653800534,10.9561298226477,10.7399675586854,9.18116169782986,9.77109863659917,9.40323019102986],[5.70678310405774,6.66154862259465,0,7.98994675562316,4.94593038167375,5.72836463615867,8.11235158724083,7.65256178153187,8.15065142907597,8.76007256265634,8.30988507282082,8.91309701678265,8.66629724080143,9.82426010379448,8.30870129249907,8.54268071001664,8.35323474316893,7.70897398227057],[8.20976445672658,4.25865887783483,7.98994675562316,0,6.99532785790822,6.43469620310431,10.4096764476556,9.51652950962973,11.1939050957909,10.4627147426448,11.1689702900908,10.546647320753,10.5708484745604,11.5547562063225,11.6160197603858,9.88406363111819,10.7020155017471,10.4675703563444],[5.82667776225818,6.67960023884926,4.94593038167375,6.99532785790822,0,4.8575131388009,8.46288752842871,8.0319315058583,8.726172089783,8.73161790330149,8.27286514155669,8.88152783442813,9.62675093908279,10.8109068917939,9.50867890759956,8.56129430593498,9.21166728284744,8.48571139105286],[7.3279781790244,6.26668680998727,5.72836463615867,6.43469620310431,4.8575131388009,0,10.051631844146,8.92833694901717,9.88801350128227,10.1968579735558,9.80606329541741,9.47694677716336,10.2032985748696,10.9502439173503,10.7118343889731,10.2485736407499,9.95124988126944,9.6455696901528],[8.39986657356742,9.91630309634838,8.11235158724083,10.4096764476556,8.46288752842871,10.051631844146,0,4.32289188181976,5.45401419571659,6.66929785847857,5.82333805363524,6.89960979808065,6.60846441830892,7.49378480640748,6.09490379797155,6.92856692552639,6.73658240504653,6.04084631483171],[8.16733063204217,9.25451827523275,7.65256178153187,9.51652950962973,8.0319315058583,8.92833694901717,4.32289188181976,0,5.86548263173596,6.92170483627566,6.43771467140554,5.936553276735,6.66918890392232,7.10201521498403,6.87338305585792,7.70858313971616,6.93977726065822,6.12205683109543],[9.58637200173571,10.9564120825428,8.15065142907597,11.1939050957909,8.726172089783,9.88801350128227,5.45401419571659,5.86548263173596,0,8.10337075683393,4.02970654063498,6.37598537189006,6.96355226928132,7.79890861008178,5.50539366529938,8.64913887544163,6.82883422186719,6.22801929982399],[7.68841587215867,9.93575571094716,8.76007256265634,10.4627147426448,8.73161790330149,10.1968579735558,6.66929785847857,6.92170483627566,8.10337075683393,0,9.22853479532283,10.1030591897721,9.35527845594351,11.0912154866989,8.92785474831708,6.32121021712703,9.14034499886722,7.20502415178336],[10.1640441508758,11.099388064366,8.30988507282082,11.1689702900908,8.27286514155669,9.80606329541741,5.82333805363524,6.43771467140554,4.02970654063498,9.22853479532283,0,5.40796455622463,7.23562402229216,8.05893271349359,5.83000947413891,8.94623155465764,6.52802367477244,6.94139936721835],[10.7676019921496,10.6754670535994,8.91309701678265,10.546647320753,8.88152783442813,9.47694677716336,6.89960979808065,5.936553276735,6.37598537189006,10.1030591897721,5.40796455622463,0,7.14309602773391,6.1610771391521,7.4911181113735,10.0381028337193,7.56298264238769,7.68916986877059],[10.0039632569807,9.90683653800534,8.66629724080143,10.5708484745604,9.62675093908279,10.2032985748696,6.60846441830892,6.66918890392232,6.96355226928132,9.35527845594351,7.23562402229216,7.14309602773391,0,5.69259437645614,5.58694500597765,8.50447659713418,5.53119139458227,6.33933832045536],[11.32498784981,10.9561298226477,9.82426010379448,11.5547562063225,10.8109068917939,10.9502439173503,7.49378480640748,7.10201521498403,7.79890861008178,11.0912154866989,8.05893271349359,6.1610771391521,5.69259437645614,0,6.42494730487994,10.5078546330517,7.19994521380774,7.82561653509729],[9.8146750121175,10.7399675586854,8.30870129249907,11.6160197603858,9.50867890759956,10.7118343889731,6.09490379797155,6.87338305585792,5.50539366529938,8.92785474831708,5.83000947413891,7.4911181113735,5.58694500597765,6.42494730487994,0,8.18110233128943,5.25899641633563,5.72577800197228],[7.74473230078491,9.18116169782986,8.54268071001664,9.88406363111819,8.56129430593498,10.2485736407499,6.92856692552639,7.70858313971616,8.64913887544163,6.32121021712703,8.94623155465764,10.0381028337193,8.50447659713418,10.5078546330517,8.18110233128943,0,7.99272460895717,6.58008064549415],[9.45716343166999,9.77109863659917,8.35323474316893,10.7020155017471,9.21166728284744,9.95124988126944,6.73658240504653,6.93977726065822,6.82883422186719,9.14034499886722,6.52802367477244,7.56298264238769,5.53119139458227,7.19994521380774,5.25899641633563,7.99272460895717,0,5.56397338345294],[7.95378561107353,9.40323019102986,7.70897398227057,10.4675703563444,8.48571139105286,9.6455696901528,6.04084631483171,6.12205683109543,6.22801929982399,7.20502415178336,6.94139936721835,7.68916986877059,6.33933832045536,7.82561653509729,5.72577800197228,6.58008064549415,5.56397338345294,0]],\"type\":\"heatmap\",\"xaxis\":\"x\",\"yaxis\":\"y\",\"frame\":null}],\"highlight\":{\"on\":\"plotly_click\",\"persistent\":false,\"dynamic\":false,\"selectize\":false,\"opacityDim\":0.2,\"selected\":{\"opacity\":1},\"debounce\":0},\"shinyEvents\":[\"plotly_hover\",\"plotly_click\",\"plotly_selected\",\"plotly_relayout\",\"plotly_brushed\",\"plotly_brushing\",\"plotly_clickannotation\",\"plotly_doubleclick\",\"plotly_deselect\",\"plotly_afterplot\",\"plotly_sunburstclick\"],\"base_url\":\"https://plot.ly\"},\"evals\":[],\"jsHooks\":[]} If ind selected in the clust argument, it is necessary to provide the list of differentially expressed genes for the exploredds subset.\n## Individuals genes identified in DEG analysis DEG analysis with `systemPipeR` degseqDF \u003c- systemPipeR::run_DESeq2(countDF = countMatrix, targets = targets, cmp = cmp[[1]], independent = FALSE) DEG_list \u003c- systemPipeR::filterDEGs(degDF = degseqDF, filter = c(Fold = 2, FDR = 10)) ### Plot heatMaplot(exploredds, clust = \"ind\", DEGlist = unique(as.character(unlist(DEG_list[[1]])))) The function provides the utility to save the plot automatically.\nPrincipal Component Analysis This function plots a Principal Component Analysis (PCA) from transformed expression matrix. This plot shows samples variation based on the expression values and identifies batch effects.\nPCAplot(exploredds, plotly = FALSE) The function provides the utility to save the plot automatically.\nMultidimensional scaling with MDSplot This function computes and plots multidimensional scaling analysis for dimension reduction of count expression matrix. Internally, it is applied the stats::dist() function to the transformed count matrix to get sample-to-sample distances.\nMDSplot(exploredds, plotly = FALSE) The function provides the utility to save the plot automatically.\nDimension Reduction with GLMplot This function computes and plots generalized principal components analysis for dimension reduction of count expression matrix.\nexploredds_r \u003c- exploreDDS(countMatrix, targets, cmp = cmp[[1]], preFilter = NULL, transformationMethod = \"raw\") GLMplot(exploredds_r, plotly = FALSE) The function provides the utility to save the plot automatically.\nMA plot This function plots log2 fold changes (y-axis) versus the mean of normalized counts (on the x-axis). Statistically significant features are colored.\nMAplot(degseqDF, comparison = \"M12-A12\", filter = c(Fold = 1, FDR = 20), genes = \"ATCG00280\") The function provides the utility to save the plot automatically.\nt-Distributed Stochastic Neighbor embedding with tSNEplot This function computes and plots t-Distributed Stochastic Neighbor embedding (t-SNE) analysis for unsupervised nonlinear dimensionality reduction of count expression matrix. Internally, it is applied the Rtsne::Rtsne() (Krijthe 2015) function, using the exact t-SNE computing with theta=0.0.\ntSNEplot(countMatrix, targets, perplexity = 5) Volcano plot A simple function that shows statistical significance (p-value) versus magnitude of change (log2 fold change).\nvolcanoplot(degseqDF, comparison = \"M12-A12\", filter = c(Fold = 1, FDR = 20), genes = \"ATCG00280\") Version information sessionInfo() ## R Under development (unstable) (2021-02-04 r79940) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.2 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /home/dcassol/src/R-devel/lib/libRlapack.so ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 parallel stats graphics grDevices utils datasets ## [8] methods base ## ## other attached packages: ## [1] systemPipeR_1.25.11 ShortRead_1.49.2 ## [3] GenomicAlignments_1.27.2 SummarizedExperiment_1.21.3 ## [5] Biobase_2.51.0 MatrixGenerics_1.3.1 ## [7] matrixStats_0.58.0 BiocParallel_1.25.5 ## [9] Rsamtools_2.7.2 Biostrings_2.59.2 ## [11] XVector_0.31.1 GenomicRanges_1.43.4 ## [13] GenomeInfoDb_1.27.11 IRanges_2.25.9 ## [15] S4Vectors_0.29.15 BiocGenerics_0.37.2 ## [17] systemPipeTools_0.9.1 BiocStyle_2.19.2 ## ## loaded via a namespace (and not attached): ## [1] backports_1.2.1 BiocFileCache_1.99.6 plyr_1.8.6 ## [4] lazyeval_0.2.2 splines_4.1.0 crosstalk_1.1.1 ## [7] ggplot2_3.3.3 digest_0.6.27 htmltools_0.5.1.1 ## [10] fansi_0.4.2 magrittr_2.0.1 checkmate_2.0.0 ## [13] memoise_2.0.0 BSgenome_1.59.2 base64url_1.4 ## [16] limma_3.47.12 annotate_1.69.2 prettyunits_1.1.1 ## [19] jpeg_0.1-8.1 colorspace_2.0-0 blob_1.2.1 ## [22] rappdirs_0.3.3 ggrepel_0.9.1 xfun_0.22 ## [25] dplyr_1.0.5 crayon_1.4.1 RCurl_1.98-1.3 ## [28] jsonlite_1.7.2 genefilter_1.73.1 VariantAnnotation_1.37.1 ## [31] brew_1.0-6 survival_3.2-10 ape_5.4-1 ## [34] glue_1.4.2 gtable_0.3.0 zlibbioc_1.37.0 ## [37] DelayedArray_0.17.10 V8_3.4.0 scales_1.1.1 ## [40] pheatmap_1.0.12 DBI_1.1.1 GGally_2.1.1 ## [43] edgeR_3.33.3 Rcpp_1.0.6 viridisLite_0.4.0 ## [46] xtable_1.8-4 progress_1.2.2 tidytree_0.3.3 ## [49] bit_4.0.4 rsvg_2.1.1 DT_0.18 ## [52] htmlwidgets_1.5.3 httr_1.4.2 RColorBrewer_1.1-2 ## [55] ellipsis_0.3.1 farver_2.1.0 pkgconfig_2.0.3 ## [58] reshape_0.8.8 XML_3.99-0.6 dbplyr_2.1.1 ## [61] sass_0.3.1 locfit_1.5-9.4 utf8_1.2.1 ## [64] labeling_0.4.2 later_1.1.0.1 tidyselect_1.1.0 ## [67] rlang_0.4.10 AnnotationDbi_1.53.1 munsell_0.5.0 ## [70] tools_4.1.0 cachem_1.0.4 generics_0.1.0 ## [73] RSQLite_2.2.7 evaluate_0.14 stringr_1.4.0 ## [76] fastmap_1.1.0 yaml_2.2.1 ggtree_2.5.2 ## [79] knitr_1.32 bit64_4.0.5 purrr_0.3.4 ## [82] KEGGREST_1.31.1 nlme_3.1-152 mime_0.10 ## [85] formatR_1.9 aplot_0.0.6 biomaRt_2.47.7 ## [88] compiler_4.1.0 filelock_1.0.2 plotly_4.9.3 ## [91] curl_4.3 png_0.1-7 treeio_1.15.7 ## [94] tibble_3.1.1 geneplotter_1.69.0 bslib_0.2.4 ## [97] stringi_1.5.3 highr_0.9 blogdown_1.3 ## [100] GenomicFeatures_1.43.8 lattice_0.20-41 Matrix_1.3-2 ## [103] glmpca_0.2.0 vctrs_0.3.7 pillar_1.6.0 ## [106] lifecycle_1.0.0 BiocManager_1.30.12 jquerylib_0.1.3 ## [109] data.table_1.14.0 bitops_1.0-6 httpuv_1.5.5 ## [112] rtracklayer_1.51.5 patchwork_1.1.1 BiocIO_1.1.2 ## [115] R6_2.5.0 latticeExtra_0.6-29 hwriter_1.3.2 ## [118] promises_1.2.0.1 bookdown_0.22 codetools_0.2-18 ## [121] MASS_7.3-53.1 assertthat_0.2.1 rjson_0.2.20 ## [124] DESeq2_1.31.18 withr_2.4.2 batchtools_0.9.15 ## [127] GenomeInfoDbData_1.2.4 hms_1.0.0 grid_4.1.0 ## [130] tidyr_1.1.3 DOT_0.1 rmarkdown_2.7.12 ## [133] rvcheck_0.1.8 Rtsne_0.15 shiny_1.6.0 ## [136] restfulr_0.0.13 Funding This project is funded by NSF award ABI-1661152.\nReferences Anders, Simon, and Wolfgang Huber. 2010. “Differential Expression Analysis for Sequence Count Data.” Genome Biol. 11 (10): R106.\n H Backman, Tyler W, and Thomas Girke. 2016. “systemPipeR: NGS workflow and report generation environment.” BMC Bioinformatics 17 (1): 388. https://doi.org/10.1186/s12859-016-1241-0.\n Krijthe, Jesse H. 2015. Rtsne: T-Distributed Stochastic Neighbor Embedding Using Barnes-Hut Implementation. https://github.com/jkrijthe/Rtsne.\n Love, Michael, Wolfgang Huber, and Simon Anders. 2014. “Moderated Estimation of Fold Change and Dispersion for RNA-seq Data with DESeq2.” Genome Biol. 15 (12): 550. https://doi.org/10.1186/s13059-014-0550-8.\n ","categories":"","description":"","excerpt":" pre code { white-space: pre !important; overflow-x: …","ref":"/sp/spt/systempipetools/","tags":"","title":"Data Visualizations"},{"body":"","categories":"","description":"","excerpt":"","ref":"/spr_wf/templates/","tags":"","title":"Existing templates"},{"body":"document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Note: if you use {systemPipeR} in published research, please cite: Backman, T.W.H and Girke, T. (2016). systemPipeR: NGS Workflow and Report Generation Environment. BMC Bioinformatics, 17: 388. \u003e10.1186/s12859-016-1241-0.\n systemPipeR(SPR) provides flexible utilities for designing, building and running automated end-to-end analysis workflows for a wide range of research applications, including next-generation sequencing (NGS) experiments, such as RNA-Seq, ChIP-Seq, VAR-Seq and Ribo-Seq (H Backman and Girke 2016). Important features include a uniform workflow interface across different data analysis applications, automated report generation, and support for running both R and command-line software, such as NGS aligners or peak/variant callers, on local computers or compute clusters (Figure 1). The latter supports interactive job submissions and batch submissions to queuing systems of clusters.\nsystemPipeR has been designed to improve the reproducibility of large-scale data analysis projects while substantially reducing the time it takes to analyze complex omics data sets. It provides a uniform workflow interface and management system that allows the users to run selected workflow steps, as well as customize and design entirely new workflows. Additionally, the package take advantage of central community S4 classes of the Bioconductor ecosystem, and enhances them with command-line software support.\nThe main motivation and advantages of using systemPipeR for complex data analysis tasks are:\n Design of complex workflows involving multiple R/Bioconductor packages Common workflow interface for different applications User-friendly access to widely used Bioconductor utilities Support of command-line software from within R Reduced complexity of using compute clusters from R Accelerated runtime of workflows via parallelization on computer systems with multiple CPU cores and/or multiple nodes Improved reproducibility by automating the generation of analysis reports Figure 1: Relevant features in `systemPipeR`. Workflow design concepts are illustrated under (A). Examples of `systemPipeR's` visualization functionalities are given under (B). A central concept for designing workflows within the systemPipeR environment is the use of workflow management containers. Workflow management containers facilitate the design and execution of complex data analysis steps. For its command-line interface systemPipeR adopts the widely used Common Workflow Language (CWL) (Amstutz et al. 2016). The interface to CWL is established by systemPipeR's workflow control class called SYSargsList (see Figure 2). This design offers many advantages such as: (i) options to run workflows either entirely from within R, from various command-line wrappers (e.g., cwl-runner) or from other languages (, e.g., Bash or Python). Apart from providing support for both command-line and R/Bioconductor software, the package provides utilities for containerization, parallel evaluations on computer clusters and automated generation of interactive analysis reports.\nFigure 2: Overview of `systemPipeR` workflows management instances. A) A typical analysis workflow requires multiple software tools (red), as well the description of the input (green) and output files, including analysis reports (purple). B) `systemPipeR` provides multiple utilities to design and build a workflow, allowing multi-instance, integration of R code and command-line software, a simple and efficient annotation system, that allows automatic control of the input and output data, and multiple resources to manage the entire workflow. c) Options are provided to execute single or multiple workflow steps, while enabling scalability, checkpoints, and generation of technical and scientific reports. An important feature of systemPipeR's CWL interface is that it provides two options to run command-line tools and workflows based on CWL. First, one can run CWL in its native way via an R-based wrapper utility for cwl-runner or cwl-tools (CWL-based approach). Second, one can run workflows using CWL’s command-line and workflow instructions from within R (R-based approach). In the latter case the same CWL workflow definition files (e.g. *.cwl and *.yml) are used but rendered and executed entirely with R functions defined by systemPipeR, and thus use CWL mainly as a command-line and workflow definition format rather than execution software to run workflows. In this regard systemPipeR also provides several convenience functions that are useful for designing and debugging workflows, such as a command-line rendering function to retrieve the exact command-line strings for each data set and processing step prior to running a command-line.\nWorkflow Management with SYSargsList The SYSargsList S4 class is a list-like container that stores the paths to all input and output files along with the corresponding parameters used in each analysis step (see Figure ??). SYSargsList instances are constructed from an optional targets files, and two CWL parameter files including *.cwl and *.yml (for details, see below). When running preconfigured NGS workflows, the only input the user needs to provide is the initial targets file containing the paths to the input files (e.g., FASTQ) and experiment design information, such as sample labels and biological replicates. Subsequent targets instances are created automatically, based on the connectivity establish between each workflow step. SYSargsList containers store all information required for one or multiple steps. This establishes central control for running, monitoring and debugging complex workflows from start to finish.\nWorkflow steps with input/output file operations are controlled by the SYSargsList container. Each of its components (SYSargs2) are constructed from an optional targets and two param files. Alternatively, LineWise instances containing pure R code can be used.\nCommand-line software support systemPipeR adopted the widely used community standard Common Workflow Language (CWL) (Amstutz et al. 2016) for describing command-line tools and workflows in a declarative, generic, and reproducible manner. CWL specifications are text-based files and can be structured using YAML (https://yaml.org/) syntax. Therefore, the description files can be easily accessed and are readable. The significant advantage of adopting CWL as a standard description of command-line tools within is the flexibility of workflow reusability for different computing environments and workflow frameworks in the community, improving reproducibility, portability, and shareability between collaborators and community.\nFollowing the CWL Command Line Tool Description Specification (https://www.commonwl.org/v1.2/CommandLineTool.html), the basic elements of the CWL tool description are defined in two files. Figure 3A-B illustrate the “hello world” example. The main file contains all the information necessary to build the command-line that will be executed, specifying the input, expected output files, and arguments for the command-line (Figure 3A). The second file is optional yet provides flexibility to assign values to parameters required to make the input or output objects when building the command-line.\nFigure 3: Example of ‘Hello World’ message using CWL syntax and demonstrating the connectivity with `systemPipeR`. (A) This file describes the command-line tool, here using ‘echo’ command. (B) This file describes all the parameters variables connected with the tool specification file. Here the reference value of the input parameter can be specific or can be filled dynamically, adding a variable that connects with the targets files from `systemPipeR`. (C) `SYSargsList` function provides the ‘inputvars’ arguments to build the connectivity between the CWL description of parameters and the targets files. The argument requires a named vector where each vector element is required to be defined in the CWL description of parameters file (B), and the names of the elements are needed to match the column names defined in the targets file (D). Reference Amstutz, Peter, Michael R Crusoe, Nebojša Tijanić, Brad Chapman, John Chilton, Michael Heuer, Andrey Kartashov, et al. 2016. “Common Workflow Language, V1.0,” July. https://doi.org/10.6084/m9.figshare.3115156.v2.\n H Backman, Tyler W, and Thomas Girke. 2016. “systemPipeR: NGS workflow and report generation environment.” BMC Bioinformatics 17 (1): 388. https://doi.org/10.1186/s12859-016-1241-0.\n ","categories":"","description":"","excerpt":"document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/introduction/","tags":"","title":"Introduction"},{"body":" Main functionalities Currently, SPS includes 3 main functional categories (Fig 1):\n Some pre-defined modules (tabs) include: A workbench for designing and configuring data analysis workflows, Downstream analysis and visualization tools for RNA-Seq, and A space to make quick ggplots. A section with user custom tabs: users define their own shiny tabs. An image editing tab “Canvas” which allows users to edit plots made from the previous two categories. Besides, SPS provides many functions to extend the default Shiny development, like more UI components, server functions. Also, SPS has some useful general R ulitlies like error catching, logging, and more.\n Figure 1. SPS Features\nThe framework provides an interactive web interface for workflow management and data visualization.\nDetailed features To know more about SPS features, find your favorite section below and click the link below to navigate to the section, or use the left sidebar menu to navigate.\nSPS Features\nApp structure\n User login\n Loading themes\n Workflow module\n Workflow metadata\n Workflow step selection \u0026 desgin\n Workflow Execution\n RNAseq normalization\n RNAseq DEG\n RNAseq plots\n Canvas Module\n Admin login\n Admin app stats\n Admin user control\n Customizable notifications\n Customizable interactive tutorials\n Logging and error handling\n X fixGalHeight(\"gallery4791515\") ","categories":"","description":"","excerpt":" Main functionalities Currently, SPS includes 3 main functional …","ref":"/sps/intro/","tags":"","title":"Introduction"},{"body":"","categories":"","description":"","excerpt":"","ref":"/spr_wf/templates/rnaseq/","tags":"","title":"RNA-Seq"},{"body":"SPS Components package systemPipeShiny Components (spsComps) package is a collection of custom UI and server components that are used in SPS main framework. If you see a component in SPS but want to outside the SPS framework, like in your own Shiny apps, take a look at these components.\nDemos Demo type source code shiny{blk} shinyapps.io Github{blk} Rmd Rmarkdown rendered Raw{blk} table {font-size: 1.5rem} Installation Read the developer tools main page, not repeating here.\nCategory {spsComps} can be divided into two major categories: UI and server.\n UI: Shiny or HTML UI components, for example, a box, a gallery, a button, etc. With these most of components, you do NOT need a server, so they are compatible with R markdown documents. See the UI page and its source code how we use the components in a Rmd doucment. However, some UI components has server side functions, mostly like updateXXX functions. Mainly these functions are used to update/change the UI based on user behaviors. It is totally okay to use the UI functions without the server functions (you will get static UI). server: can only be run in the Shiny server. These functions are designed to make back-end progress easier, extensions of original shiny Server functions. Functions reference manual In documents, we only highlight some important functions. Please read the reference manuals for details of every function.\nsome screenshots of spsComps Animations Loaders Buttons Code display button Go top button Input buttons Button groups Table of buttons Gallery Logos Progress tracking Porgress panel Timeline Tooltips Popovers Colorful titles Colorful divider lines ","categories":"","description":"","excerpt":"SPS Components package systemPipeShiny Components (spsComps) package …","ref":"/sps/dev/spscomps/","tags":"","title":"spsComps"},{"body":"This is the the table of content for systemPipeR package.\nSections ","categories":"","description":"","excerpt":"This is the the table of content for systemPipeR package.\nSections ","ref":"/sp/spr/","tags":"","title":"systemPipeR"},{"body":" For most of the UI components, you can view them in the online Shiny demo{blk}. Most but not all UI components work in a Rmarkdown document. Here we demostrate how you could use some of them in a Rmarkdown doc. The source code of this document is on Github{blk}.\nload package To start to use spsComps, load it in your Shiny app file or Rmarkdown file\nlibrary(spsComps) ## Loading required package: shiny library(magrittr) So you can see it depends on shiny. When you load it, there is no need to additionally load shiny.\nspsGoTop A go top button.\nspsGoTop() It will not be display inline of the Rmd, just simply call it and maybe change the style as you want. By default, a “go to top” button will be created on the bottom-right corner. Now scroll this page, and you should see it (the rocket button).\ngallery texts \u003c- c(\"p1\", \"p2\", \"\", \"p4\", \"p5\") hrefs \u003c- c(\"https://github.com/lz100/spsComps/blob/master/img/1.jpg?raw=true\", \"https://github.com/lz100/spsComps/blob/master/img/2.jpg?raw=true\", \"\", \"https://github.com/lz100/spsComps/blob/master/img/4.jpg?raw=true\", \"https://github.com/lz100/spsComps/blob/master/img/5.jpg?raw=true\") images \u003c- c(\"https://github.com/lz100/spsComps/blob/master/img/1.jpg?raw=true\", \"https://github.com/lz100/spsComps/blob/master/img/2.jpg?raw=true\", \"https://github.com/lz100/spsComps/blob/master/img/3.jpg?raw=true\", \"https://github.com/lz100/spsComps/blob/master/img/4.jpg?raw=true\", \"https://github.com/lz100/spsComps/blob/master/img/5.jpg?raw=true\") gallery( texts = texts, hrefs = hrefs, images = images, enlarge = TRUE, # only \"modal\" methods workds in Rmd, but other methods work in Shiny enlarge_method = \"modal\" ) Gallery\np1\n p2\n \n p4\n p5\n X fixGalHeight(\"gallery6509249\") You can show a gallery of plots you make in the Rmd and when people click it, it will be enlarged. You can also specify a link for each image.\nLogos a single one with hexLogo hexLogo( \"logo\", \"Logo\", hex_img = \"https://live.staticflickr.com/7875/46106952034_954b8775fa_b.jpg\", hex_link = \"https://www.google.com\", footer = \"Footer\", footer_link = \"https://www.google.com\" ) Logo\n Footer a panel of logos with hexPanel hexPanel( \"demo1\", \"\" , rep(\"https://live.staticflickr.com/7875/46106952034_954b8775fa_b.jpg\", 2) ) Buttons Some colorful buttons hrefTab hrefTab( title = \"Different background and text colors\", label_texts = c(\"Go top\", \"Disabled\", \"Email me\"), hrefs = c(\"#\", \"\", \"mailto:xxx@abc.com\"), bg_colors = c(\"green\", \"#eee\", \"orange\"), text_colors = c(\"#caffc1\", \"black\", \"blue\") ) Different background and text colors\nGo top Disabled Email me A table colorful buttons hrefTable hrefTable( title = \"Change button color and text color\", item_titles = c(\"workflow 1\", \"No links\"), item_labels = list(c(\"tab 1\"), c(\"tab 3\", \"tab 4\")), item_hrefs = list(c(\"https://www.google.com/\"), c(\"\", \"\")), item_bg_colors = list(c(\"blue\"), c(\"red\", \"orange\")), item_text_colors = list(c(\"black\"), c(\"yellow\", \"green\")), style = \"display: table;\" ) Change button color and text color Category Options workflow 1 tab 1 No links tab 3 tab 4 hrefTable( title = \"Change row name colors and width\", item_titles = c(\"Green\", \"Red\", \"Orange\"), item_labels = list(c(\"tab 1\"), c(\"tab 3\", \"tab 4\"), c(\"tab 5\", \"tab 6\", \"tab 7\")), item_hrefs = list( c(\"https://www.google.com/\"), c(\"\", \"\"), c(\"https://www.google.com/\", \"https://www.google.com/\", \"\") ), item_title_colors = c(\"green\", \"red\", \"orange\"), style = \"display: table;\" ) Change row name colors and width Category Options Green tab 1 Red tab 3 tab 4 Orange tab 5 tab 6 tab 7 The table caption is on top in Shiny but on bottom in Rmd. You may also want to add the style = \"display: table;\" in Rmd to make the table occupy full length of the document in R markdown.\nAnimations animateUI Add animations to existing components with animateUI\nTo buttons tags$button(id = \"btn1\", \"random button\") random button\nanimateUI(\"btn1\", animation = \"ring\") addSpsAnimation(\"#btn1\", \"sps-animation faa-ring animated \") To some text p(id = \"mytext\", class = \"text-red\", \"some move text\") some move text\nanimateUI(\"mytext\", animation = \"horizontal\", speed = \"fast\") addSpsAnimation(\"#mytext\", \"sps-animation faa-horizontal animated faa-fast\") On hover, move mouse on the red thumb tags$button( id = \"btn2\", icon(id = \"myicon\", \"thumbs-o-up\"), style = \"color: red; boarder: initial; border-color: transparent;\" ) ## The `name` provided ('thumbs-o-up') is deprecated in Font Awesome 5: ## * please consider using 'thumbs-up' or 'fas fa-thumbs-up' instead ## * use the `verify_fa = FALSE` to deactivate these messages animateUI(\"btn2\", animation = \"bounce\", speed = \"fast\", hover = TRUE) addSpsAnimation(\"#btn2\", \"sps-animation faa-bounce animated-hover faa-fast\") Inline animation You can add animations to inline Rmarkdown text by giving it a HTML tag and id, like following:\nsome text some text \u003cspan id=\"some-text\" style=\"display: inline-block\"\u003esome text\u003c/span\u003e some text some text some text some text some text some text some text\nanimateUI(selector = \"some-text\", animation = \"ring\") addSpsAnimation(\"#some-text\", \"sps-animation faa-ring animated \") Most animations required the target tag to have CSS display “block” or “inline-block”, you can append this by adding style=\"display: inline-block\" to the tag as shown above or check examples below.\n animateAppend Add animations with pipe %\u003e% by animateAppend\nicon(\"home\") %\u003e% animateAppend(\"ring\") \ntags$p(\"Append animation\", class = \"text-primary\", style=\"display: inline-block\") %\u003e% animateAppend(\"pulse\") Append animation\n animateAppendNested Apply multiple animations to the same component\ntags$b(\"Nested animations\", class = \"text-primary\") %\u003e% animateAppendNested(\"ring\") %\u003e% animateAppendNested(\"pulse\") %\u003e% animateAppendNested(\"passing\") Nested animations tags$b(\"Nested animations display changed\", class = \"text-primary\") %\u003e% animateAppendNested(\"ring\") %\u003e% animateAppendNested(\"pulse\", display = \"block\", style = \"width: 30%\") Nested animations display changed animateIcon Here is a convenient function that allows you to create font-awesome icons with animations and customize, color, size, etc, an enhanced version of original shiny::icon and can also be used in Rmarkdown.\nDefault Default is the same as original icon\nanimateIcon(\"home\") \nAnimation and color animateIcon(name = \"home\", animation = \"horizontal\", speed = \"slow\", color =\"red\") \nAdd to a button tags$button(animateIcon(\"spinner\", \"spin\", \"fast\"), \"A button\") A button on hover animateIcon(name = \"wrench\", animation = \"wrench\", hover = TRUE, color =\"green\") \nChange size animateIcon(\"home\", size = \"xs\") \nanimateIcon(\"home\", size = \"sm\") \nanimateIcon(\"home\", size = \"lg\") \nanimateIcon(\"home\", size = \"2x\") \nanimateIcon(\"home\", size = \"3x\") \nanimateIcon(\"home\", size = \"5x\") \nanimateIcon(\"home\", size = \"7x\") \nanimateIcon(\"home\", size = \"10x\") \n Loaders Add loaders to indicate busy status. Most cases, loaders are added by a backend server to show the busy processing status and are removed when the process is done. Rmarkdown documents does not have a server, but you can still add some loaders.\ncssLoader Default loaders There are 12 different default loaders: “circle,” “dual-ring,” “facebook,” “heart,” “ring,” “roller,” “default,” “ellipsis,” “grid,” “hourglass,” “ripple,” “spinner.”\ncssLoader(height = \"100px\") $(function(){ $(\"#spsloader-927518346\").prepend(chooseLoader(\"spsloader-927518346\", \"default\", \"\", \"#337ab7\", \"100px\", \"100px\")); }); customize it:\ncssLoader(type = \"grid\", height = \"150px\", color = \"orange\") $(function(){ $(\"#spsloader-597318642\").prepend(chooseLoader(\"spsloader-597318642\", \"grid\", \"\", \"orange\", \"150px\", \"150px\")); }); Add to a button:\ntags$button( ## `inline = TRUE` is important if you want loader and ## text in the same line. cssLoader(is_icon = TRUE, inline = TRUE, color = \"#3a7bd5\"), \"A button\" ) $(function(){ $(\"#spsloader-478251369\").prepend(chooseLoader(\"spsloader-478251369\", \"default\", \"\", \"#3a7bd5\", \"1.5rem\", \"1.5rem\")); }); A button Your own loaders You can choose a gif to be a your loader\ncssLoader(type = \"gif\", src = \"https://github.com/lz100/spsComps/blob/master/examples/demo/www/spinner.gif?raw=true\", height = \"100px\") $(function(){ $(\"#spsloader-251734698\").prepend(chooseLoader(\"spsloader-251734698\", \"gif\", \"https://github.com/lz100/spsComps/blob/master/examples/demo/www/spinner.gif?raw=true\", \"#337ab7\", \"100px\", \"100px\")); }); cssLoader(type = \"gif\", src = \"https://github.com/lz100/spsComps/blob/master/examples/demo/www/bean_eater.gif?raw=true\", height = \"150px\") $(function(){ $(\"#spsloader-529478631\").prepend(chooseLoader(\"spsloader-529478631\", \"gif\", \"https://github.com/lz100/spsComps/blob/master/examples/demo/www/bean_eater.gif?raw=true\", \"#337ab7\", \"150px\", \"150px\")); }); bsTooltip and bsTip Add tooltips to the documents with bsTooltip\nactionButton(\"\", \"Tooltip on the left\") %\u003e% bsTooltip(\"Tooltip on the left\", \"left\") Tooltip on the left bsTooltip( \"bsTooltip89222956\", \"left\", \"Tooltip on the left\", \"black\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"Tooltip on the top\") %\u003e% bsTooltip(\"Tooltip on the top\", \"top\") Tooltip on the top bsTooltip( \"bsTooltip61577506\", \"top\", \"Tooltip on the top\", \"black\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"Tooltip on the right\") %\u003e% bsTooltip(\"Tooltip on the right\", \"right\") Tooltip on the right bsTooltip( \"bsTooltip83163117\", \"right\", \"Tooltip on the right\", \"black\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"Tooltip on the bottom\") %\u003e% bsTooltip(\"Tooltip on the bottom\", \"bottom\") Tooltip on the bottom bsTooltip( \"bsTooltip54616265\", \"bottom\", \"Tooltip on the bottom\", \"black\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) or use the higher leveler convenient function bsTip\nactionButton(\"\", \"primary\") %\u003e% bsTip(\"primary\", status = \"primary\") primary bsTooltip( \"bsTooltip69609518\", \"top\", \"primary\", \"#0275d8\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"info\") %\u003e% bsTip(\"info\", status = \"info\") info bsTooltip( \"bsTooltip96741769\", \"top\", \"info\", \"#5bc0de\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"success\") %\u003e% bsTip(\"success\", status = \"success\") success bsTooltip( \"bsTooltip73842437\", \"top\", \"success\", \"#5cb85c\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"warning\") %\u003e% bsTip(\"warning\", status = \"warning\") warning bsTooltip( \"bsTooltip99963005\", \"top\", \"warning\", \"#f0ad4e\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) actionButton(\"\", \"danger\") %\u003e% bsTip(\"danger\", status = \"danger\") danger bsTooltip( \"bsTooltip88798086\", \"top\", \"danger\", \"#d9534f\", \"white\", \"12px\", \"hover focus\", \"400\", \"1\", false ) bsPopover and bsPop There is no extra step if you use popovers in Shiny directly. In Rmarkdown, you need to add following as plain text close to the end of your Rmd:\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/jquery-popover@0.0.4/src/jquery-popover.min.js\"\u003e\u003c/script\u003e \u003cscript\u003e $(function(){ $('span[data-popoverid] script').map(function(){ let el = document.createElement(\"script\"); el.innerHTML = $(this).html(); document.body.appendChild(el); }); }); \u003c/script\u003e $(function(){ $('span[data-popoverid] script').map(function(){ let el = document.createElement(\"script\"); el.innerHTML = $(this).html(); document.body.appendChild(el); }); }); Add Popovers to the documents with bsPopover\nspan(\"Popover on the left\") %\u003e% bsPopover(\"Popover on the left\", \"Popover on the left\", \"left\") Popover on the left bsPopover( \"bspopover03902739\", \"left\", `Popover on the left`, \"Popover on the left\", \"#ebebeb\", \"black\", \"black\", \"14px\", \"12px\", \"hover focus\", \"600\", \"400\", \"1\", false ) span(\"Popover on the top\") %\u003e% bsPopover(\"Popover on the top\", \"Popover on the top\", \"top\") Popover on the top bsPopover( \"bspopover20455852\", \"top\", `Popover on the top`, \"Popover on the top\", \"#ebebeb\", \"black\", \"black\", \"14px\", \"12px\", \"hover focus\", \"600\", \"400\", \"1\", false ) span(\"Popover on the right\") %\u003e% bsPopover(\"Popover on the right\", \"Popover on the right\", \"right\") Popover on the right bsPopover( \"bspopover95424854\", \"right\", `Popover on the right`, \"Popover on the right\", \"#ebebeb\", \"black\", \"black\", \"14px\", \"12px\", \"hover focus\", \"600\", \"400\", \"1\", false ) span(\"Popover on the bottom\") %\u003e% bsPopover(\"Popover on the bottom\", \"Popover on the bottom\", \"bottom\") Popover on the bottom bsPopover( \"bspopover40865521\", \"bottom\", `Popover on the bottom`, \"Popover on the bottom\", \"#ebebeb\", \"black\", \"black\", \"14px\", \"12px\", \"hover focus\", \"600\", \"400\", \"1\", false ) or use the higher leveler convenient function bsPop\nspan(\"Popover\") %\u003e% bsPop(\"Popover\", \"Popover\") Popover bsPopover( \"bspopover40358561\", \"top\", `Popover`, \"Popover\", \"#0275d8\", \"white\", \"#0275d8\", \"14px\", \"12px\", \"hover focus\", \"600\", \"400\", \"1\", true ) Titles with spsTitle You can use {spsComps} to add colorful titles in Rmarkdown\nspsTitle(\"primary\", status = \"primary\") primary spsTitle(\"info\", status = \"info\") info spsTitle(\"success\", status = \"success\") success spsTitle(\"warning\", status = \"warning\") warning spsTitle(\"danger\", status = \"danger\") danger Or you own colors\nspsTitle(\"purple\", other_color = \"purple\") purple spsTitle(\"pink\", other_color = \"pink\") pink Add horizontal divider lines with spsHr spsHr(\"info\") spsHr(\"primary\") spsHr(\"success\") spsHr(\"warning\") spsHr(\"danger\") Other components Other components are either performed the best in a Shiny app or requires a server. Please see the demo\n","categories":"","description":"","excerpt":" For most of the UI components, you …","ref":"/sps/dev/spscomps/ui/","tags":"","title":"UI components"},{"body":"Workflow management The workflow management module in SPS allows one to modify or create the configuration files required for running data analysis workflows in systemPipeR (SPR). This includes three types of important files: a sample metadata (targets) file, a workflow file (in R Markdown format) defining the workflow steps, and workflow running files in Common Workflow Language (CWL){blk} format. In SPS, one can easily create these files under the “Workflow Management” module, located in navigation bar on the left of the dashboard.\nThe current version of SPS allows to:\n create a workflow environment; create and/or check the format of targets / workflow / CWL files; download the prepared workflow files to run elsewhere, like a cluster; directly execute the workflow from SPS. 1. setup a workflow Figure 3. A. Workflow Management - Targets File\n In the workflow module, read the instructions and choose step 1. Step 1 should be automatically opened for you on start. Choose a folder where you want to create the workflow environment. Choose a workflow template. These are SPR workflows and mainly are next-generation sequencing workflows. Click “Gen workflow” to create the workflow project. You should see a pop-up saying about the project path and other information. Clicking the pop-up will jump you to the step 2. The status tracker and banner for step 1 should all turn green. 2. Prepare the targets file The targets file defines all input file paths and other sample information of analysis workflows. To better undertand the structure of this file, one can consult the “Structure of targets file” section in the SPR vignette. Essentially, this is the tabular file representation of the colData slot in an SummarizedExperiment object which stores sample IDs and other meta information.\nThe following step-by-step instructions explain how to create and/or modify targets files using RNA-Seq as an example (Fig.3 A):\n Your project targets file is loaded for you, but you can choose to upload a different one. You can edit, right click to add/remove rows/columns (The first row is treated as column names). SPR target file includes a header block, that can also be edited in the SPS app. Each headers needs to start with a “#”. Header is useful for workflows with DEG analysis in current SPR. You can define sample comparison groups here. Leave it as default for other projects. The section on the left provides sample statistics and information whether files exist inside the workflow project’s data directory. Choose any column you want from the dropdown to check and watch the statistics bar change in this section. statistic status bar. Clicking on “Add to task” can help you to check if your target file has any formatting problem. You should see a green success pop-up if everything is right. Now your target file is ready and you can click “save” to download it and later use in other SPR projects. Figure 3. A. Workflow Management - Targets File\n3. Prepare a workflow object In SPR, workflows are defined in Rmarkdown files, you can read details and obtain them here.\nNow let us follow the order below to see how SPS helps you to prepare a workflow file for a RNAseq project (Fig.3 B):\n The left panal is the workflow designer. All steps from the template from your choosen workflow will be displayed here. The arrows indicates the execution order of the entire workflow. All the steps are draggable. Drag and place steps to a different place to change the order. Note: if you change the order, it may break the dependency. SPS will check this for you. After changing orders, steps marked in pink mean these steps are broken. You need to fix the dependency before you can save it. To config a step, such as, changing name, fixing dependency. Click the button next to each step, a modal will show up and you can make changes there. To add a step, click the button. There, you will have more options to choose which will be explained in the next figure. History is enabled in this designer, you can undo or redo anytime you want. Current SPS stores max 100 steps of history for you. To delete a step, simply drag it to the trash can. After you are done with all edits, click here to save the workflow so we can run or download it in the next major step. On the right side is the workflow dependency plot. This plot shows how each step is connected and the expected execution order. It does not mean the the workflow will be run in the same order. The order is determined by the order you have in the left-side designer. Enlarge the left or right panel. If you have a small monitor screen, this can help. Figure 3. B.1 Workflow Management - Workflow Designer\n R step and sysArgs step On the designer there are two types of workflow steps. One is R step, which only has R code. Then it is the time to run these R steps, they will be run in the same R session as the Shiny app and in a separate environment different than your global environment. In other words, all R steps are in the same environment, they can communicate with each other, meaning you can define a variable in one step and use it in other R steps.\nsysArgs steps, on the other hand, is different, as its name suggest, it will invoke system commands (like bash) when run. Details of how to create these steps will be discussed on Fig 3.B.5, Fig 3.B.6.\nView and modify steps Current SPS allows users to view some basic information of R steps like, step name, select dependency(ies). Besides, users are welcome to change the R code they want in the second sub-tab (Fig 3.B.2).\n Figure 3. B.2 Workflow Management - config R\n Modification of sysArgs steps is limited to step name and dependency. However, this kind steps will provide more information to view, like the files that were used to create this step, raw commandline code that will be run, targets (metadata) and output dataframes. This information is distributed in different subtabs (Fig 3.B.3).\n Figure 3. B.3 Workflow Management - config sysArgs\n Create a new step After clicking the button in Fig 3.B.1, you would need to choose whether to create an R or sysArgs step (Figure 3. B.5).\n Figure 3. B.5 Workflow Management - Choose new step type\n Create a new R step\nCreate a new R step is simple. In the modal, type the step name, R code, and select dependency (Fig 3. B.6).\n Figure 3. B.6 Workflow Management - New R step\n Create a new sysArgs step\nBasic info for sysArgs step is simialr to R step (Fig 3. B.7).\n Figure 3. B.7 Workflow Management - New sysArgs step\n To generate some commandline line, there are three items need to be prepared: targets, CWL file, CWL yaml file (Fig.3. B.8).\n targets: metadata that will populate the basecommand sample-wisely. Columns in targets will be injected into CWL yaml and then, yaml file will replace variables in parsed CWL base command. CWL file: provide the base command. CWL yaml file: provides CWL variables. Choose the targets source. Targets in SPR workflow steps can come from either a fresh file or inherit from a previous sysArg step(s) (output from a previous step can become input of the next(s)). If you choose from a previous step(s), select the steps from here. If a new file, upload here. Then, the targets or inherited targets table is displayed here for you to take a look. Later we will use these column to replace CWL yaml variables. Choose the CWL and CWL yaml file you want to use. All .cwl and .yaml or .yml files inside your workflow project param/cwl folder will be listed here. You could drop more of these files you want to this folder. They will become aviable the next time you create a new step. If you have all the three items, you can start to use which column from the targets to replace each CWL yaml variables. Try to parse the command, see if the results is as what you expect. If not, try to change options above and try again. If everything looks fine, save and create the step. Figure 3. B.8 Workflow Management - New sysArgs step\n 4. Prepare CWL files (optional) In the new version of SPR, all individual system workflow steps are called by the CWL files. Each SPR workflow has a set of CWL files and normally users do not need to make any change. In case you want to learn more about CWL and create some new CWL files, Step 4 is a good place to practice.\nTo run a CWL step in SPR, 3 files are required:\n targets: to determine how many samples will be run and sample names. CWL running file: can be translated to bash code; CWL input: variables to inject into the running file SPR is the parser between R and CWL by injecting sample information from targets to CWL input file and then CWL parser translates it to bash code.\n Most people are not familiar this part, so read instructions carefully. Your project targets has been loaded for you, and an example CWL running and input for hisat2 is also loaded for you. Directly parse the code. See what commandline code you get. Change the targets injecting column, and parse again, see what has changed. You can edit the CWL running and input files Try to parse the new file and see what has changed. If new CWL files has been created, you can edit workflow Rmd files by adding your new steps. Figure 3. C. Workflow Management - CWL File\n5. Run or finish workflow preparation Up until this step, congratulations, the workflow is prepared. You can choose to download the workflow project files as a bundle or continue to run the workflow.\n Figure 4.A.B Workflow Runner\n On step 5 you can choose to download the prepared workflow or directly run the workflow. However, if you do not have the required commandline tools, workflow will most likely fail. Make sure you system has these tools (Read about these tools). Open up the runner. It is a “Rstudio-like” interface. Code editor. Required workflow running code is pre-entered for you. You can simply hit “Run” to start. Of course, you can delete the default code and run random R code. Output R console. Workflow running log and real-time updated progress workflow plot. View any plot output. and send a copy of your current plot to SPS Canvas tab or download it. App security Running the workflow may introduce some security concerns. Read App Security for more details.\nis_demo option The is_demo option will impact the workflow module.\n TRUE: you are not deploying the app for production purpose. It is just a show case. Under this option, users who are trying to create a workflow will be locked inside a temp directory and every time they start a new session, they will be assigned to a new temp directory. This is useful if many people want to try the app the same time, so they will have different private environments, and the temp directory will be removed after the Shiny session is closed. FALSE: you are using the app on your own local computer or use it in a production environment. WF module will have full access to the sever storage system and users can choose any place they have permissions to create the workflow session. ","categories":"","description":"","excerpt":"Workflow management The workflow management module in SPS allows one …","ref":"/sps/modules/workflow/","tags":"","title":"Workflow"},{"body":"pre code { white-space: pre !important; overflow-x: scroll !important; word-break: keep-all !important; word-wrap: initial !important; } document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Note: the most recent version of this vignette can be found here.\n Note: if you use systemPipeR or systemPipeRdata in published research, please cite: Backman, T.W.H and Girke, T. (2016). systemPipeR: Workflow and Report Generation Environment. BMC Bioinformatics, 17: 388. 10.1186/s12859-016-1241-0.\n systemPipeRdata package provides a demo sample FASTQ files used in the workflow reporting vignettes. The chosen data set SRP010938 obtains 18 paired-end (PE) read sets from Arabidposis thaliana (Howard et al. 2013). To minimize processing time during testing, each FASTQ file has been subsetted to 90,000-100,000 randomly sampled PE reads that map to the first 100,000 nucleotides of each chromosome of the A. thalina genome. The corresponding reference genome sequence (FASTA) and its GFF annotation files (provided in the same download) have been truncated accordingly. This way the entire test sample data set requires less than 200MB disk storage space. A PE read set has been chosen for this test data set for flexibility, because it can be used for testing both types of analysis routines requiring either SE (single-end) reads or PE reads.\nGetting started Installation The systemPipeRdata package is available at Bioconductor and can be installed from within R as follows:\nif (!requireNamespace(\"BiocManager\", quietly = TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeRdata\") Also, it is possible to install the development version from Bioconductor.\nBiocManager::install(\"systemPipeRdata\", version = \"devel\", build_vignettes = TRUE, dependencies = TRUE) # Installs Devel version from Bioconductor Loading package and documentation library(\"systemPipeRdata\") # Loads the package library(help = \"systemPipeRdata\") # Lists package info vignette(\"systemPipeRdata\") # Opens vignette Starting with pre-configured workflow templates Load one of the available workflows into your current working directory. The following does this for the rnaseq workflow template. The name of the resulting workflow directory can be specified under the mydirname argument. The default NULL uses the name of the chosen workflow. An error is issued if a directory of the same name and path exists already.\n Full details of pre-configed workflows are listed on this page\n genWorkenvir(workflow = \"systemPipeR/SPrnaseq\", mydirname = \"rnaseq\") setwd(\"rnaseq\") On Linux and OS X systems the same can be achieved from the command-line of a terminal with the following commands.\n$ Rscript -e \"systemPipeRdata::genWorkenvir(workflow='systemPipeR/SPrnaseq', mydirname='rnaseq')\" Build, run and visualize the workflow template Build workflow from RMarkdown file This template provides some common steps for a RNAseq workflow. One can add, remove, modify workflow steps by operating on the sal object.\nsal \u003c- SPRproject() sal \u003c- importWF(sal, file_path = \"systemPipeVARseq.Rmd\", verbose = FALSE) Running workflow Next, we can run the entire workflow from R with one command:\nsal \u003c- runWF(sal) Visualize workflow systemPipeR workflows instances can be visualized with the plotWF function.\nplotWF(sal) Report generation systemPipeR compiles all the workflow execution logs in one central location, making it easier to check any standard output (stdout) or standard error (stderr) for any command-line tools used on the workflow or the R code stdout.\nsal \u003c- renderLogs(sal) Also, the technical report can be generated using renderReport function.\nsal \u003c- renderReport(sal) Workflow templates collection A collection of workflow templates are available, and it is possible to browse the current availability, as follows:\navailableWF(github = TRUE) This function returns the list of workflow templates available within the package and systemPipeR Organization on GitHub. Each one listed template can be created as described above.\nThe workflow template choose from Github will be installed as an R package, and also it creates the environment with all the settings and files to run the demo analysis.\ngenWorkenvir(workflow=\"systemPipeR/SPrnaseq\", mydirname=\"NULL\") setwd(\"SPrnaseq\") Besides, it is possible to choose different versions of the workflow template, defined through other branches on the GitHub Repository. By default, the master branch is selected, however, it is possible to define a different branch with the ref argument.\ngenWorkenvir(workflow=\"systemPipeR/SPrnaseq\", ref = \"singleMachine\") setwd(\"SPrnaseq\") Download a specific R Markdown file Also, it is possible to download a specific workflow script for your analysis. The URL can be specified under url argument and the R Markdown file name in the urlname argument. The default NULL copies the current version available in the chose template.\ngenWorkenvir(workflow=\"systemPipeR/SPrnaseq\", url = \"https://raw.githubusercontent.com/systemPipeR/systemPipeRNAseq/cluster/vignettes/systemPipeRNAseq.Rmd\", urlname = \"rnaseq_V-cluster.Rmd\") setwd(\"rnaseq\") Dynamic generation of workflow template It is possible to create a new workflow structure from RStudio menu File -\u003e New File -\u003e R Markdown -\u003e From Template -\u003e systemPipeR New WorkFlow. This interactive option creates the same environment as demonstrated above.\nFigure 1: Selecting workflow template within RStudio.\nDirectory Structure The workflow templates generated by genWorkenvir contain the following preconfigured directory structure:\n workflow/ (e.g. rnaseq/) This is the root directory of the R session running the workflow. Run script ( *.Rmd) and sample annotation (targets.txt) files are located here. Note, this directory can have any name (e.g. rnaseq, varseq). Changing its name does not require any modifications in the run script(s). Important subdirectories: param/ Stores non-CWL parameter files such as: *.param, *.tmpl and *.run.sh. These files are only required for backwards compatibility to run old workflows using the previous custom command-line interface. param/cwl/: This subdirectory stores all the CWL parameter files. To organize workflows, each can have its own subdirectory, where all CWL param and input.yml files need to be in the same subdirectory. data/ FASTQ files FASTA file of reference (e.g. reference genome) Annotation files etc. results/ Analysis results are usually written to this directory, including: alignment, variant and peak files (BAM, VCF, BED); tabular result files; and image/plot files Note, the user has the option to organize results files for a given sample and analysis step in a separate subdirectory. Note: Directory names are indicated in green. Users can change this structure as needed, but need to adjust the code in their workflows accordingly.\n Figure 2: systemPipeR’s preconfigured directory structure.\nReturn paths to sample data The location of the sample data provided by systemPipeRdata can be returned as a list.\npathList()[1:2] ## $targets ## [1] \"C:/Users/lz/AppData/Local/R/win-library/4.2/systemPipeRdata/extdata/param/targets.txt\" ## ## $targetsPE ## [1] \"C:/Users/lz/AppData/Local/R/win-library/4.2/systemPipeRdata/extdata/param/targetsPE.txt\" Version information sessionInfo() ## R version 4.2.0 (2022-04-22 ucrt) ## Platform: x86_64-w64-mingw32/x64 (64-bit) ## Running under: Windows 10 x64 (build 19044) ## ## Matrix products: default ## ## locale: ## [1] LC_COLLATE=English_United States.utf8 ## [2] LC_CTYPE=English_United States.utf8 ## [3] LC_MONETARY=English_United States.utf8 ## [4] LC_NUMERIC=C ## [5] LC_TIME=English_United States.utf8 ## ## attached base packages: ## [1] stats graphics grDevices utils datasets ## [6] methods base ## ## other attached packages: ## [1] systemPipeRdata_2.1.1 BiocStyle_2.24.0 ## ## loaded via a namespace (and not attached): ## [1] bslib_0.3.1 compiler_4.2.0 ## [3] BiocManager_1.30.18 formatR_1.12 ## [5] jquerylib_0.1.4 GenomeInfoDb_1.32.1 ## [7] XVector_0.36.0 bitops_1.0-7 ## [9] remotes_2.4.2 tools_4.2.0 ## [11] zlibbioc_1.42.0 digest_0.6.29 ## [13] jsonlite_1.8.0 evaluate_0.15 ## [15] rlang_1.0.2 cli_3.3.0 ## [17] rstudioapi_0.13 yaml_2.3.5 ## [19] blogdown_1.10.1 xfun_0.31 ## [21] fastmap_1.1.0 GenomeInfoDbData_1.2.8 ## [23] stringr_1.4.0 knitr_1.39 ## [25] Biostrings_2.64.0 sass_0.4.1 ## [27] S4Vectors_0.34.0 IRanges_2.30.0 ## [29] stats4_4.2.0 R6_2.5.1 ## [31] rmarkdown_2.14 bookdown_0.26 ## [33] magrittr_2.0.3 codetools_0.2-18 ## [35] htmltools_0.5.2 BiocGenerics_0.42.0 ## [37] stringi_1.7.6 RCurl_1.98-1.6 ## [39] crayon_1.5.1 Funding This project was supported by funds from the National Institutes of Health (NIH) and the National Science Foundation (NSF).\nReferences Howard, Brian E, Qiwen Hu, Ahmet Can Babaoglu, Manan Chandra, Monica Borghi, Xiaoping Tan, Luyan He, et al. 2013. “High-Throughput RNA Sequencing of Pseudomonas-Infected Arabidopsis Reveals Hidden Transcriptome Complexity and Novel Splice Variants.” PLoS One 8 (10): e74183. https://doi.org/10.1371/journal.pone.0074183.\n ","categories":"","description":"","excerpt":"pre code { white-space: pre !important; overflow-x: scroll !important; …","ref":"/sp/sprdata/systempiperdata/","tags":"","title":"Workflow templates and sample data"},{"body":"Demo Demo demo Source code shinyapps.io github Instructions Instructions on how to use {drawer} and the capture buttons are provided in the demo Shiny app in details. Click on the show code button on each tab in the demo app for code to reproduce.\n","categories":"","description":"","excerpt":"Demo Demo demo Source code shinyapps.io github Instructions …","ref":"/sps/dev/drawer/shiny/","tags":"","title":"drawer in Shiny"},{"body":" document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Getting Started Installation systemPipeR environment can be installed from the R console using the BiocManager::install command. The associated data package systemPipeRdata can be installed the same way. The latter is a helper package for generating systemPipeR workflow environments with a single command containing all parameter files and sample data required to quickly test and run workflows.\nif (!requireNamespace(\"BiocManager\", quietly = TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeR\") BiocManager::install(\"systemPipeRdata\") Please note that if you desire to use a third-party command-line tool, the particular tool and dependencies need to be installed and exported in your PATH. See details.\nLoading package and documentation library(\"systemPipeR\") # Loads the package library(help = \"systemPipeR\") # Lists package info vignette(\"systemPipeR\") # Opens vignette How to get help for systemPipeR All questions about the package or any particular function should be posted to the Bioconductor support site https://support.bioconductor.org.\nPlease add the “systemPipeR” tag to your question, and the package authors will automatically receive an alert.\nWe appreciate receiving reports of bugs in the functions or documentation and suggestions for improvement. For that, please consider opening an issue at GitHub.\nProject structure systemPipeR expects a project directory structure that consists of a directory where users may store all the raw data, the results directory that will be reserved for all the outfiles files or new output folders, and the parameters directory.\nThis structure allows reproducibility and collaboration across the data science team since internally relative paths are used. Users could transfer this project to a different location and still be able to run the entire workflow. Also, it increases efficiency and data management once the raw data is kept in a separate folder and avoids duplication.\nLoad sample data and workflow templates The mini sample FASTQ files used by this overview vignette as well as the associated workflow reporting vignettes can be loaded via the systemPipeRdata package as shown below. The chosen data set SRP010938 obtains 18 paired-end (PE) read sets from Arabidposis thaliana (Howard et al. 2013). To minimize processing time during testing, each FASTQ file has been subsetted to 90,000-100,000 randomly sampled PE reads that map to the first 100,000 nucleotides of each chromosome of the A. thalina genome. The corresponding reference genome sequence (FASTA) and its GFF annotation files (provided in the same download) have been truncated accordingly. This way the entire test sample data set requires less than 200MB disk storage space. A PE read set has been chosen for this test data set for flexibility, because it can be used for testing both types of analysis routines requiring either SE (single-end) reads or PE reads.\nThe following generates a fully populated systemPipeR workflow environment (here for RNA-Seq) in the current working directory of an R session. At this time the package includes workflow templates for RNA-Seq, ChIP-Seq, VAR-Seq, and Ribo-Seq. Templates for additional NGS applications will be provided in the future.\nDirectory Structure systemPipeRdata, helper package, provides pre-configured workflows, reporting templates, and sample data loaded as demonstrated below. With a single command, the package allows creating the workflow environment containing the structure described here (see Figure 1).\ngenWorkenvir(workflow = \"rnaseq\") setwd(\"rnaseq\") Directory names are indicated in green. Users can change this structure as needed, but need to adjust the code in their workflows accordingly.\n workflow/ (e.g. myproject/) This is the root directory of the R session running the workflow. Run script ( *.Rmd) and sample annotation (targets.txt) files are located here. Note, this directory can have any name (e.g. myproject). Changing its name does not require any modifications in the run script(s). Important subdirectories: param/ param/cwl/: This subdirectory stores all the parameter and configuration files. To organize workflows, each can have its own subdirectory, where all *.cwl and *input.yml files need to be in the same subdirectory. data/ Raw data (e.g. FASTQ files) FASTA file of reference (e.g. reference genome) Annotation files Metadata etc. results/ Analysis results are usually written to this directory, including: alignment, variant and peak files (BAM, VCF, BED); tabular result files; and image/plot files. Note, the user has the option to organize results files for a given sample and analysis step in a separate subdirectory. Figure 1: *systemPipeR’s* preconfigured directory structure. The following parameter files are included in each workflow template:\n targets.txt: initial one provided by user; downstream targets_*.txt files are generated automatically *.param/cwl: defines parameter for input/output file operations, e.g.: hisat2/hisat2-mapping-se.cwl hisat2/hisat2-mapping-se.yml Configuration files for computer cluster environments (skip on single machines): .batchtools.conf.R: defines the type of scheduler for batchtools pointing to template file of cluster, and located in user’s home directory batchtools.*.tmpl: specifies parameters of scheduler used by a system, e.g. Torque, SGE, Slurm, etc. Structure of initial targets file The targets file defines all input files (e.g. FASTQ, BAM, BCF) and sample comparisons of an analysis workflow. It can, also, store any number of descriptive information for each sample used in the workflow.\nThe following shows the format of a sample targets file included in the package. It also can be viewed and downloaded from systemPipeR’s GitHub repository here. Please note that here it is represented a tabular file, however systemPipeR can import the inputs information from a YAML files, as well as SummarizedExperiment object. For more details on how to create custom targets, please find here.\nUsers should note here, the usage of targets files is optional when using systemPipeR's new workflow management interface. They can be replaced by a standard YAML input file used by CWL. Since for organizing experimental variables targets files are extremely useful and user-friendly. Thus, we encourage users to keep using them.\nStructure of targets file for single-end (SE) samples In a target file with a single type of input files, here FASTQ files of single-end (SE) reads, the first column describe the path and the second column represents a unique id name for each sample. The third column called Factor represents the biological replicates. All subsequent columns are additional information, and any number of extra columns can be added as needed.\ntargetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") showDF(read.delim(targetspath, comment.char = \"#\")) ## Loading required namespace: DT {\"x\":{\"filter\":\"none\",\"vertical\":false,\"extensions\":[\"FixedColumns\",\"Scroller\"],\"data\":[[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\"],[\"./data/SRR446027_1.fastq.gz\",\"./data/SRR446028_1.fastq.gz\",\"./data/SRR446029_1.fastq.gz\",\"./data/SRR446030_1.fastq.gz\",\"./data/SRR446031_1.fastq.gz\",\"./data/SRR446032_1.fastq.gz\",\"./data/SRR446033_1.fastq.gz\",\"./data/SRR446034_1.fastq.gz\",\"./data/SRR446035_1.fastq.gz\",\"./data/SRR446036_1.fastq.gz\",\"./data/SRR446037_1.fastq.gz\",\"./data/SRR446038_1.fastq.gz\",\"./data/SRR446039_1.fastq.gz\",\"./data/SRR446040_1.fastq.gz\",\"./data/SRR446041_1.fastq.gz\",\"./data/SRR446042_1.fastq.gz\",\"./data/SRR446043_1.fastq.gz\",\"./data/SRR446044_1.fastq.gz\"],[\"M1A\",\"M1B\",\"A1A\",\"A1B\",\"V1A\",\"V1B\",\"M6A\",\"M6B\",\"A6A\",\"A6B\",\"V6A\",\"V6B\",\"M12A\",\"M12B\",\"A12A\",\"A12B\",\"V12A\",\"V12B\"],[\"M1\",\"M1\",\"A1\",\"A1\",\"V1\",\"V1\",\"M6\",\"M6\",\"A6\",\"A6\",\"V6\",\"V6\",\"M12\",\"M12\",\"A12\",\"A12\",\"V12\",\"V12\"],[\"Mock.1h.A\",\"Mock.1h.B\",\"Avr.1h.A\",\"Avr.1h.B\",\"Vir.1h.A\",\"Vir.1h.B\",\"Mock.6h.A\",\"Mock.6h.B\",\"Avr.6h.A\",\"Avr.6h.B\",\"Vir.6h.A\",\"Vir.6h.B\",\"Mock.12h.A\",\"Mock.12h.B\",\"Avr.12h.A\",\"Avr.12h.B\",\"Vir.12h.A\",\"Vir.12h.B\"],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\"]],\"container\":\"\\n \\n \\n \\n FileName\\n SampleName\\n Factor\\n SampleLong\\n Experiment\\n Date\\n \\n \\n\",\"options\":{\"scrollX\":true,\"fixedColumns\":true,\"deferRender\":true,\"scrollY\":200,\"scroller\":true,\"columnDefs\":[{\"className\":\"dt-right\",\"targets\":5},{\"orderable\":false,\"targets\":0}],\"order\":[],\"autoWidth\":false,\"orderClasses\":false}},\"evals\":[],\"jsHooks\":[]} To work with custom data, users need to generate a targets file containing the paths to their own FASTQ files and then provide under targetspath the path to the corresponding targets file.\nStructure of targets file for paired-end (PE) samples For paired-end (PE) samples, the structure of the targets file is similar, where users need to provide two FASTQ path columns: FileName1 and FileName2 with the paths to the PE FASTQ files.\ntargetspath \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") showDF(read.delim(targetspath, comment.char = \"#\")) {\"x\":{\"filter\":\"none\",\"vertical\":false,\"extensions\":[\"FixedColumns\",\"Scroller\"],\"data\":[[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\"],[\"./data/SRR446027_1.fastq.gz\",\"./data/SRR446028_1.fastq.gz\",\"./data/SRR446029_1.fastq.gz\",\"./data/SRR446030_1.fastq.gz\",\"./data/SRR446031_1.fastq.gz\",\"./data/SRR446032_1.fastq.gz\",\"./data/SRR446033_1.fastq.gz\",\"./data/SRR446034_1.fastq.gz\",\"./data/SRR446035_1.fastq.gz\",\"./data/SRR446036_1.fastq.gz\",\"./data/SRR446037_1.fastq.gz\",\"./data/SRR446038_1.fastq.gz\",\"./data/SRR446039_1.fastq.gz\",\"./data/SRR446040_1.fastq.gz\",\"./data/SRR446041_1.fastq.gz\",\"./data/SRR446042_1.fastq.gz\",\"./data/SRR446043_1.fastq.gz\",\"./data/SRR446044_1.fastq.gz\"],[\"./data/SRR446027_2.fastq.gz\",\"./data/SRR446028_2.fastq.gz\",\"./data/SRR446029_2.fastq.gz\",\"./data/SRR446030_2.fastq.gz\",\"./data/SRR446031_2.fastq.gz\",\"./data/SRR446032_2.fastq.gz\",\"./data/SRR446033_2.fastq.gz\",\"./data/SRR446034_2.fastq.gz\",\"./data/SRR446035_2.fastq.gz\",\"./data/SRR446036_2.fastq.gz\",\"./data/SRR446037_2.fastq.gz\",\"./data/SRR446038_2.fastq.gz\",\"./data/SRR446039_2.fastq.gz\",\"./data/SRR446040_2.fastq.gz\",\"./data/SRR446041_2.fastq.gz\",\"./data/SRR446042_2.fastq.gz\",\"./data/SRR446043_2.fastq.gz\",\"./data/SRR446044_2.fastq.gz\"],[\"M1A\",\"M1B\",\"A1A\",\"A1B\",\"V1A\",\"V1B\",\"M6A\",\"M6B\",\"A6A\",\"A6B\",\"V6A\",\"V6B\",\"M12A\",\"M12B\",\"A12A\",\"A12B\",\"V12A\",\"V12B\"],[\"M1\",\"M1\",\"A1\",\"A1\",\"V1\",\"V1\",\"M6\",\"M6\",\"A6\",\"A6\",\"V6\",\"V6\",\"M12\",\"M12\",\"A12\",\"A12\",\"V12\",\"V12\"],[\"Mock.1h.A\",\"Mock.1h.B\",\"Avr.1h.A\",\"Avr.1h.B\",\"Vir.1h.A\",\"Vir.1h.B\",\"Mock.6h.A\",\"Mock.6h.B\",\"Avr.6h.A\",\"Avr.6h.B\",\"Vir.6h.A\",\"Vir.6h.B\",\"Mock.12h.A\",\"Mock.12h.B\",\"Avr.12h.A\",\"Avr.12h.B\",\"Vir.12h.A\",\"Vir.12h.B\"],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\",\"23-Mar-2012\"]],\"container\":\"\\n \\n \\n \\n FileName1\\n FileName2\\n SampleName\\n Factor\\n SampleLong\\n Experiment\\n Date\\n \\n \\n\",\"options\":{\"scrollX\":true,\"fixedColumns\":true,\"deferRender\":true,\"scrollY\":200,\"scroller\":true,\"columnDefs\":[{\"className\":\"dt-right\",\"targets\":6},{\"orderable\":false,\"targets\":0}],\"order\":[],\"autoWidth\":false,\"orderClasses\":false}},\"evals\":[],\"jsHooks\":[]} Sample comparisons Sample comparisons are defined in the header lines of the targets file starting with ‘# \u003cCMP\u003e.’\nreadLines(targetspath)[1:4] ## [1] \"# Project ID: Arabidopsis - Pseudomonas alternative splicing study (SRA: SRP010938; PMID: 24098335)\" ## [2] \"# The following line(s) allow to specify the contrasts needed for comparative analyses, such as DEG identification. All possible comparisons can be specified with 'CMPset: ALL'.\" ## [3] \"# \u003cCMP\u003e CMPset1: M1-A1, M1-V1, A1-V1, M6-A6, M6-V6, A6-V6, M12-A12, M12-V12, A12-V12\" ## [4] \"# \u003cCMP\u003e CMPset2: ALL\" The function readComp imports the comparison information and stores it in a list. Alternatively, readComp can obtain the comparison information from the corresponding SYSargsList step (see below). Note, these header lines are optional. They are mainly useful for controlling comparative analyses according to certain biological expectations, such as identifying differentially expressed genes in RNA-Seq experiments based on simple pair-wise comparisons.\nreadComp(file = targetspath, format = \"vector\", delim = \"-\") ## $CMPset1 ## [1] \"M1-A1\" \"M1-V1\" \"A1-V1\" \"M6-A6\" \"M6-V6\" \"A6-V6\" \"M12-A12\" ## [8] \"M12-V12\" \"A12-V12\" ## ## $CMPset2 ## [1] \"M1-A1\" \"M1-V1\" \"M1-M6\" \"M1-A6\" \"M1-V6\" \"M1-M12\" \"M1-A12\" ## [8] \"M1-V12\" \"A1-V1\" \"A1-M6\" \"A1-A6\" \"A1-V6\" \"A1-M12\" \"A1-A12\" ## [15] \"A1-V12\" \"V1-M6\" \"V1-A6\" \"V1-V6\" \"V1-M12\" \"V1-A12\" \"V1-V12\" ## [22] \"M6-A6\" \"M6-V6\" \"M6-M12\" \"M6-A12\" \"M6-V12\" \"A6-V6\" \"A6-M12\" ## [29] \"A6-A12\" \"A6-V12\" \"V6-M12\" \"V6-A12\" \"V6-V12\" \"M12-A12\" \"M12-V12\" ## [36] \"A12-V12\" Downstream targets files description After the step which required the initial targets file information, the downstream targets files are created automatically (see Figure 2). Each step that uses the previous step outfiles as an input, the new targets input will be managed internally by the workflow instances, establishing connectivity among the steps in the workflow. systemPipeR provides features to automatically and systematically build this connection, providing security that all the samples will be managed efficiently and reproducibly.\nFigure 2: *`systemPipeR`* automatically creates the downstream `targets` files based on the previous steps outfiles. A) Usually, users provide the initial `targets` files, and this step will generate some outfiles, as demonstrated on B. Then, those files are used to build the new `targets` files as inputs in the next step. *`systemPipeR`* (C) manages this connectivity among the steps automatically for the users. Structure of the new parameters files The parameters and configuration required for running command-line software are provided by the widely used community standard Common Workflow Language (CWL) (Amstutz et al. 2016), which describes parameters analysis workflows in a generic and reproducible manner. For R-based workflow steps, param files are not required. For a complete overview of the CWL syntax, please see the section below. Also, we have a dedicated section explain how to systemPipeR establish the connection between the CWL parameters files and the targets files. Please see here.\nReferences Amstutz, Peter, Michael R Crusoe, Nebojša Tijanić, Brad Chapman, John Chilton, Michael Heuer, Andrey Kartashov, et al. 2016. “Common Workflow Language, V1.0,” July. https://doi.org/10.6084/m9.figshare.3115156.v2.\n Howard, Brian E, Qiwen Hu, Ahmet Can Babaoglu, Manan Chandra, Monica Borghi, Xiaoping Tan, Luyan He, et al. 2013. “High-Throughput RNA Sequencing of Pseudomonas-Infected Arabidopsis Reveals Hidden Transcriptome Complexity and Novel Splice Variants.” PLoS One 8 (10): e74183. https://doi.org/10.1371/journal.pone.0074183.\n ","categories":"","description":"","excerpt":" document.addEventListener(\"DOMContentLoaded\", function() …","ref":"/sp/spr/gettingstarted/","tags":"","title":"Getting Started"},{"body":"Build workflow from a template The precisely same workflow can be created by importing the steps from a template file. In SPR, we use R Markdown files as templates. As demonstrated above, it is required to initialize the project with SPRproject function.\nsuppressPackageStartupMessages({ library(systemPipeR) }) importWF importWF function will scan and import all the R chunk from the R Markdown file and build all the workflow instances. Then, each R chuck in the file will be converted in a workflow step.\nWe have prepared the template for you already. Let’s first see what is in the template or can be read here:\ncat(readLines(system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\")), sep = \"\\n\") --- title: \"Simple Workflow by systemPipeR\" author: \"Author: Daniela Cassol, Le Zhang, and Thomas Girke\" date: \"Last update: `r format(Sys.time(), '%d %B, %Y')`\" output: BiocStyle::html_document: toc_float: true code_folding: show package: systemPipeR vignette: | %\\VignetteEncoding{UTF-8} %\\VignetteIndexEntry{Workflow example} %\\VignetteEngine{knitr::rmarkdown} fontsize: 14pt --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` # Build the Workflow - Load `systemPipeR` library: ```{r load_library, eval=TRUE, spr=TRUE} appendStep(sal) \u003c- LineWise(code={ library(systemPipeR) }, step_name = \"load_library\", dependency = NA) ``` ## Export dataset to file - Add first step as `LineWise` ```{r export_iris, eval=TRUE, spr=TRUE} appendStep(sal) \u003c- LineWise(code={ mapply( function(x, y) write.csv(x, y), split(iris, factor(iris$Species)), file.path(\"results\", paste0(names(split(iris, factor(iris$Species))), \".csv\"))) }, step_name = \"export_iris\", dependency = \"load_library\") ``` ## Compress data - Adding the second step, as `SYSargs2` ```{r gzip, eval=TRUE, spr=TRUE, spr.dep=TRUE} targetspath \u003c- system.file(\"extdata/cwl/gunzip\", \"targets_gunzip.txt\", package = \"systemPipeR\") appendStep(sal) \u003c- SYSargsList(step_name = \"gzip\", targets = targetspath, dir = TRUE, wf_file = \"gunzip/workflow_gzip.cwl\", input_file = \"gunzip/gzip.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(FileName = \"_FILE_PATH_\", SampleName = \"_SampleName_\"), dependency = \"export_iris\") ``` ## Decompress data ```{r gunzip, eval=TRUE, spr=TRUE} appendStep(sal) \u003c- SYSargsList(step_name = \"gunzip\", targets = \"gzip\", dir = TRUE, wf_file = \"gunzip/workflow_gunzip.cwl\", input_file = \"gunzip/gunzip.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(gzip_file = \"_FILE_PATH_\", SampleName = \"_SampleName_\"), rm_targets_col = \"FileName\", dependency = \"gzip\") ``` ## Import data to R and perform statistical analysis and visualization ```{r stats, eval=TRUE, spr=TRUE} appendStep(sal) \u003c- LineWise(code={ df \u003c- lapply(getColumn(sal, step=\"gunzip\", 'outfiles'), function(x) read.delim(x, sep=\",\")[-1]) df \u003c- do.call(rbind, df) stats \u003c- data.frame(cbind(mean=apply(df[,1:4], 2, mean), sd=apply(df[,1:4], 2, sd))) stats$species \u003c- rownames(stats) plot \u003c- ggplot2::ggplot(stats, ggplot2::aes(x=species, y=mean, fill=species)) + ggplot2::geom_bar(stat = \"identity\", color=\"black\", position=ggplot2::position_dodge()) + ggplot2::geom_errorbar(ggplot2::aes(ymin=mean-sd, ymax=mean+sd), width=.2, position=ggplot2::position_dodge(.9)) }, step_name = \"stats\", dependency = \"gunzip\", run_step = \"optional\") ``` SPR chunks The SPR templates has no difference than a normal R markdown file, except one little thing – the SPR chunks.\nTo make a normal R chunk also a SPR chunk, in the chunk header spr=TRUE or spr=T option needs to be appended.\nFor example:\n ```{r step_1, eval=TRUE, spr=TRUE}\n ```{r step_2, eval=FALSE, spr=TRUE}\n Note here the eval=FALSE, by default steps with this option will still be imported, but you can use ignore_eval flag to change it in importWF.\nPreprocess code Inside SPR chunks, before the actual step definition, there is some special space called preprocess code.\nWhy do need preprocess code? When we import/create the workflow steps, these steps are not really executed when the time of creation, no matter it is a sysArgs step or a Linewise step. However, in many cases, we need to connect different previous steps' outputs to the inputs of the next. This is easy to handle between sysArgs steps via the targets argument connection. If it is a Linewise step to a sysArgs step. Things become tricky. Since Linewise code is not run at the time of step definition, no output paths are generated, so the next sysArgs step cannot find the inputs.\nTo overcome this problem, preprocess code feature is introduced. Defining preprocess code is very easy. Write any lines of R code below the SPR chunk header line. Right before the step is defined, insert one line of comment of ###pre-end to indicate the completion of preprocess code. For example:\ntargetspath \u003c- system.file(\"extdata\", \"cwl\", \"example\", \"targets_example.txt\", package = \"systemPipeR\") ###pre-end appendStep(sal) \u003c- SYSargsList( step_name = \"Example\", targets = targetspath, wf_file = \"example/example.cwl\", input_file = \"example/example.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(Message = \"_STRING_\", SampleName = \"_SAMPLE_\") ) In the example above the targets path is not directly loaded but given through an intermediate variable targetspath. This is a simple example, other useful actions like path concatenation, checking file integrity before piping to expensive (slow) functions can also be done in preprocess. Another good example will be the ChIPseq workflow. Watch closely how the output of LineWise step merge_bams is predicted and writing to an intermediate targets file on-the-fly in the preprocess code of call_peaks_macs_withref so it can be used in the call_peaks_macs_withref step creation as input targets.\nActually, if the SPR chunk has R code before the step definition but ###pre-end delimiter is not added, these code will still be evaluated at the time of import. However, these lines of code will not be store in the SYSargsList, so later when you render the report (renderReport) or export the workflow as a new template (sal2rmd), these lines will not be included. That means, these lines are one-shot reprocess code and not reproducible.\nOther rules For SPR chunks, the last object assigned must to be the SYSargsList, for example a sysArgs2(commandline) steps:\ntargetspath \u003c- system.file(\"extdata/cwl/example/targets_example.txt\", package = \"systemPipeR\") appendStep(sal) \u003c- SYSargsList(step_name = \"Example\", targets = targetspath, wf_file = \"example/example.cwl\", input_file = \"example/example.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(Message = \"_STRING_\", SampleName = \"_SAMPLE_\")) OR a Linewise (R) step:\nappendStep(sal) \u003c- LineWise(code = { library(systemPipeR) }, step_name = \"load_lib\") Also, note that all the required files or objects to generate one particular step must be defined in an imported R code. The motivation for this is that when R Markdown files are imported, the spr = TRUE flag will be evaluated, append, and stored in the workflow control class as the SYSargsList object.\n The workflow object name used in the R Markdown (e.g. appendStep(sal)) needs to be the same when the importWF function is used. Usually we use the name sal ( short abbreviation for sysargslist). It is important to keep consistency. If different object names are used, when running the workflow, you can see a error, like Error: object not found..\n Special in importWF: SPR chunk names will be used as step names, and it has higher priority than the stepname argument. For example, the chunk header is {r step_1, eval=TRUE, spr=TRUE}, and the inside SYSargsList option is SYSargsList(step_name = \"step_99\", ...). After the import, step name will be overwritten to \"step_1\" instead of \"step_99\".\n start to import sal_rmd \u003c- SPRproject(logs.dir = \".SPRproject_rmd\") ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject_rmd' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject_rmd/SYSargsList.yml' sal_rmd \u003c- importWF(sal_rmd, file_path = system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\")) ## Reading Rmd file ## ## ---- Actions ---- ## Checking chunk eval values ## Checking chunk SPR option ## Ignore non-SPR chunks: 17 ## Parse chunk code ## Checking preprocess code for each step ## No preprocessing code for SPR steps found ## Now importing step 'load_library' ## Now importing step 'export_iris' ## Now importing step 'gzip' ## Now importing step 'gunzip' ## Now importing step 'stats' ## Now back up current Rmd file as template for `renderReport` ## Template for renderReport is stored at ## /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject_rmd/workflow_template.Rmd ## Edit this file manually is not recommended ## import done sal_rmd ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## We can see 5 steps are appended to our sal object.\nSimple exploration After import, we can explore the workflow to check the steps:\n# list individual steps stepsWF(sal_rmd) ## $load_library ## Instance of 'LineWise' ## Code Chunk length: 1 ## ## $export_iris ## Instance of 'LineWise' ## Code Chunk length: 1 ## ## $gzip ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 3 (SE...VI), targetsheader: 1 (lines) ## modules: 0 ## wf: 1, clt: 1, yamlinput: 4 (inputs) ## input: 3, output: 3 ## cmdlist: 3 ## Sub Steps: ## 1. gzip (rendered: TRUE) ## ## ## ## $gunzip ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 3 (SE...VI), targetsheader: 1 (lines) ## modules: 0 ## wf: 1, clt: 1, yamlinput: 4 (inputs) ## input: 3, output: 3 ## cmdlist: 3 ## Sub Steps: ## 1. gunzip (rendered: TRUE) ## ## ## ## $stats ## Instance of 'LineWise' ## Code Chunk length: 5 # list step dependency dependency(sal_rmd) ## $load_library ## [1] NA ## ## $export_iris ## [1] \"load_library\" ## ## $gzip ## [1] \"export_iris\" ## ## $gunzip ## [1] \"gzip\" ## ## $stats ## [1] \"gunzip\" # list R step code codeLine(sal_rmd) ## gzip AND gunzip step have been dropped because it is not a LineWise object. ## load_library ## library(systemPipeR) ## export_iris ## mapply(function(x, y) write.csv(x, y), split(iris, factor(iris$Species)), file.path(\"results\", paste0(names(split(iris, factor(iris$Species))), \".csv\"))) ## stats ## df \u003c- lapply(getColumn(sal, step = \"gunzip\", \"outfiles\"), function(x) read.delim(x, sep = \",\")[-1]) ## df \u003c- do.call(rbind, df) ## stats \u003c- data.frame(cbind(mean = apply(df[, 1:4], 2, mean), sd = apply(df[, 1:4], 2, sd))) ## stats$species \u003c- rownames(stats) ## plot \u003c- ggplot2::ggplot(stats, ggplot2::aes(x = species, y = mean, fill = species)) + ggplot2::geom_bar(stat = \"identity\", color = \"black\", position = ggplot2::position_dodge()) + ggplot2::geom_errorbar(ggplot2::aes(ymin = mean - sd, ymax = mean + sd), width = 0.2, position = ggplot2::position_dodge(0.9)) # list step targets targetsWF(sal_rmd) ## $load_library ## DataFrame with 0 rows and 0 columns ## ## $export_iris ## DataFrame with 0 rows and 0 columns ## ## $gzip ## DataFrame with 3 rows and 2 columns ## FileName SampleName ## \u003ccharacter\u003e \u003ccharacter\u003e ## SE results/setosa.csv SE ## VE results/versicolor.csv VE ## VI results/virginica.csv VI ## ## $gunzip ## DataFrame with 3 rows and 2 columns ## gzip_file SampleName ## \u003ccharacter\u003e \u003ccharacter\u003e ## SE results/SE.csv.gz SE ## VE results/VE.csv.gz VE ## VI results/VI.csv.gz VI ## ## $stats ## DataFrame with 0 rows and 0 columns Update workflow Maybe you have noticed some lines in the importing\nTemplate for renderReport is stored at xxxx/.SPRproject_rmd/workflow_template.Rmd Edit this file manually is not recommended It means current import is successful and a copy of your workflow template is copied to this position, and it will be used for renderReport as the skeleton.\nIn real data analysis, the workflow template does not always stays the same, e.g. adding some text, new steps to the template. One way we could add new steps is the interactive method. The problem is this way does not contain any text description in the final report. renderReport has a smart way to insert these new steps that do not exist in the template to the right order but it cannot create text descrption for you.\nAnother way to import new steps or update text in the template is to use importWF(..., update = TRUE).\nExample 1 Let’s add a step and some text to spr_simple_wf.Rmd and try to update.\n update = TRUE is highly interactive. It uses a Q\u0026A style to ask users things like whether to update preprocess code of certain steps, whether to import certain new steps. In this mode, you can always say “no” to the choice, so you can choose to partially update the template. Rendering the webpage document is not interactive, so here we use importWF(..., update = TRUE, confirm = TRUE), which means confirm all the choices, say “yes” to all. Then, partially update is no longer the option here. For the updated template, you can download here\nOne step, preprocess code and some description has been added to the end:\n## A new step This is a new step with some simple code to demonstrate the update of `importWF` ```{r session_info, eval=TRUE, spr=TRUE} cat(\"some fake preprocess code\\n\") ###pre-end appendStep(sal) \u003c- LineWise(code={ sessionInfo() }, step_name = \"sessionInfo\", dependency = \"stats\") ``` # the file is with `.md` extension, but `importWF` needs `.Rmd`. # we need to first download and change extension tmp_file \u003c- tempfile(fileext = \".rmd\") download.file( \"https://raw.githubusercontent.com/systemPipeR/systemPipeR.github.io/main/static/en/sp/spr/sp_run/spr_simple_wf_new.md\", tmp_file ) sal_rmd \u003c- importWF(sal_rmd, file_path = tmp_file, update = TRUE, confirm = TRUE) ## Reading Rmd file ## ## ---- Actions ---- ## Checking chunk eval values ## Checking chunk SPR option ## Ignore non-SPR chunks: 17 ## Parse chunk code ## Checking preprocess code for each step ## Update starts. Note for existing steps, update only fix the line number records. They are NOT imported again. If you have changed arguments in methods like `SYSargsList`, `Linewise`, `appendStep` in template for some steps, delete the original step from the workflow and rerun this function or manually to import it again, or use replacement methods to change arguments in current workflow, see ?`SYSargsList-class` help file. Otherwise, package would use what is in the current workflow to `renderReport` and `sal2rmd`. New arguments in the template will be ignored. ## Comparing SPR steps ## Some new steps exist in new template but not in current SYSargsList. ## They will be imported to workflow later. Update existing steps first. ## steps: sessionInfo ## Comparing step orders ## Note this function checks SPR step sequental orders, not the dependency graph. Order change will not be immediately taken place in SYSargsList object. New orders will be only used in `renderReport`. `sal2rmd` still uses the order in SYSargsList object. ## Some steps in the new template have different order than SYSargsList. ## sessionInfo: 0 -\u003e 6 ## Updating SPR steps line numbers ## Updating SPR steps preprocess code information ## Template update done. ## Now importing new steps ## Now importing step 'sessionInfo' ## some fake preprocess code ## Now back up current Rmd file as template for `renderReport` ## Template for renderReport is stored at ## /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject_rmd/workflow_template.Rmd ## Edit this file manually is not recommended ## update done We can see under update mode, importWF compare the old template and the new template and find the difference. List all differences to users. It includes:\n List all new steps Compare step orders, update if needed update line number records of steps from old template to new template. update preprocess code finally import new steps A new step has been successfully imported from the new template.\nsal_rmd ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## 6. sessionInfo --\u003e Status: Pending ## Under interactive mode, users would have a lot more options. For example, when adding a new step, importWF has a back-tracking algorithm that automatically detects the right order where this step should be appended. However, things can go wrong and it does not work 100%. Under interactive mode, the program first lists the previous step where this new step would be appended after, and then users have the option to choose whether this is the correct step. If not, a new prompt would pop up to let the users to manually choose the right order to append the new step. See the gif below.\n This does not mean you could append a step to any place. It also has to meet the dependency requirement. For example, this new step is depend on step 5 but you manually choose to append it after step 1. Then, the import would fail.\n Example 2 Let’s see another example how importWF update preprocess code and line numbers\ntmp_file2 \u003c- tempfile(fileext = \".rmd\") download.file( \"https://raw.githubusercontent.com/systemPipeR/systemPipeR.github.io/main/static/en/sp/spr/sp_run/spr_simple_wf_new_precode_changed.md\", tmp_file2 ) sal_rmd \u003c- importWF(sal_rmd, file_path = tmp_file2, update = TRUE, confirm = TRUE) ## Reading Rmd file ## ## ---- Actions ---- ## Checking chunk eval values ## Checking chunk SPR option ## Ignore non-SPR chunks: 17 ## Parse chunk code ## Checking preprocess code for each step ## Update starts. Note for existing steps, update only fix the line number records. They are NOT imported again. If you have changed arguments in methods like `SYSargsList`, `Linewise`, `appendStep` in template for some steps, delete the original step from the workflow and rerun this function or manually to import it again, or use replacement methods to change arguments in current workflow, see ?`SYSargsList-class` help file. Otherwise, package would use what is in the current workflow to `renderReport` and `sal2rmd`. New arguments in the template will be ignored. ## Comparing SPR steps ## Comparing step orders ## Updating SPR steps line numbers ## Updating step lines of stats 76:92 -\u003e 79:95 ## Updating step lines of sessionInfo 96:104 -\u003e 99:108 ## Updating SPR steps preprocess code information ## For step sessionInfo old preprocess code: ## cat(\"some fake preprocess code\\n\") ## ###pre-end ## New preprocess code: ## 1+1 ## cat(\"some fake preprocess code that has been changed!\\n\") ## ###pre-end ## Template update done. ## Now importing new steps ## Now back up current Rmd file as template for `renderReport` ## Template for renderReport is stored at ## /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject_rmd/workflow_template.Rmd ## Edit this file manually is not recommended ## update done Note for existing steps, and their preprocess code, they are not re-imported or re-evaluated.\n Colors Rendering the web document is not interactive, so colors are also removed. It is only gray color in code chunks above, but in the actual interactive mode, multiple colors are used to indicate the status as you have seen in the gifs.\nAdvanced templates There are quite a few pre-configed templates that is provided by the systemPipeRdata package. You can also take a look at them individual here\nSession sessionInfo() ## R version 4.2.0 (2022-04-22) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.4 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] systemPipeR_2.3.4 ShortRead_1.54.0 ## [3] GenomicAlignments_1.32.0 SummarizedExperiment_1.26.1 ## [5] Biobase_2.56.0 MatrixGenerics_1.8.0 ## [7] matrixStats_0.62.0 BiocParallel_1.30.2 ## [9] Rsamtools_2.12.0 Biostrings_2.64.0 ## [11] XVector_0.36.0 GenomicRanges_1.48.0 ## [13] GenomeInfoDb_1.32.2 IRanges_2.30.0 ## [15] S4Vectors_0.34.0 BiocGenerics_0.42.0 ## ## loaded via a namespace (and not attached): ## [1] lattice_0.20-45 png_0.1-7 assertthat_0.2.1 ## [4] digest_0.6.29 utf8_1.2.2 R6_2.5.1 ## [7] evaluate_0.15 ggplot2_3.3.6 blogdown_1.10 ## [10] pillar_1.7.0 zlibbioc_1.42.0 rlang_1.0.2 ## [13] rstudioapi_0.13 jquerylib_0.1.4 Matrix_1.4-1 ## [16] rmarkdown_2.14 stringr_1.4.0 htmlwidgets_1.5.4 ## [19] RCurl_1.98-1.6 munsell_0.5.0 DelayedArray_0.22.0 ## [22] compiler_4.2.0 xfun_0.31 pkgconfig_2.0.3 ## [25] htmltools_0.5.2 tidyselect_1.1.2 tibble_3.1.7 ## [28] GenomeInfoDbData_1.2.8 bookdown_0.26 fansi_1.0.3 ## [31] dplyr_1.0.9 crayon_1.5.1 bitops_1.0-7 ## [34] grid_4.2.0 DBI_1.1.2 jsonlite_1.8.0 ## [37] gtable_0.3.0 lifecycle_1.0.1 magrittr_2.0.3 ## [40] scales_1.2.0 cli_3.3.0 stringi_1.7.6 ## [43] hwriter_1.3.2.1 latticeExtra_0.6-29 bslib_0.3.1 ## [46] generics_0.1.2 ellipsis_0.3.2 vctrs_0.4.1 ## [49] RColorBrewer_1.1-3 tools_4.2.0 glue_1.6.2 ## [52] purrr_0.3.4 jpeg_0.1-9 parallel_4.2.0 ## [55] fastmap_1.1.0 yaml_2.3.5 colorspace_2.0-3 ## [58] knitr_1.39 sass_0.4.1 ","categories":"","description":"","excerpt":"Build workflow from a template The precisely same workflow can be …","ref":"/sp/spr/sp_run/step_import/","tags":"","title":"Import workflow from template"},{"body":"Full if (!requireNamespace(\"BiocManager\", quietly=TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeShiny\", dependencies=TRUE) This will install all required packages including suggested packages that are required by the core modules. Be aware, it will take quite some time if you are installing on Linux where only source installation is available. Windows and Mac binary installations will be much faster.\nMinimum To install the package, please use the BiocManager::install command:\nif (!requireNamespace(\"BiocManager\", quietly=TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeShiny\") By the minimum installation, all the 3 core modules are not installed. You can still start the app, and When you start the app and click on these modules, it will tell to enable these modules, what packages and command you need to run. Just follow the instructions. So, install as you need.\nMost recent To obtain the most recent updates immediately, one can install it directly from GitHub{blk} as follow:\nif (!requireNamespace(\"remotes\", quietly=TRUE)) install.packages(\"remotes\") remotes::install(\"systemPipeR/systemPipeShiny\", dependencies=TRUE) Similarly, remotes::install(\"systemPipeR/systemPipeShiny\") for the minimum develop version.\nLinux If you are on Linux, you may also need the following libraries before installing SPS. Different distributions may have different commands, but the following commands are examples for Ubuntu:\nsudo apt-get install -y libicu-dev sudo apt-get install -y pandoc sudo apt-get install -y zlib1g-dev sudo apt-get install -y libcurl4-openssl-dev sudo apt-get install -y libssl-dev sudo apt-get install -y make On other Linux distributions, the install commands may be slightly different.\n","categories":"","description":"","excerpt":"Full if (!requireNamespace(\"BiocManager\", quietly=TRUE)) …","ref":"/sps/install/","tags":"","title":"Installation"},{"body":" SPS tabs In SPS, tab is the basic component of a functionality unit. For example, all the Modules in SPS are complex tabs with many small sub-tabs, the Canvas is another independent tab providing image editing features and an user custom tab is also a SPS tab.\nFrom the developer’s view, all SPS tabs are Shiny Modules{blk}.\nTo understand how SPS tabs work, we will demonstrate with a SPS project. For demo purpose, we are using the /tmp folder but one should use a regular location instead of the temp in a real case.\nsuppressPackageStartupMessages(library(systemPipeShiny)) spsInit(app_path = tempdir(), project_name = \"tab_demo\", overwrite = TRUE, change_wd = FALSE) ## [SPS-INFO] 2021-04-19 23:16:52 Start to create a new SPS project ## [SPS-INFO] 2021-04-19 23:16:52 Create project under /tmp/RtmpjAYUc0/tab_demo ## [SPS-INFO] 2021-04-19 23:16:52 Now copy files ## [SPS-INFO] 2021-04-19 23:16:52 Create SPS database ## [SPS-INFO] 2021-04-19 23:16:52 Created SPS database method container ## [SPS-INFO] 2021-04-19 23:16:52 Creating SPS db... ## [SPS-DANGER] 2021-04-19 23:16:52 Done, Db created at '/tmp/RtmpjAYUc0/tab_demo/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-19 23:16:52 Key md5 ecdf3312953a6bcdaea49e6d85954b80 ## [SPS-INFO] 2021-04-19 23:16:52 SPS project setup done! ## save project path (sps_dir \u003c- file.path(tempdir(), \"tab_demo\")) ## [1] \"/tmp/RtmpjAYUc0/tab_demo\" To reproduce code locally, run the following chunk instead.\nlibrary(systemPipeShiny) spsInit() sps_dir \u003c- normalizePath(\".\") Tab registration In SPS, all tabs are controlled by the config/tabs.csv file. To see what kind of tabs you have with current project. use the spsTabInfo function. It returns a tibble of current tab information.\nspsTabInfo(app_path = sps_dir) ## # A tibble: 11 x 8 ## tab_id display_label type type_sub image displayed tab_file_name plugin ## \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e ## 1 core_ab… About this App core \"\" \"\" 1 No file for … \"core\" ## 2 core_ca… Canvas core \"\" \"\" 1 No file for … \"core\" ## 3 core_we… Home core \"\" \"\" 1 No file for … \"core\" ## 4 core_ri… Internal use on… core \"\" \"\" 1 No file for … \"core\" ## 5 core_top Top push bars core \"\" \"\" 1 No file for … \"core\" ## 6 module_… Module Main Page core \"\" \"\" 1 No file for … \"core\" ## 7 wf Workflow module modu… \"\" \"\" 1 No file for … \"core\" ## 8 vs_rnas… RNAseq module modu… \"\" \"\" 1 No file for … \"core\" ## 9 vs_esq Quick ggplot mo… modu… \"\" \"\" 1 No file for … \"core\" ## 10 vs_main custom tabs mai… core \"\" \"\" 1 No file for … \"core\" ## 11 vs_exam… My custom plott… vs \"plot\" \"\" 1 tab_vs_examp… \"\" tab_id: A unique string ID display_label: for type is “core” or “module”, this is only some description, but for you own custom tabs, this value will be used as a display tab name on left sidebar on SPS UI. type: tab category, “core”, “module” and “vs” (visualization). type_sub: more specific category, current only “plot” (plotting) image: If this is an user custom tab, providing an image path will display the image in visualization main tab gallery. If it not provided, a warning will be given on app starts and an “No image” image will be used like the following: displayed: Internal use only tab_file_name: where the tab file is relative to the R folder. plugin: Internal use only Add a new custom tab SPS provides templates to help developers to create a small SPS tab that\n The main purpose is to generate some plots can be loaded into SPS framework easily can interact with other SPS tabs (components), like the Canvas tab. When you initiate a SPS project, an example custom tab is created for you already. You can find the tab file inside the R folder of the project root. When you start the app for the first time, you can easily find it from the left sidebar, or click on the “Custom tabs” to go to custom tab main tab.\n Example custom tab Simple template Under current SPS version, users are able to add custom tabs with the spsNewTab function. This function:\n creates the tab file. provides a nice template. Helps you to register tab information to tabs.csv spsNewTab(tab_id = \"vs_new\", tab_displayname = \"New tab demo\", app_path = sps_dir) ## [SPS-INFO] 2021-04-19 23:16:52 Write to file /tmp/RtmpjAYUc0/tab_demo/R/tab_vs_new.R ## [SPS-INFO] 2021-04-19 23:16:52 Now register your new tab to config/tab.csv ## [SPS-SUCCESS] 2021-04-19 23:16:52 New tab created! ## [SPS] 2021-04-19 23:16:52 To load this new tab: `sps(tabs = c(\"vs_new\")` If you are running the code locally, and are using Rstudio, the tab file will be opened automatically for you.\nIn your global.R, add the new tab to confirm you want to load it, and then restart you app. Scroll down to the bottom, you should see:\n# add \"vs_new\" in `tabs` sps_app \u003c- sps( tabs = c(\"vs_example\", \"vs_new\"), server_expr = { msg(\"Custom expression runs -- Hello World\", \"GREETING\", \"green\") } ) Load new custom tabs By default, it uses the simple template, which contains the spsEzUI and spsEzServer functions. We have provided commented instructions on how to fill each argument.\nUI spsEzUI( desc = \"xxx\", tab_title = \"xxx\", plot_title = \"xxx\", plot_control = shiny::tagList( xxx ) ) The only augment new users need to take some time to learn is adding plot_control. Developers need to add some Shiny UI components to let users control how the plotting is done with interactive options. Basic use can be learned in 5 minutes on Shiny website{blk} and Shiny book{blk}\nServer spsEzServer( plot_code = { # data passed from data loading is a reactiveValues object, data stored in `mydata$data` plot_data \u003c- mydata$data # some validations, make sure users give you the right data format spsValidate({ stopifnot(inherits(plot_data, \"data.frame\")) # require a dataframe stopifnot(nrow(plot_data) \u003e 1) # has least one row if (!all(c(\"Sepal.Length\", \"Sepal.Width\") %in% colnames(plot_data)))# has two required columns stop(\"Require column 'Sepal.Length' and 'Sepal.Width'\") TRUE # give it a TRUE if all checks passed. }, verbose = FALSE # only show messages when fail ) # actual plot code ggplot2::ggplot(plot_data) + ggplot2::geom_point(ggplot2::aes(x = Sepal.Length, y = Sepal.Width)) + # grab user defined title from plot control by `input$+control_ID`, # no need to add `ns()` on server end. ggplot2::ggtitle(input$plot_title) }, other_server_code = {} ) For the server code, users only need to focus on the plotting code. The only very important thing developers need to remember is that the plotting data been passed to this function is stored in a reactiveValues{blk} object and it is called mydata$data. Usually we assign it to a new value so it can be used easily downstream, like plot_data \u003c- mydata$data.\nSome validation is recommended before reaching the plotting code. You would never know what kind of dataset users upload. It is always good to check if users' uploads meet the requirements. In SPS you can use the spsValidate function or use Shiny’s default validate{blk} function (spsValidate is discussed in developer tools).\nFull template For some developers who already has experience with Shiny, and would like to make more complex customization, using the full template enables you to change every detail on the new tab. Simply add the template = \"full\" argument.\nspsNewTab( tab_id = \"vs_new_full\", tab_displayname = \"New tab demo\", template = \"full\", app_path = sps_dir) ## [SPS-INFO] 2021-04-19 23:16:52 Write to file /tmp/RtmpjAYUc0/tab_demo/R/tab_vs_new_full.R ## [SPS-INFO] 2021-04-19 23:16:52 Now register your new tab to config/tab.csv ## [SPS-SUCCESS] 2021-04-19 23:16:52 New tab created! ## [SPS] 2021-04-19 23:16:52 To load this new tab: `sps(tabs = c(\"vs_new_full\")` You can see the full template is a lot longer than the simple template:\nsimple_len \u003c- R.utils::countLines(file.path(sps_dir, \"R\", \"tab_vs_new.R\")) full_len \u003c- R.utils::countLines(file.path(sps_dir, \"R\", \"tab_vs_new_full.R\")) spsinfo(glue::glue(\"Simple template has {simple_len} lines\"), TRUE) ## [SPS-INFO] 2021-04-19 23:16:52 Simple template has 66 lines spsinfo(glue::glue(\"Full template has {full_len} lines\"), TRUE) ## [SPS-INFO] 2021-04-19 23:16:52 Full template has 281 lines Tab registeration In your global.R, scroll down to the bottom, you should see:\nsps_app \u003c- sps( tabs = c(\"vs_example\"), server_expr = { msg(\"Custom expression runs -- Hello World\", \"GREETING\", \"green\") } ) This is the SPS main function. You can load/unload custom tabs by providing tab IDs in tabs argument, like c(\"tab1\", \"tab2). Open config/tabs.csv or use spsTabInfo() to see what tabs IDs can be load and other tab information. Essential framework tabs (core) and built-in modules (modules) are loaded automatically. However, you can choose to unload core and modules tabs, and overwrite core tabs by changing some SPS options.\nTab naming Once a tab ID is provided in the sps function tabs argument, when the function runs, it is looking for tab information inside this tabs.csv, like the display name and tab image. Then it will search for the UI and server function in the enviornment. It is expecting a UI function named tab_id + UI -\u003e tab_idUI and the server tab_id + Server -\u003e tab_idServer. If you did not use the spsNewTab function to generate the new tab, make sure you name your tab UI and server in this pattern.\n","categories":"","description":"","excerpt":" SPS tabs In SPS, tab is the basic component of a functionality unit. …","ref":"/sps/adv_features/tabs/","tags":"","title":"Manage tabs"},{"body":" As a framework, default SPS tabs like the welcome tab, the module main tab, the visualization main tab, the Canvas tab and the About tab can be user-defined.\n Default UI and tabs you can overwrite Overwrite SPS default tabs To start create a SPS project:\nsuppressPackageStartupMessages(library(systemPipeShiny)) app_path \u003c- \".\" spsInit(app_path = app_path, overwrite = TRUE, open_files = FALSE) ## [SPS-DANGER] 2021-04-22 15:45:11 Done, Db created at '/tmp/Rtmp2YLDmY/overwrite/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-22 15:45:11 Key md5 6886f6bf17229ffb646102abad92fa31 ## [SPS-INFO] 2021-04-22 15:45:11 SPS project setup done! use the function spsCoreTabReplace to create a template of which tab you would like to overwrite. Here we use the “Welcome” tab as example to demo how to write your own welcome tab.\nspsCoreTabReplace(replace_tab = \"welcome\") ## [SUCCESS] 2021-04-22 15:45:11 File /tmp/Rtmp2YLDmY/overwrite/R/tab_core_welcome.R created If you are using Rstudio the template will be opened for you like following:\n########################## Overwrite the welcome tab ########################### ## UI core_welcomeUI \u003c- function(id){ ns \u003c- NS(id) tagList( # add your UI code below ) } ## server core_welcomeServer \u003c- function(id, shared){ module \u003c- function(input, output, session, shared){ ns \u003c- session$ns # add your server code below } moduleServer(id, module) } Then you can write your own UI and server for this tab, for example, we can add some UI to the tab:\ncore_welcomeUI \u003c- function(id){ ns \u003c- NS(id) tagList( # add your UI code below h2(\"This is my welcome page\"), h4(\"some UI\"), sliderInput(ns(\"num\"), \"Select a number\", 0, 10, 5) ) } When you restart the app, you should see your custom Welcome tab:\n Custom Welcome tab UI ","categories":"","description":"","excerpt":" As a framework, default SPS tabs like the welcome tab, the module …","ref":"/sps/adv_features/overwritetabs/","tags":"","title":"Overwrite tabs"},{"body":"RNA-Seq Module This is a module which takes a raw count table to do normalization, Differential gene expression (DEG) analysis, and finally helps users to generate different plots to visualize the results.\nPrepare metadata and count table To start, we require two files, the metadata file (targets) and a raw count table (Fig. 5).\n Figure 5 RNAseq\n This is the RNAseq module UI when you first click it. All sub-tabs are disbled at the beginning. Other tabs will enabled as you proceed with different options. First, we need a metadata file to tell SPS what samples and conditions to use. Here, we use the metadata file from SPR, which is also known as “targets” file. If you are not familiar with the targets file, we suggest to use the workflow module step 2 to practice creating and checking the format. You can also use the example to see how it looks like. The loaded targets table is display here. You can use the box below each column name to filter what samples to include/exclude. Only the “SampleName” and “Factor” columns are used, other columns are ignored. SampleName should be a unique character string without space for each row. Factor is the experiment design factors, or conditions, or treatments. If you want to DEG analysis, DEG comparison groups are defined in the targets file header. The header will be parsed into comparison groups which contain individual comparisons. If the parsed comparison is not what you want, edit the header lines and reupload. If everything is expected, confirm to use this table. You should see the progress timeline of step 1 becomes green if your targets and header pass the format checking. (Not on figure) Similarly, use example or upload a count table and confirm to use it. Note: For the count table, the first column will be used as gene names. Other column names will be treated as sample names, and values in these columns are treated as raw counts. Make sure columns except the first one are numeric, and replace NA with 0.\nUpon successfully confirm targets and count table, you should see the “Normalize Data” subtab is enabled. You can click on the top navigation or click the pop-up for the next step.\nProcess raw count If this UI is displayed, that means your targets and count table are accepted by SPS (Fig 6). On this sub-tab, you can choose:\n Transform your count data with “raw”, “rlog” or “VST” and visualize the results in other sub-tabs. Do DEG analysis. These two options are independent.\n Figure 6 RNAseq Normalization\n At step 1 panel, choose how SPS can help you, count transformation or DEG analysis. The former will jump you to step 2, latter will jump to step 3. There are many options. If you are not clear, hover your mouse on the option, and some tips will show up. To start data transformation or DEG analysis. A gallery of different plot options will show up when the data process is done. When the data process is done, you can download results from the right side panel. Check all items you want and SPS will help you to zip it into one file to download. If at least one item is checked, downloading is enabled. Progress timeline will also change upon successful data process. Different visualization options will be enabled depending on the data process options. Plot options SPS RNAseq module provides 6 different plot options to cluster transformed count table.\n Figure 6 RNAseq plots\n Change plot options to customize your plots. Most plots are Plotly plots, which means you can interact with these plots, like hiding/show groups, zoom in/out, etc. All SPS plots are resizable. Drag the bottom-right corner icon to resize your plot. Click “To canvas” to take a screenshot of current plot and edit it in SPS Canvas tab. Or clicking the down-arrow button to directly save current plot to a png or jpg. DEG report This is a special sub-tab designed to filter and visualize DEG results. This sub-tab can be accessed once the DEG is calculated on the “Normalize Data” sub-tab.\n Figure 7 RNAseq DEG\n DEG summary plot. You can view what are the DEG results across different comparision groups. Switch to view a ggplot friendly table. Different from the table you could download from “Normalize Data” subtab, this DEG table is rearranged so you can easily make a ggplot from it. You can change the filter settings here, so DEGs will be re-filtered and you do not need to go back to “Normalize Data” subtab to recalculate DEG. DEG plotting options. Choose from a volcano plot, an upset plot (intersection), a MA plot or a heatmap. Interact with other bioconductor packages. Locally If you are familiar with R and want to continue other analysis after these, simple stop SPS:\n After count transformation, there is a spsRNA_trans object stored in your R environment. raw method gives you a normalized count table. Other two methods give you a DESeq2 class object. You can use it for other analysis. After DEG analysis, SPS stores a global object called spsDEG. It is a summerizedExperiment object which has all individual tables from all DEG comparisons. You can use it for other downstream analysis. Remotely If you are using SPS from a remote server, you can choose to download results from “Normalize Data” sub-tab. Choose results in tabular format or summerizedExperiment format which is saved in a .rds file.\n","categories":"","description":"","excerpt":"RNA-Seq Module This is a module which takes a raw count table to do …","ref":"/sps/modules/rnaseq/","tags":"","title":"RNAseq"},{"body":"How to create a new Workflow Template SPRthis package expand usethis package, providing automation to create systemPipeR workflows templates.\nInstallation To install SPRthis using from BiocManager the following code:\nif (!requireNamespace(\"BiocManager\", quietly = TRUE)) { install.packages(\"BiocManager\") BiocManager::install(\"dcassol/SPRthis\") Quick start to using to SPRthis ## Load the package library(SPRthis) ## create Package sprthis(wfName=\"SPRtest\", analysis=\"SPRtest\", path=tempdir()) ## ✔ Creating '/tmp/RtmpUJVdef/SPRtest/' ## ✔ Setting active project to '/tmp/RtmpUJVdef/SPRtest' ## ✔ Creating 'R/' ## ✔ Writing 'DESCRIPTION' ## Package: SPRtest ## Title: SPRtest ## Version: 0.99.0 ## Date: 2022-04-29 ## Authors@R (parsed): ## * First Last \u003cfirst.last@example.com\u003e [aut, cre] (YOUR-ORCID-ID) ## Description: This package provides a pre-configured workflow and reporting ## template for SPRtest. ## License: Artistic-2.0 ## URL: https://github.com/systemPipeR/SPRtest ## Imports: ## systemPipeR (\u003e= 1.25.0) ## Suggests: ## BiocStyle, ## knitr, ## rmarkdown ## VignetteBuilder: ## knitr ## biocViews: Infrastructure, ... ## Encoding: UTF-8 ## Roxygen: list(markdown = TRUE) ## RoxygenNote: 7.1.2 ## SystemRequirements: SPRtest can be used to run external command-line ## software, but the corresponding tool needs to be installed on a ## system. ## ✔ Writing 'NAMESPACE' ## ✔ Setting active project to '\u003cno active project\u003e' ## ✔ Setting active project to '/tmp/RtmpUJVdef/SPRtest' ## ✔ Adding 'testthat' to Suggests field in DESCRIPTION ## ✔ Setting Config/testthat/edition field in DESCRIPTION to '3' ## ✔ Creating 'tests/testthat/' ## ✔ Writing 'tests/testthat.R' ## ✔ Writing 'tests/testthat/test-SPRtest.R' ## • Edit 'tests/testthat/test-SPRtest.R' ## [1] \"/tmp/RtmpUJVdef/SPRtest\" SPRtest/ ├── DESCRIPTION ├── NAMESPACE ├── README.md ├── SPRtest.Rproj ├── .gitignore ├── .Rbuildignore ├── .Rproj.user/ ├── R/ │ ├── functions.R ├── vignettes │ ├── bibtex.bib │ ├── SPRtest.Rmd └── inst ├── rmarkdown │ └── templates │ └── SPRtest │ ├── template.yml │ └── skeleton │ ├── batchtools.slurm.tmpl │ ├── .batchtools.conf.R │ ├── bibtex.bib │ ├── NEWS │ ├── SPRconfig.yml │ ├── skeleton.Rmd │ ├── targetsPE.txt │ ├── data/ │ ├── param/ │ └── results/ Help functions to create the package Create the webiste for the package with pkgdown Edit the _pkgdown.yml file and run:\npkgdown::build_site() Documentation with roxygen2 roxygen2::roxygenise() Testing the code with testthat To test the code, you can run\ndevtools::test() Update R Markdown template on skeleton path \u003c- file.path(\"vignettes/SPRtest.Rmd\") skeleton_update(path) Package available to genWorkenvir Function After creating the new repository on GitHub systemPipeR Organization, please follow:\n Rules: The Workflow Template need to be available under systemPipeR Organization; The repository needs to be public; About setting: Description: keywords in the description are required: “Workflow Template”; Topics: we expected “systempiper” and “release” or “development” words on Topics section; Branch name: To make simple, please name the branch as “master”. Check availability of workflow templates A collection of workflow templates are available, and it is possible to browse the current availability, as follows:\nsystemPipeRdata::availableWF(github = TRUE) ## $systemPipeRdata ## [1] \"chipseq\" \"new\" \"riboseq\" \"rnaseq\" \"varseq\" ## ## $github ## workflow branches version ## 1 systemPipeR/SPchipseq master release ## 2 systemPipeR/SPriboseq master release ## 3 systemPipeR/SPrnaseq cluster, master, singleMachine release ## 4 systemPipeR/SPvarseq master release ## 5 systemPipeR/SPatacseq master devel ## 6 systemPipeR/SPblast master devel ## 7 systemPipeR/SPclipseq master devel ## 8 systemPipeR/SPdenovo master devel ## 9 systemPipeR/SPhic master devel ## 10 systemPipeR/SPmetatrans master devel ## 11 systemPipeR/SPmethylseq master devel ## 12 systemPipeR/SPmirnaseq master devel ## 13 systemPipeR/SPpolyriboseq master devel ## 14 systemPipeR/SPscrnaseq master devel ## html description ## 1 https://github.com/systemPipeR/SPchipseq Workflow Template ## 2 https://github.com/systemPipeR/SPriboseq Workflow Template ## 3 https://github.com/systemPipeR/SPrnaseq Workflow Template ## 4 https://github.com/systemPipeR/SPvarseq Workflow Template ## 5 https://github.com/systemPipeR/SPatacseq Workflow Template ## 6 https://github.com/systemPipeR/SPblast Workflow Template ## 7 https://github.com/systemPipeR/SPclipseq Workflow Template ## 8 https://github.com/systemPipeR/SPdenovo Workflow Template ## 9 https://github.com/systemPipeR/SPhic Workflow Template ## 10 https://github.com/systemPipeR/SPmetatrans Workflow Template ## 11 https://github.com/systemPipeR/SPmethylseq Workflow Template ## 12 https://github.com/systemPipeR/SPmirnaseq Workflow Template ## 13 https://github.com/systemPipeR/SPpolyriboseq Workflow Template ## 14 https://github.com/systemPipeR/SPscrnaseq Workflow Template This function returns the list of workflow templates available within the package and systemPipeR Project Organization on GitHub. Each one listed template can be created as described above.\n","categories":"","description":"","excerpt":"How to create a new Workflow Template SPRthis package expand usethis …","ref":"/sp/sprdata/newwf/","tags":"","title":"Rules to create a new Workflow Template"},{"body":"{spsComps} has some useful functions for exception catch, expression validation, and more. Even though we say they are Shiny server functions, but in fact most of them can be run without a Shiny server. We have designed the functions to detect whether there is a Shiny server, if not, they will work only in R console as well.\nload package library(spsComps) ## Loading required package: shiny library(magrittr) Server components shinyCatch basic The shinyCatch function is useful to capture exception. What we mean exception can be message, warning or error. For example\nshinyCatch({ message(\"This is a message\") warning(\"This is a warning\") stop(\"This is an error\") }) ## [SPS-INFO] 2021-12-15 01:36:28 This is a message ## ## [SPS-WARNING] 2021-12-15 01:36:28 This is a warning ## [SPS-ERROR] 2021-12-15 01:36:28 This is an error ## NULL You can see all 3 levels are captured inside the [SPS-XX] log on your console. If you run this in your Shiny app, a pop-up message with the corresponding log level message will be displayed in in app, like following:\nSo the message on both UI and console is called dual-end logging in SPS.\nShiny off Of course, if you do not want users to see the message, you can hide it by shiny = FALSE, but the message will be still logged on R console. Run the following on your own computer and watch the difference.\nlibrary(shiny) ui \u003c- fluidPage( spsDepend(\"toastr\") ) server \u003c- function(input, output, session) { shinyCatch({ stop(\"This is an error\") }, shiny = FALSE) } shinyApp(ui, server) get return shinyCatch is able to return you values if your expression has any. Imagine we have a function addNum that gives message, warning or error depeend on the input.\naddNum \u003c- function(num){ if (num \u003e 0) {message(num)} else if (num == 0) {warning(\"Num is 0\")} else {stop(\"less than 0\")} return(num + num) } value_a \u003c- shinyCatch({ addNum(1) }) ## [SPS-INFO] 2021-12-15 01:36:28 1 value_a ## [1] 2 value_b \u003c- shinyCatch({ addNum(0) }) ## [SPS-WARNING] 2021-12-15 01:36:28 Num is 0 value_b ## [1] 0 value_c \u003c- shinyCatch({ addNum(-1) }) ## [SPS-ERROR] 2021-12-15 01:36:28 less than 0 value_c ## NULL You can see at message and warning level, the expected value returned, and at error level, the return is NULL. So the following code value_c still runs and is not blocked by the error occurred in shinyCatch.\nBlocking level More often, if there is an error, we do want take the log in R console, inform the Shinyapp user and then stop the following code. In this case, we need to specify the blocking_level. So, default is \"none\", do not block and return NULL if there is an error, and you can choose \"error\", \"warning\" or \"message\".\n error: block downstream if the first error detected in shinyCatch warning: block downstream if the first error or warning detected in shinyCatch message: block downstream if the first error, warning or message detected in shinyCatch You can see the stringency becomes tighter: message \u003e warning \u003e error\nBlocking code will generate error, in order to have the Rmd rendered, we wrap the expression in try \ntry({ shinyCatch({ stop(\"error level is the most commonly used level\") }, blocking_level = \"error\") print(\"This will not be evaluated\") }) ## [SPS-ERROR] 2021-12-15 01:36:28 error level is the most commonly used level ## Error : try({ shinyCatch({ message(\"error level is the most commonly used level\") }, blocking_level = \"message\") print(\"This will not be evaluated either\") }) ## [SPS-INFO] 2021-12-15 01:36:28 error level is the most commonly used level ## ## Error : You can see the following print in both cases are not got evaluated.\nBlock reative The most useful case for shinyCatch is to use it in the Shiny reactive context. Most errors in shiny::reactive, shiny::observer, shiny::observeEvent, or shiny::renderXXX series function will crash the app. With shinyCatch, it will not. It “dual-logs” the error and stop downstream code.\nThe following example use shiny::reactiveConsole() to mock a Shiny server session\nshiny::reactiveConsole(TRUE) y \u003c- observe({ stop(\"an error from a function\") print(\"some other process\") }) ## Warning: Error in \u003cobserver\u003e: The value of x is ## 38: stop ## 37: \u003cobserver\u003e [#2] ## 35: contextFunc ## 34: env$runWith ## 27: ctx$run ## 26: run ## 7: flushCallback ## 6: FUN ## 5: lapply ## 4: ctx$executeFlushCallbacks ## 3: .getReactiveEnvironment()$flush ## 2: flushReact ## 1: \u003cAnonymous\u003e It crashes the app. However, if you use shinyCatch\nshiny::reactiveConsole(TRUE) y \u003c- observe({ shinyCatch({ stop(\"an error from a function\") }, blocking_level = \"error\") print(\"some other process\") }) ## [SPS-ERROR] 2021-03-02 22:13:05 an error from a function It only logs the error and prevent the downstream print to run. Now try following real Shiny apps and watch the difference:\n# with shinyCatch library(shiny) server \u003c- function(input, output, session) { observe({ shinyCatch({ stop(\"an error from a function\") }, blocking_level = \"error\") print(\"some other process\") }) } shinyApp(fluidPage(spsDepend(\"toastr\")), server) # without shinyCatch library(shiny) server \u003c- function(input, output, session) { observe({ stop(\"an error from a function\") print(\"some other process\") }) } shinyApp(fluidPage(spsDepend(\"toastr\")), server) spsValidate In data analysis, it is important we do some validations before the downstream process, like make a plot. It is epecially the case in Shiny apps. We cannot predict what the user inputs will be, like what kind of data they will use. Similar to shinyCatch, spsValidate is able to catch exceptions but more useful to handle validations. In addtion to shinyCatch functionalities, it will give users a success message if the expression goes through and return TRUE (shinyCatch returns the final expression value).\nshiny::reactiveConsole(TRUE) x \u003c- reactiveVal(10) y \u003c- observe({ spsValidate({ # have multiple validations in one expression if (x() == 1) stop(\"cannot be 1\") if (x() == 0) stop(\"cannot be 0\") if (x() \u003c 0) stop(\"less than 0\") }) message(\"The value of x is \", x()) }) x(0) x(-10) ## The value of x is 10 ## [ ERROR] 2021-03-02 22:36:16 cannot be 0 ## [ ERROR] 2021-03-02 22:36:16 less than 0 Try this real Shiny app:\nlibrary(shiny) ui \u003c- fluidPage( spsDepend(\"toastr\"), shiny::sliderInput( \"num\", \"change number\", min = -1, max = 2, value = 2, step = 1 ) ) server \u003c- function(input, output, session) { x \u003c- reactive(as.numeric(input$num)) y \u003c- observe({ spsValidate(vd_name = \"check numbers\", verbose = TRUE, { # have multiple validations in one expression if (x() == 1) stop(\"cannot be 1\") if (x() == 0) stop(\"cannot be 0\") if (x() \u003c 0) stop(\"less than 0\") }) message(\"The value of x is \", x()) }) } shinyApp(ui, server) You should see the success message like this:\nshinyCheckPkg Sometimes we want the app behave differently if users have certain packages installed. For example, if some packages are installed, we open up additional tabs on UI to allow more features. This can be done with the shinyCheckPkg function. This function has to run inside Shiny server, an alternative version to use without Shiny is from the spsUtil package, spsUtil::checkNameSpace\nUse it in Shiny server, specify the packages you want to check by different sources, like CRAN, Bioconductor, or github.\nshinyCheckPkg(session, cran_pkg = c(\"pkg1\", \"pkg2\"), bioc_pkg = \"bioxxx\", github = \"user1/pkg1\") It will return TRUE if all packages are installed, otherwise FALSE\nNow try this real example. We check if the ggplot99 package is installed, if yes we make a plot. It also combines the spsValidate function. You can have a better idea how these functions work.\nlibrary(shiny) ui \u003c- fluidPage( tags$label('Check if package \"pkg1\", \"pkg2\", \"bioxxx\", github package \"user1/pkg1\" are installed'), br(), actionButton(\"check_random_pkg\", \"check random_pkg\"), br(), spsHr(), tags$label('We can combine `spsValidate` to block server code to prevent crash if some packages are not installed.'), br(), tags$label('If \"shiny\" is installed, make a plot.'), br(), actionButton(\"check_shiny\", \"check shiny\"), br(), tags$label('If \"ggplot99\" is installed, make a plot.'), br(), actionButton(\"check_gg99\", \"check ggplot99\"), br(), plotOutput(\"plot_pkg\") ) server \u003c- function(input, output, session) { observeEvent(input$check_random_pkg, { shinyCheckPkg(session, cran_pkg = c(\"pkg1\", \"pkg2\"), bioc_pkg = \"bioxxx\", github = \"user1/pkg1\") }) observeEvent(input$check_shiny, { spsValidate(verbose = FALSE, { if(!shinyCheckPkg(session, cran_pkg = c(\"shiny\"))) stop(\"Install packages\") }) output$plot_pkg \u003c- renderPlot(plot(1)) }) observeEvent(input$check_gg99, { spsValidate({ if(!shinyCheckPkg(session, cran_pkg = c(\"ggplot99\"))) stop(\"Install packages\") }) output$plot_pkg \u003c- renderPlot(plot(99)) }) } shinyApp(ui, server) You should see something like this if there is any missing package:\nIn-line operation In-place operations like i += 1, i -= 1 is not support in R. These functions implement these operations in R. This set of functions will apply this kind of operations on [shiny::reactiveVal] objects.\nreactiveConsole(TRUE) rv \u003c- reactiveVal(0) incRv(rv) # add 1 rv() ## [1] 1 incRv(rv) # add 1 rv() ## [1] 2 incRv(rv, -1) # minus 1 rv() ## [1] 1 incRv(rv, -1) # minus 1 rv() ## [1] 0 rv2 \u003c- reactiveVal(1) multRv(rv2) # times 2 rv2() ## [1] 2 multRv(rv2) # times 2 rv2() ## [1] 4 diviRv(rv2) # divide 2 rv2() ## [1] 2 diviRv(rv2) # divide 2 rv2() ## [1] 1 reactiveConsole(FALSE) If you are looking for inline operations on normal R objects or shiny::reactiveValues, check spsUtil\n","categories":"","description":"","excerpt":"{spsComps} has some useful functions for exception catch, expression …","ref":"/sps/dev/spscomps/server/","tags":"","title":"Server functions"},{"body":"document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i How to connect CWL description files within systemPipeR This section will demonstrate how to connect CWL parameters files to create workflows. In addition, we will show how the workflow can be easily scalable with systemPipeR.\nSYSargsList container stores all the information and instructions needed for processing a set of input files with a single or many command-line steps within a workflow (i.e. several components of the software or several independent software tools). The SYSargsList object is created and fully populated with the SYSargsList construct function. Full documentation of SYSargsList management instances can be found here and here.\nThe following imports a .cwl file (here example.cwl) for running the echo Hello World! example.\nHW \u003c- SYSargsList(wf_file = \"example/workflow_example.cwl\", input_file = \"example/example_single.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\")) HW ## Instance of 'SYSargsList': ## WF Steps: ## 1. Step_x --\u003e Status: Pending ## Total Files: 1 | Existing: 0 | Missing: 1 ## 1.1. echo ## cmdlist: 1 | Pending: 1 ## cmdlist(HW) ## $Step_x ## $Step_x$defaultid ## $Step_x$defaultid$echo ## [1] \"echo Hello World! \u003e results/M1.txt\" However, we are limited to run just one command-line or one sample in this example. To scale the command-line over many samples, a simple solution offered by systemPipeR is to provide a variable for each of the parameters that we want to run with multiple samples.\nLet’s explore the example:\ndir_path \u003c- system.file(\"extdata/cwl\", package = \"systemPipeR\") yml \u003c- yaml::read_yaml(file.path(dir_path, \"example/example.yml\")) yml ## $message ## [1] \"_STRING_\" ## ## $SampleName ## [1] \"_SAMPLE_\" ## ## $results_path ## $results_path$class ## [1] \"Directory\" ## ## $results_path$path ## [1] \"./results\" For the message and SampleName parameter, we are passing a variable connecting with a third file called targets.\nNow, let’s explore the targets file structure:\ntargetspath \u003c- system.file(\"extdata/cwl/example/targets_example.txt\", package = \"systemPipeR\") read.delim(targetspath, comment.char = \"#\") ## Message SampleName ## 1 Hello World! M1 ## 2 Hello USA! M2 ## 3 Hello Bioconductor! M3 The targets file defines all input files or values and sample ids of an analysis workflow. For this example, we have defined a string message for the echo command-line tool, in the first column that will be evaluated, and the second column is the SampleName id for each one of the messages. Any number of additional columns can be added as needed.\nUsers should note here, the usage of targets files is optional when using systemPipeR's new CWL interface. Since for organizing experimental variables targets files are extremely useful and user-friendly. Thus, we encourage users to keep using them.\nHow to connect the parameter files and targets file information? The constructor function creates an SYSargsList S4 class object connecting three input files:\n CWL command-line specification file (wf_file argument); Input variables (input_file argument); Targets file (targets argument). As demonstrated above, the latter is optional for workflow steps lacking input files. The connection between input variables (here defined by input_file argument) and the targets file are defined under the inputvars argument. A named vector is required, where each element name needs to match with column names in the targets file, and the value must match the names of the .yml variables. This is used to replace the CWL variable and construct all the command-line for that particular step.\nThe variable pattern _XXXX_ is used to distinguish CWL variables that target columns will replace. This pattern is recommended for consistency and easy identification but not enforced.\nThe following imports a .cwl file (same example demonstrated above) for running the echo Hello World example. However, now we are connecting the variable defined on the .yml file with the targets file inputs.\nHW_mul \u003c- SYSargsList(step_name = \"echo\", targets = targetspath, wf_file = \"example/workflow_example.cwl\", input_file = \"example/example.yml\", dir_path = dir_path, inputvars = c(Message = \"_STRING_\", SampleName = \"_SAMPLE_\")) HW_mul ## Instance of 'SYSargsList': ## WF Steps: ## 1. echo --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 1.1. echo ## cmdlist: 3 | Pending: 3 ## cmdlist(HW_mul) ## $echo ## $echo$M1 ## $echo$M1$echo ## [1] \"echo Hello World! \u003e results/M1.txt\" ## ## ## $echo$M2 ## $echo$M2$echo ## [1] \"echo Hello USA! \u003e results/M2.txt\" ## ## ## $echo$M3 ## $echo$M3$echo ## [1] \"echo Hello Bioconductor! \u003e results/M3.txt\" WConnectivity between CWL param files and targets files.\nCreating the CWL param files In the next two sections, we will discuss how to use createParam from SPR to create CWL param files. In createParam, there are two versions of syntax:\n version 1: pseudo-bash script format, easy to write version 2: ; separated format, has more rules, but support a lot more functionalities. Contribute new CWL files to systemPipeR systemPipeR organizes a collection of CWL CommandLineTool and Workflow descriptions for a variety of applications, that can be found on Github cwl_collection.\nIf you have new cwl files would like to add to this collection, submit a pull request.\nAfter adding, new files will automatically trigger a push to systemPipeRdata (SPRdata) and systemPipeR (SPR) repositories master branch shortly.\n","categories":"","description":"","excerpt":"document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/cwl/cwl_and_spr/","tags":"","title":"SPR and CWL"},{"body":"","categories":"","description":"","excerpt":"","ref":"/sp/spt/","tags":"","title":"systemPipeTools"},{"body":"","categories":"","description":"","excerpt":"","ref":"/spr_wf/templates/varseq/","tags":"","title":"VARseq"},{"body":"","categories":"","description":"","excerpt":"","ref":"/spr_wf/templates/chipseq/","tags":"","title":"ChIP-Seq"},{"body":"suppressPackageStartupMessages({ library(systemPipeR) }) createParam by default uses the version 1 syntax, so there is no need to provide additional version argument. We will see in the next section how to use syntaxVersion to change to the v2 syntax.\nInput Imagine we want to create CWL for command:\nhisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz To use createParam, simply write the command in a pseudo-bash script format:\ncommand \u003c- \" hisat2 \\ -S \u003cF, out: ./results/M1A.sam\u003e \\ -x \u003cF: ./data/tair10.fasta\u003e \\ -k \u003cint: 1\u003e \\ -min-intronlen \u003cint: 30\u003e \\ -max-intronlen \u003cint: 3000\u003e \\ -threads \u003cint: 4\u003e \\ -U \u003cF: ./data/SRR446027_1.fastq.gz\u003e \" Format What does the string above mean?\n First line is the base command. Each line is an argument with its default value.\n For argument lines (starting from the second line), any word before the first space with leading - or -- in each will be treated as a prefix, like -S or --min. Any line without this first word will be treated as no prefix.\n All defaults are placed inside \u003c...\u003e.\n First argument is the input argument type. “File” (or “F”) for files, “int” for integers, “string” for character strings.\n Optional: use the keyword out followed the type with a , comma separation to indicate if this argument is also an CWL output.\n Then, use : to separate keywords and default values, any non-space value after the : will be treated as the default value.\n If any argument has no default value, just a flag, like --verbose, there is no need to add any \u003c...\u003e\n run createParam Function The string above that we just defined will be used as input for createParam.\nIf the format is correct, after parsing, the function will print the three components of the cwl file: - BaseCommand: Specifies the program to execute. - Inputs: Defines the input parameters of the process. - Outputs: Defines the parameters representing the output of the process.\nThe fourth printed component is the translated command-line from CWL.\nIf in you are using R interactively, the function will verify that everything is correct and will ask you to proceed. Here, the user can answer “no” and provide more information at the string level. Another question is to save the param created here.\nIf running the workflow in non-interactive mode, the createParam function will consider “yes” and returning the container.\ncmd \u003c- createParam(command, writeParamFiles = FALSE) ## *****BaseCommand***** ## hisat2 ## *****Inputs***** ## S: ## type: File ## preF: -S ## yml: ./results/M1A.sam ## x: ## type: File ## preF: -x ## yml: ./data/tair10.fasta ## k: ## type: int ## preF: -k ## yml: 1 ## min-intronlen: ## type: int ## preF: -min-intronlen ## yml: 30 ## max-intronlen: ## type: int ## preF: -max-intronlen ## yml: 3000 ## threads: ## type: int ## preF: -threads ## yml: 4 ## U: ## type: File ## preF: -U ## yml: ./data/SRR446027_1.fastq.gz ## *****Outputs***** ## output1: ## type: File ## value: ./results/M1A.sam ## *****Parsed raw command line***** ## hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz If the user chooses not to save the param files on the above operation, later, one can use the writeParamFiles function.\nwriteParamFiles(cmd, overwrite = TRUE) ## Written content of 'commandLine' to file: ## param/cwl/hisat2/hisat2.cwl ## Written content of 'commandLine' to file: ## param/cwl/hisat2/hisat2.yml By default, the files will be saved inside ./param/cwl/base_cmd. It means a child folder under param then cwl, and create a new folder named by the base command of the command-line.\nAccess and edit param files Print a component printParam(cmd, position = \"baseCommand\") ## Print a baseCommand section ## *****BaseCommand***** ## hisat2 printParam(cmd, position = \"outputs\") ## *****Outputs***** ## output1: ## type: File ## value: ./results/M1A.sam printParam(cmd, position = \"inputs\", index = 1:2) ## Print by index ## *****Inputs***** ## S: ## type: File ## preF: -S ## yml: ./results/M1A.sam ## x: ## type: File ## preF: -x ## yml: ./data/tair10.fasta printParam(cmd, position = \"inputs\", index = -1:-2) ## Negative indexing printing to exclude certain indices in a position ## *****Inputs***** ## k: ## type: int ## preF: -k ## yml: 1 ## min-intronlen: ## type: int ## preF: -min-intronlen ## yml: 30 ## max-intronlen: ## type: int ## preF: -max-intronlen ## yml: 3000 ## threads: ## type: int ## preF: -threads ## yml: 4 ## U: ## type: File ## preF: -U ## yml: ./data/SRR446027_1.fastq.gz Subsetting the command-line cmd2 \u003c- subsetParam(cmd, position = \"inputs\", index = 1:2, trim = TRUE) ## *****Inputs***** ## S: ## type: File ## preF: -S ## yml: ./results/M1A.sam ## x: ## type: File ## preF: -x ## yml: ./data/tair10.fasta ## *****Parsed raw command line***** ## hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta cmdlist(cmd2) ## $defaultid ## $defaultid$hisat2 ## [1] \"hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta\" cmd2 \u003c- subsetParam(cmd, position = \"inputs\", index = c(\"S\", \"x\"), trim = TRUE) ## *****Inputs***** ## S: ## type: File ## preF: -S ## yml: ./results/M1A.sam ## x: ## type: File ## preF: -x ## yml: ./data/tair10.fasta ## *****Parsed raw command line***** ## hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta cmdlist(cmd2) ## $defaultid ## $defaultid$hisat2 ## [1] \"hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta\" Replacing a existing argument in the command-line cmd3 \u003c- replaceParam(cmd, \"base\", index = 1, replace = list(baseCommand = \"bwa\")) ## Replacing baseCommand ## *****BaseCommand***** ## bwa ## *****Parsed raw command line***** ## bwa -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz cmdlist(cmd3) ## $defaultid ## $defaultid$hisat2 ## [1] \"bwa -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz\" new_inputs \u003c- new_inputs \u003c- list( \"new_input1\" = list(type = \"File\", preF=\"-b\", yml =\"myfile\"), \"new_input2\" = \"-L \u003cint: 4\u003e\" ) cmd4 \u003c- replaceParam(cmd, \"inputs\", index = 1:2, replace = new_inputs) ## Replacing inputs ## *****Inputs***** ## new_input1: ## type: File ## preF: -b ## yml: myfile ## new_input2: ## type: int ## preF: -L ## yml: 4 ## k: ## type: int ## preF: -k ## yml: 1 ## min-intronlen: ## type: int ## preF: -min-intronlen ## yml: 30 ## max-intronlen: ## type: int ## preF: -max-intronlen ## yml: 3000 ## threads: ## type: int ## preF: -threads ## yml: 4 ## U: ## type: File ## preF: -U ## yml: ./data/SRR446027_1.fastq.gz ## *****Parsed raw command line***** ## hisat2 -b myfile -L 4 -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz cmdlist(cmd4) ## $defaultid ## $defaultid$hisat2 ## [1] \"hisat2 -b myfile -L 4 -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz\" Adding new arguments newIn \u003c- new_inputs \u003c- list( \"new_input1\" = list(type = \"File\", preF=\"-b1\", yml =\"myfile1\"), \"new_input2\" = list(type = \"File\", preF=\"-b2\", yml =\"myfile2\"), \"new_input3\" = \"-b3 \u003cF: myfile3\u003e\" ) cmd5 \u003c- appendParam(cmd, \"inputs\", index = 1:2, append = new_inputs) ## Replacing inputs ## *****Inputs***** ## S: ## type: File ## preF: -S ## yml: ./results/M1A.sam ## x: ## type: File ## preF: -x ## yml: ./data/tair10.fasta ## k: ## type: int ## preF: -k ## yml: 1 ## min-intronlen: ## type: int ## preF: -min-intronlen ## yml: 30 ## max-intronlen: ## type: int ## preF: -max-intronlen ## yml: 3000 ## threads: ## type: int ## preF: -threads ## yml: 4 ## U: ## type: File ## preF: -U ## yml: ./data/SRR446027_1.fastq.gz ## new_input1: ## type: File ## preF: -b1 ## yml: myfile1 ## new_input2: ## type: File ## preF: -b2 ## yml: myfile2 ## new_input3: ## type: File ## preF: -b3 ## yml: myfile3 ## *****Parsed raw command line***** ## hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz -b1 myfile1 -b2 myfile2 -b3 myfile3 cmdlist(cmd5) ## $defaultid ## $defaultid$hisat2 ## [1] \"hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz -b1 myfile1 -b2 myfile2 -b3 myfile3\" cmd6 \u003c- appendParam(cmd, \"inputs\", index = 1:2, after=0, append = new_inputs) ## Replacing inputs ## *****Inputs***** ## new_input1: ## type: File ## preF: -b1 ## yml: myfile1 ## new_input2: ## type: File ## preF: -b2 ## yml: myfile2 ## new_input3: ## type: File ## preF: -b3 ## yml: myfile3 ## S: ## type: File ## preF: -S ## yml: ./results/M1A.sam ## x: ## type: File ## preF: -x ## yml: ./data/tair10.fasta ## k: ## type: int ## preF: -k ## yml: 1 ## min-intronlen: ## type: int ## preF: -min-intronlen ## yml: 30 ## max-intronlen: ## type: int ## preF: -max-intronlen ## yml: 3000 ## threads: ## type: int ## preF: -threads ## yml: 4 ## U: ## type: File ## preF: -U ## yml: ./data/SRR446027_1.fastq.gz ## *****Parsed raw command line***** ## hisat2 -b1 myfile1 -b2 myfile2 -b3 myfile3 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz cmdlist(cmd6) ## $defaultid ## $defaultid$hisat2 ## [1] \"hisat2 -b1 myfile1 -b2 myfile2 -b3 myfile3 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz\" Editing output param new_outs \u003c- list( \"sam_out\" = \"\u003cF: $(inputs.results_path)/test.sam\u003e\" ) cmd7 \u003c- replaceParam(cmd, \"outputs\", index = 1, replace = new_outs) ## Replacing outputs ## *****Outputs***** ## sam_out: ## type: File ## value: $(inputs.results_path)/test.sam ## *****Parsed raw command line***** ## hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 -min-intronlen 30 -max-intronlen 3000 -threads 4 -U ./data/SRR446027_1.fastq.gz output(cmd7) ## $defaultid ## $defaultid$hisat2 ## [1] \"./results/test.sam\" ","categories":"","description":"","excerpt":"suppressPackageStartupMessages({ library(systemPipeR) }) createParam …","ref":"/sp/spr/cwl/create_param_v1/","tags":"","title":"createParam V1"},{"body":"document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i About this section In this section, we will discuss following topics:\n How to create SPR data analysis projects. How to build workflow step by step interactively or use use a template as starting point. After step design, how to run a workflow. After workflow finished running, how we can check the status, visualize the workflow. Different options for managing the workflow, e.g. resume, restart, overwrite a SPR project. How to explore the workflow object (methods). Finally, how to generate some data analysis reports. Project initialization To create a workflow within systemPipeR, we can start by defining an empty container and checking the directory structure:\nsal \u003c- SPRproject() ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' Internally, SPRproject function will create a hidden folder called .SPRproject, by default, to store all the log files. A YAML file, here called SYSargsList.yml, has been created, which initially contains the basic location of the project structure; however, every time the workflow object sal is updated in R, the new information will also be store in this flat-file database for easy recovery. If you desire different names for the logs folder and the YAML file, these can be modified as follows:\nsal \u003c- SPRproject(logs.dir = \".SPRproject\", sys.file = \".SPRproject/SYSargsList.yml\") Also, this function will check and/or create the basic folder structure if missing, which means data, param, and results folder, as described here. If the user wants to use a different names for these directories, can be specified as follows:\nsal \u003c- SPRproject(data = \"data\", param = \"param\", results = \"results\") It is possible to separate all the R objects created within the workflow analysis from the current environment. SPRproject function provides the option to create a new environment, and in this way, it is not overwriting any object you may want to have at your current section.\nsal \u003c- SPRproject(envir = new.env()) In this stage, the object sal is a empty container, except for the project information. The project information can be accessed by the projectInfo method:\nsal ## Instance of 'SYSargsList': ## No workflow steps added projectInfo(sal) ## $project ## [1] \"/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run\" ## ## $data ## [1] \"data\" ## ## $param ## [1] \"param\" ## ## $results ## [1] \"results\" ## ## $logsDir ## [1] \".SPRproject\" ## ## $sysargslist ## [1] \".SPRproject/SYSargsList.yml\" Also, the length function will return how many steps this workflow contains, and in this case, it is empty, as follow:\nlength(sal) ## [1] 0 Workflow Design systemPipeR workflows can be designed and built from start to finish with a single command, importing from an R Markdown file or stepwise in interactive mode from the R console. In the next section, we will demonstrate how to build the workflow in an interactive mode, and in the following section, we will show how to build from a file.\nNew workflows are constructed, or existing ones modified, by connecting each step via appendStep method. Each SYSargsList instance contains instructions needed for processing a set of input files with a specific command-line and the paths to the corresponding outfiles generated.\nThe constructor function Linewise is used to build the R code-based step. For more details about this S4 class container, see here.\nBuild workflow interactive This tutorial shows a straightforward example for describing and explaining all main features available within systemPipeR to design, build, manage, run, and visualize the workflow. In summary, we are exporting a dataset to multiple files, compressing and decompressing each one of the files, importing to R, and finally performing a statistical analysis.\nIn the previous section, we initialize the project by building the sal object. Until this moment, the container has no steps:\nsal ## Instance of 'SYSargsList': ## No workflow steps added In the next subsection, we will discuss how to populate the object created with the first step in the workflow interactively.\nSubsections ","categories":"","description":"","excerpt":"document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/sp_run/","tags":"","title":"Design and run Workflows"},{"body":"The {drawer} package offers an interactive image editing tool that can be added as part of the HTML in Shiny, R markdown or any type of HTML document. Often times, plots, photos are embedded in the web application/file. {drawer} can take screenshots of these image-like elements, or any part of the HTML document and send to an image editing space called “canvas” to allow users immediately edit the screenshot(s) within the same document. Users can quickly combine, compare different screenshots, upload their own images and maybe make a scientific figure.\nFeatures {drawer} is built with 99% javascript + HTML + CSS, there is no need to have a Shiny server or any other types of server in the back-end. That’s why you can use it in any HTML document. All you need is a modern web browser, like Chrome or Firefox (IE will not work). Shiny and R markdown compatible. Screenshot any element in the page and edit in canvas or download it png or jpg Drag and upload your own images. Drawer UI screenshot Installation Read the developer tools main page, not repeating here.\nFunctions reference manual Please read the reference manuals for details of every function.\nSome video demos Basic looking and options Capture Use the capture buttons to capture plots, images and other elements in the same document.\n Add text Upload your own images You can upload one or multiple your own images at once.\n Browser support {drawer} only works on recent browsers versions, like Chrome, latest Edge, Firefox. IE is not supported (IE is not my friend). Also, some browser privacy extensions will block javascript and HTML5 canvas fingerprint. This will cause the screenshot to be blank. {drawer} does not collect any user information from you.\n","categories":"","description":"","excerpt":"The {drawer} package offers an interactive image editing tool that can …","ref":"/sps/dev/drawer/","tags":"","title":"drawer"},{"body":"\n{drawer} is compatible with R markdown. Instructions and details are all included in these Rmd demos:\n Demo Source code With instructions link Pure drawer link ","categories":"","description":"","excerpt":"\n{drawer} is compatible with R markdown. Instructions and details are …","ref":"/sps/dev/drawer/rmd/","tags":"","title":"drawer in Rmarkdown"},{"body":"systemPipeShiny systemPipeShiny: An Interactive Framework for Workflow Management and Visualization - F1000 Publication{blk} systemPipeR systemPipeR: a generic workflow environment federates R with command-line software - F1000 Publication{blk} ","categories":"","description":"","excerpt":"systemPipeShiny systemPipeShiny: An Interactive Framework for …","ref":"/outreach/posters/","tags":"","title":"Posters"},{"body":"Quick {ggplot} module This module enables you to quickly upload datasets and make a {ggplot{blk}} in a second by using some functionalities from {Esquisse{blk}}.\nUpload data Upload data The first thing you come to this module is to upload a tabular data file. You can choose to use the example or upload your own. The example is just the iris data. 1.1. If you choose to upload, there will be a upload button where you need to choose your own file. By default, it assumes you upload a “.csv” file with “#” as comments. If not you can choose the file delimiter and comment character. You can view your uploaded data and use the boxes below each column name to perform some filters, but you are not allowed to edit the data. If everything looks good, you can submit to proceed to the plot making panel. Make a plot Make a plot Figure 8 Quick ggplot\n Provide a tabular data table by uploading or use example. Drag variables from into different ggplot aesthetic boxes to make a ggplot. Change to different plot types. Customize other different plotting options. For a more specific guide, read Esquisse official guide{blk}.\n","categories":"","description":"","excerpt":"Quick {ggplot} module This module enables you to quickly upload …","ref":"/sps/modules/ggplot/","tags":"","title":"Quick ggplot"},{"body":"SPS example usage To start with SPS after installation:\nLoad package Load the systemPipeShiny package in your R session.\nlibrary(systemPipeShiny) ## Loading required package: shiny ## Loading required package: spsUtil ## Loading required package: spsComps ## Loading required package: drawer Initialize SPS project Before launching the SPS application, a project environment needs to be created with the following command.\nspsInit() For this demo, the project directory structure is written to a temporary directory on a user’s system. For a real project, it should be written to a defined and user controlled location on a system rather than a temporary directory.\nsps_tmp_dir \u003c- tempdir() spsInit(app_path = sps_tmp_dir, change_wd = FALSE, project_name = \"SPSProject\") ## [SPS-INFO] 2021-12-14 23:53:38 Start to create a new SPS project ## [SPS-INFO] 2021-12-14 23:53:38 Create project under /tmp/RtmpGAaU3K/SPSProject ## [SPS-INFO] 2021-12-14 23:53:38 Now copy files ## [SPS-INFO] 2021-12-14 23:53:38 Create SPS database ## [SPS-INFO] 2021-12-14 23:53:38 Created SPS database method container ## [SPS-INFO] 2021-12-14 23:53:38 Creating SPS db... ## [SPS-DANGER] 2021-12-14 23:53:38 Done, Db created at '/tmp/RtmpGAaU3K/SPSProject/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-12-14 23:53:38 Key md5 90499a61aeea98b338debf236bd5aef4 ## [SPS-INFO] 2021-12-14 23:53:38 SPS project setup done! sps_dir \u003c- file.path(sps_tmp_dir, \"SPSProject\") SPS project structure The file and directory structure of an SPS project is organized as follows.\n SPS_xx/ ├── server.R | ├── global.R | Most important server, UI and global files, unless special needs, `global.R` is the only file you need to edit manually ├── ui.R | ├── deploy.R | Deploy helper file ├── config | Important app config files. Do not edit them by hand if you don't know │ ├── sps.db | SPS database │ ├── sps_options.yaml | SPS default option list │ └── tabs.csv | SPS tab registration information ├── data | App example data files │ ├── xx.csv ├── R | All SPS additional tab files, helper R function, interactive guides files │ ├── tab_xx.R ├── README.md ├── results | Not in use for this current version, but you can store some data been generated from the app │ └── README.md └── www | Internet resources ├── css | CSS files │ └── sps.css ├── img | App image resources │ └── xx.png ├── js | Javascripts │ └── xx.js ├── loading_themes | Loading screen files │ └── xx.html └── plot_list | Image files for custom visualization tab thumbnails └── plot_xx.jpg Launch SPS By default, the working directory will be set inside the project folder automatically. To launch the SPS Shiny application, one only needs to execute the following command.\nshiny::runApp() Alternatively, when using RStudio one can click the Run App button in the top right corner.\nAfter the SPS app has been launched, clicking the “Continue to app” button on the welcome screen will open the main dashboard (Fig.2).\n Figure 2A: SPS welcome page\nClick on one of the big icons on the welcome page to choose for the module/tool you want to use, or use the lefe sidebar to navigate to different tabs.\nSPS tabs Within the functional categories, SPS functions are modularized into sub-components, here referred to as SPS tabs that are similar to menu tabs in other GUI applications that organize related and inter-connected functionalies into groups. On the backend, SPS tabs are based on Shiny modules, that are stored in separate files. This modular structure is highly extensible and greatly simplifies the design of new SPS tabs by both users and/or developers. Details about extending existing tabs and designing new ones are provided in Manage tabs section on our website.\n Figure 2B: Screenshot of SPS' tabs.\n Welcome screen. Module tabs. User defined custom tabs. The Canvas tab. All SPS tabs has this description on top. It is highly recommend to click here to expand and read the full the description for the first time. In addition, in Rstudio the global.R file will be automatically opened when the SPS project is created. Custom changes can be made inside this file before the app launches. Later we will discuss how to change and create new custom tabs and change other settings in advanced sections.\n","categories":"","description":"","excerpt":"SPS example usage To start with SPS after installation:\nLoad package …","ref":"/sps/quick_start/","tags":"","title":"Quick start"},{"body":" suppressPackageStartupMessages({ library(systemPipeR) }) Until this point, you have learned how to create a SPR workflow interactively or use a template to import/update the workflow. Next, we will learn how to run the workflow and manage the workflow.\nFirst let’s set up the workflow using the example workflow template. For real production purposes, we recommend you to check out the complex templates over here.\nFor demonstration purposes here, we still use the simple workflow.\nsal \u003c- SPRproject() ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' sal \u003c- importWF(sal, file_path = system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\")) ## Reading Rmd file ## ## ---- Actions ---- ## Checking chunk eval values ## Checking chunk SPR option ## Ignore non-SPR chunks: 17 ## Parse chunk code ## Checking preprocess code for each step ## No preprocessing code for SPR steps found ## Now importing step 'load_library' ## Now importing step 'export_iris' ## Now importing step 'gzip' ## Now importing step 'gunzip' ## Now importing step 'stats' ## Now back up current Rmd file as template for `renderReport` ## Template for renderReport is stored at ## /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/workflow_template.Rmd ## Edit this file manually is not recommended ## import done sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## Before running It is good to check if the command-line tools are installed before running the workflow. To do so, we can use the tryCMD function.\ntryCMD(command=\"R\") ## [1] \"All set up, proceed!\" tryCMD(command=\"hisat2\") ## [1] \"All set up, proceed!\" tryCMD(command=\"blastp\") ## ERROR: ## blastp : COMMAND NOT FOUND. ## Please make sure to configure your PATH environment variable according to the software in use. In examples above, installed tools will have a message \"All set up, proceed!\", and not installed tool will have an error message, like the blastp example above.\nIf you see the error message:\n Check if the tool is really installed, by typing the same command from a terminal. If you cannot call it even from a terminal, you need to (re)install.\n If the tool is available in terminal but you see the error message in tryCMD. It is mostly likely due to the path problem. Make sure you export the path. Or try to use following to set it up in R:\nold_path \u003c- Sys.getenv(\"PATH\") Sys.setenv(PATH = paste(old_path, \"path/to/tool_directory\", sep = \":\")) Start running To run the workflow, call the runWF function which will execute all steps in the workflow container.\nsal \u003c- runWF(sal) ## Running Step: load_library ## Running Session: Management ## | | | 0% | |======================================================================| 100% ## Step Status: Success ## Running Step: export_iris ## Running Session: Management ## | | | 0% | |======================================================================| 100% ## Step Status: Success ## Running Step: gzip ## Running Session: Management ## | | | 0% | |======================= | 33% | |=============================================== | 67% | |======================================================================| 100% ## ---- Summary ---- ## Targets Total_Files Existing_Files Missing_Files gzip ## SE SE 1 1 0 Success ## VE VE 1 1 0 Success ## VI VI 1 1 0 Success ## ## Step Status: Success ## Running Step: gunzip ## Running Session: Management ## | | | 0% | |======================= | 33% | |=============================================== | 67% | |======================================================================| 100% ## ---- Summary ---- ## Targets Total_Files Existing_Files Missing_Files gunzip ## SE SE 1 1 0 Success ## VE VE 1 1 0 Success ## VI VI 1 1 0 Success ## ## Step Status: Success ## Running Step: stats ## Running Session: Management ## | | | 0% | |======================================================================| 100% ## Step Status: Success ## Done with workflow running, now consider rendering logs \u0026 reports ## To render logs, run: sal \u003c- renderLogs(sal) ## From command-line: Rscript -e \"sal = systemPipeR::SPRproject(resume = TRUE); sal = systemPipeR::renderLogs(sal)\" ## To render reports, run: sal \u003c- renderReport(sal) ## From command-line: Rscript -e \"sal= s ystemPipeR::SPRproject(resume = TRUE); sal = systemPipeR::renderReport(sal)\" ## This message is displayed once per R session sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Success ## 2. export_iris --\u003e Status: Success ## 3. gzip --\u003e Status: Success ## Total Files: 3 | Existing: 3 | Missing: 0 ## 3.1. gzip ## cmdlist: 3 | Success: 3 ## 4. gunzip --\u003e Status: Success ## Total Files: 3 | Existing: 3 | Missing: 0 ## 4.1. gunzip ## cmdlist: 3 | Success: 3 ## 5. stats --\u003e Status: Success ## We can see the workflow status changed from pending to Success\nRun selected steps This function allows the user to choose one or multiple steps to be executed using the steps argument. However, it is necessary to follow the workflow dependency graph. If a selected step depends on a previous step(s) that was not executed, the execution will fail.\nsal \u003c- runWF(sal, steps = c(1,3)) ## Running Step: load_library ## Running Session: Management ## | | | 0% | |======================================================================| 100% ## Step Status: Success ## Skipping Step: export_iris ## Running Step: gzip ## Running Session: Management ## | | | 0% | |======================= | 33% | |=============================================== | 67% | |======================================================================| 100% ## ---- Summary ---- ## Targets Total_Files Existing_Files Missing_Files gzip ## SE SE 1 1 0 Success ## VE VE 1 1 0 Success ## VI VI 1 1 0 Success ## ## Step Status: Success ## Skipping Step: gunzip ## Skipping Step: stats We do not see any problem here because we have finished the entire workflow running previously. So all depedency satisfies. Let’s clean the workflow and start from scratch to see what will happen if one or more depedency is not met and we are trying to run some selected steps.\nsal \u003c- SPRproject(overwrite = TRUE) ## Recreating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' sal \u003c- importWF(sal, file_path = system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\")) ## Reading Rmd file ## ## ---- Actions ---- ## Checking chunk eval values ## Checking chunk SPR option ## Ignore non-SPR chunks: 17 ## Parse chunk code ## Checking preprocess code for each step ## No preprocessing code for SPR steps found ## Now importing step 'load_library' ## Now importing step 'export_iris' ## Now importing step 'gzip' ## Now importing step 'gunzip' ## Now importing step 'stats' ## Now back up current Rmd file as template for `renderReport` ## Template for renderReport is stored at ## /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/workflow_template.Rmd ## Edit this file manually is not recommended ## import done sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## sal \u003c- runWF(sal, steps = c(1,3)) ## Running Step: load_library ## Running Session: Management ## | | | 0% | |======================================================================| 100% ## Step Status: Success ## Skipping Step: export_iris ## Previous steps: ## export_iris ## have been not executed yet. We can see the workflow step 3 is not run because of the dependency problem: \u003e ## export_iris \u003e ## have been not executed yet.\noptional steps By default all steps are 'mandatory', but you can change it to 'optional'\nSYSargsList(..., run_step = 'optional') # or LineWise(..., run_step = 'optional') When workflow is run by runWF, default will run all steps 'ALL', but you can choose to only run mandatory steps 'mandatory' or optional steps 'optional'.\n# default sal \u003c- runWF(sal, run_step = \"ALL\") # only mandatory sal \u003c- runWF(sal, run_step = \"mandatory\") # only optional sal \u003c- runWF(sal, run_step = \"optional\") Force to run steps Forcing the execution of the steps, even if the status of the step is 'Success' and all the expected outfiles exists.\nsal \u003c- runWF(sal, force = TRUE, ... = ) Another feature of the runWF function is ignoring all the warnings and errors and running the workflow by the arguments warning.stop and error.stop, respectively.\nsal \u003c- runWF(sal, warning.stop = FALSE, error.stop = TRUE, ...) To force the step to run without checking the dependency, we can use ignore.dep = TRUE. For example, let’s run the step 3 that could not be run because of dependency problem.\nsal \u003c- runWF(sal, steps = 3, ignore.dep = TRUE) ## Skipping Step: load_library ## Skipping Step: export_iris ## Running Step: gzip ## Running Session: Management ## | | | 0% | |======================= | 33% | |=============================================== | 67% | |======================================================================| 100% ## ---- Summary ---- ## Targets Total_Files Existing_Files Missing_Files gzip ## SE SE 1 0 1 Error ## VE VE 1 0 1 Error ## VI VI 1 0 1 Error ## Error in runWF(sal, steps = 3, ignore.dep = TRUE): Caught an error, stop workflow! We can see the workflow failed, because required files from step 2 are missing and we jumped directly to step 3. Therefore, skip dependency is possible in SPR but not recommended.\n Workflow envirnment When the project was initialized by SPRproject function, it was created an environment for all object to store during the workflow preprocess code execution or Linewise R code execution. This environment can be accessed as follows:\nviewEnvir(sal) ## \u003cenvironment: 0x557918f5c620\u003e ## [1] \"df\" \"plot\" \"stats\" We can see there are \"df\", \"plot\", \"stats\" 3 objects, and they are created during the step 5 Linewise code execution. To access these variables interactive from your global environment, use copyEnvir method.\ncopyEnvir(sal, c(\"df\", \"plot\")) ## \u003cenvironment: 0x557918f5c620\u003e ## Copying to 'new.env': ## df, plot exists(\"df\", envir = globalenv()) ## [1] TRUE exists(\"plot\", envir = globalenv()) ## [1] TRUE Now we see, they are in our global enviornment, and we are free to do other operations on them.\nSave envirnment The workflow execution allows to save this environment for future recovery:\nsal \u003c- runWF(sal, saveEnv = TRUE) Depending on what variable you have saved in the enviorment, it can become expensive (take much space and slow to load back in resume).\n Parallelization on clusters This section of the tutorial provides an introduction to the usage of the systemPipeR features on a cluster.\nSo far, all workflow steps are run in the same computer as we manage the workflow instance. This is called running in the management session. Alternatively, the computation can be greatly accelerated by processing many files in parallel using several compute nodes of a cluster, where a scheduling/queuing system is used for load balancing. This is called running in the compute session. The behavior controlled by the run_session argument in SYSargsList.\nSYSargsList(..., run_session = \"management\") # or SYSargsList(..., run_session = \"compute\") By default, all steps are run on \"management\", and we can change it to use \"compute\". However, simply change the value will not work, we also couple with computing resources (see below for what is ‘resources’). The resources need to be appended to the step by run_remote_resources argument.\nSYSargsList(..., run_session = \"compute\", run_remote_resources = list(...)) This is how to config the running session for each step, but generally we can use a more convenient method addResources to add resources (continue reading below).\nResources Resources here refer to computer resources, like CPU, RAM, time limit, etc. The resources list object provides the number of independent parallel cluster processes defined under the Njobs element in the list. The following example will run 18 processes in parallel using each 4 CPU cores on a slurm scheduler. If the resources available on a cluster allow running all 18 processes at the same time, then the shown sample submission will utilize in a total of 72 CPU cores.\nNote, runWF can be used with most queueing systems as it is based on utilities from the batchtools package, which supports the use of template files (*.tmpl) for defining the run parameters of different schedulers. To run the following code, one needs to have both a conffile (see .batchtools.conf.R samples here) and a template file (see *.tmpl samples here) for the queueing available on a system. The following example uses the sample conffile and template files for the Slurm scheduler provided by this package.\nThe resources can be appended when the step is generated, or it is possible to add these resources later, as the following example using the addResources function:\nBefore adding resources\nrunInfo(sal)[['runOption']][['gzip']] ## $directory ## [1] TRUE ## ## $run_step ## [1] \"mandatory\" ## ## $run_session ## [1] \"management\" ## ## $rmd_line ## [1] \"52:60\" ## ## $prepro_lines ## [1] \"\" resources \u003c- list(conffile=\".batchtools.conf.R\", template=\"batchtools.slurm.tmpl\", Njobs=18, walltime=120,##minutes ntasks=1, ncpus=4, memory=1024,##Mb partition = \"short\"# a compute node called 'short' ) sal \u003c- addResources(sal, c(\"gzip\"), resources = resources) ## Please note that the 'gzip' step option 'management' was replaced with 'compute'. After adding resources\nrunInfo(sal)[['runOption']][['gzip']] ## $directory ## [1] TRUE ## ## $run_step ## [1] \"mandatory\" ## ## $run_session ## [1] \"compute\" ## ## $rmd_line ## [1] \"52:60\" ## ## $prepro_lines ## [1] \"\" ## ## $run_remote_resources ## $run_remote_resources$conffile ## [1] \".batchtools.conf.R\" ## ## $run_remote_resources$template ## [1] \"batchtools.slurm.tmpl\" ## ## $run_remote_resources$Njobs ## [1] 18 ## ## $run_remote_resources$walltime ## [1] 120 ## ## $run_remote_resources$ntasks ## [1] 1 ## ## $run_remote_resources$ncpus ## [1] 4 ## ## $run_remote_resources$memory ## [1] 1024 ## ## $run_remote_resources$partition ## [1] \"short\" You can see the step option is automatically replaced from ‘management’ to ‘compute’.\nWorkflow status To check the summary of the workflow, we can use:\nsal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Success ## 2. export_iris --\u003e Status: Success ## 3. gzip --\u003e Status: Success ## Total Files: 3 | Existing: 3 | Missing: 0 ## 3.1. gzip ## cmdlist: 3 | Success: 3 ## 4. gunzip --\u003e Status: Success ## Total Files: 3 | Existing: 3 | Missing: 0 ## 4.1. gunzip ## cmdlist: 3 | Success: 3 ## 5. stats --\u003e Status: Success ## To access more details about the workflow instances, we can use the statusWF method:\nstatusWF(sal) ## $load_library ## DataFrame with 1 row and 2 columns ## Step Status ## \u003ccharacter\u003e \u003ccharacter\u003e ## 1 load_library Success ## ## $export_iris ## DataFrame with 1 row and 2 columns ## Step Status ## \u003ccharacter\u003e \u003ccharacter\u003e ## 1 export_iris Success ## ## $gzip ## DataFrame with 3 rows and 5 columns ## Targets Total_Files Existing_Files Missing_Files gzip ## \u003ccharacter\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cmatrix\u003e ## SE SE 1 1 0 Success ## VE VE 1 1 0 Success ## VI VI 1 1 0 Success ## ## $gunzip ## DataFrame with 3 rows and 5 columns ## Targets Total_Files Existing_Files Missing_Files gunzip ## \u003ccharacter\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cmatrix\u003e ## SE SE 1 1 0 Success ## VE VE 1 1 0 Success ## VI VI 1 1 0 Success ## ## $stats ## DataFrame with 1 row and 2 columns ## Step Status ## \u003ccharacter\u003e \u003ccharacter\u003e ## 1 stats Success To access the options of each workflow step, for example, whether it is mandatory step or optional step, where it stored in the template, where to run the step, etc., we can use the runInfo function to check.\nrunInfo(sal) ## $env ## \u003cenvironment: 0x557918f5c620\u003e ## ## $runOption ## $runOption$load_library ## $runOption$load_library$directory ## [1] FALSE ## ## $runOption$load_library$run_step ## [1] \"mandatory\" ## ## $runOption$load_library$run_session ## [1] \"management\" ## ## $runOption$load_library$run_remote_resources ## NULL ## ## $runOption$load_library$rmd_line ## [1] \"25:31\" ## ## $runOption$load_library$prepro_lines ## [1] \"\" ## ## ## $runOption$export_iris ## $runOption$export_iris$directory ## [1] FALSE ## ## $runOption$export_iris$run_step ## [1] \"mandatory\" ## ## $runOption$export_iris$run_session ## [1] \"management\" ## ## $runOption$export_iris$run_remote_resources ## NULL ## ## $runOption$export_iris$rmd_line ## [1] \"37:46\" ## ## $runOption$export_iris$prepro_lines ## [1] \"\" ## ## ## $runOption$gzip ## $runOption$gzip$directory ## [1] TRUE ## ## $runOption$gzip$run_step ## [1] \"mandatory\" ## ## $runOption$gzip$run_session ## [1] \"compute\" ## ## $runOption$gzip$rmd_line ## [1] \"52:60\" ## ## $runOption$gzip$prepro_lines ## [1] \"\" ## ## $runOption$gzip$run_remote_resources ## $runOption$gzip$run_remote_resources$conffile ## [1] \".batchtools.conf.R\" ## ## $runOption$gzip$run_remote_resources$template ## [1] \"batchtools.slurm.tmpl\" ## ## $runOption$gzip$run_remote_resources$Njobs ## [1] 18 ## ## $runOption$gzip$run_remote_resources$walltime ## [1] 120 ## ## $runOption$gzip$run_remote_resources$ntasks ## [1] 1 ## ## $runOption$gzip$run_remote_resources$ncpus ## [1] 4 ## ## $runOption$gzip$run_remote_resources$memory ## [1] 1024 ## ## $runOption$gzip$run_remote_resources$partition ## [1] \"short\" ## ## ## ## $runOption$gunzip ## $runOption$gunzip$directory ## [1] TRUE ## ## $runOption$gunzip$run_step ## [1] \"mandatory\" ## ## $runOption$gunzip$run_session ## [1] \"management\" ## ## $runOption$gunzip$rmd_line ## [1] \"64:72\" ## ## $runOption$gunzip$prepro_lines ## [1] \"\" ## ## ## $runOption$stats ## $runOption$stats$directory ## [1] FALSE ## ## $runOption$stats$run_step ## [1] \"optional\" ## ## $runOption$stats$run_session ## [1] \"management\" ## ## $runOption$stats$run_remote_resources ## NULL ## ## $runOption$stats$rmd_line ## [1] \"76:92\" ## ## $runOption$stats$prepro_lines ## [1] \"\" Visualize workflow systemPipeR workflows instances can be visualized with the plotWF function.\nThis function will make a plot of selected workflow instance and the following information is displayed on the plot:\n- Workflow structure (dependency graphs between different steps); - Workflow step status, *e.g.* `Success`, `Error`, `Pending`, `Warnings`; - Sample status and statistics; - Workflow timing: running duration time. If no argument is provided, the basic plot will automatically detect width, height, layout, plot method, branches, etc.\nplotWF(sal, width = \"80%\", rstudio = TRUE) {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats\\n }\\n \\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:01:28; End time: 2022-06-03 19:01:28; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:01:29; End time: 2022-06-03 19:01:29; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, dashed, rounded\\\" label=gzip\n3/0/0/3; 0.1s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-03 19:01:29; End time: 2022-06-03 19:01:29; Duration: 00:00:0.1\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0.1s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-03 19:01:29; End time: 2022-06-03 19:01:30; Duration: 00:00:0.1\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.4s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:01:30; End time: 2022-06-03 19:01:30; Duration: 00:00:0.4\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-85376142\",\"responsive\":true,\"width\":\"80%\",\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} We will discuss a lot more advanced use of plotWF function in the next section.\nHigh-level project control If you desire to resume or restart a project that has been initialized in the past, SPRproject function allows this operation.\nResume\nWith the resume option, it is possible to load the SYSargsList object in R and resume the analysis. Please, make sure to provide the logs.dir location, and the corresponded YAML file name, if the default names were not used when the project was created.\nsal \u003c- SPRproject(resume = TRUE, logs.dir = \".SPRproject\", sys.file = \".SPRproject/SYSargsList.yml\") If you choose to save the environment in the last analysis, you can recover all the files created in that particular section. SPRproject function allows this with load.envir argument. Please note that the environment was saved only with you run the workflow in the last section (runWF()).\nsal \u003c- SPRproject(resume = TRUE, load.envir = TRUE) Restart\nThe resume option will keep all previous logs in the folder; however, if you desire to clean the execution (delete all the log files) history and restart the workflow, the restart=TRUE option can be used.\nsal \u003c- SPRproject(restart = TRUE, load.envir = FALSE) Overwrite\nThe last and more drastic option from SYSproject function is to overwrite the logs and the SYSargsList object. This option will delete the hidden folder and the information on the SYSargsList.yml file. This will not delete any parameter file nor any results it was created in previous runs. Please use with caution.\nsal \u003c- SPRproject(overwrite = TRUE) Session sessionInfo() ## R version 4.2.0 (2022-04-22) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.4 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] systemPipeR_2.3.4 ShortRead_1.54.0 ## [3] GenomicAlignments_1.32.0 SummarizedExperiment_1.26.1 ## [5] Biobase_2.56.0 MatrixGenerics_1.8.0 ## [7] matrixStats_0.62.0 BiocParallel_1.30.2 ## [9] Rsamtools_2.12.0 Biostrings_2.64.0 ## [11] XVector_0.36.0 GenomicRanges_1.48.0 ## [13] GenomeInfoDb_1.32.2 IRanges_2.30.0 ## [15] S4Vectors_0.34.0 BiocGenerics_0.42.0 ## ## loaded via a namespace (and not attached): ## [1] lattice_0.20-45 png_0.1-7 assertthat_0.2.1 ## [4] digest_0.6.29 utf8_1.2.2 R6_2.5.1 ## [7] evaluate_0.15 highr_0.9 ggplot2_3.3.6 ## [10] blogdown_1.10 pillar_1.7.0 zlibbioc_1.42.0 ## [13] rlang_1.0.2 rstudioapi_0.13 jquerylib_0.1.4 ## [16] Matrix_1.4-1 rmarkdown_2.14 labeling_0.4.2 ## [19] stringr_1.4.0 htmlwidgets_1.5.4 RCurl_1.98-1.6 ## [22] munsell_0.5.0 DelayedArray_0.22.0 compiler_4.2.0 ## [25] xfun_0.31 pkgconfig_2.0.3 htmltools_0.5.2 ## [28] tidyselect_1.1.2 tibble_3.1.7 GenomeInfoDbData_1.2.8 ## [31] bookdown_0.26 fansi_1.0.3 dplyr_1.0.9 ## [34] crayon_1.5.1 bitops_1.0-7 grid_4.2.0 ## [37] DBI_1.1.2 jsonlite_1.8.0 gtable_0.3.0 ## [40] lifecycle_1.0.1 magrittr_2.0.3 scales_1.2.0 ## [43] cli_3.3.0 stringi_1.7.6 farver_2.1.0 ## [46] hwriter_1.3.2.1 latticeExtra_0.6-29 bslib_0.3.1 ## [49] generics_0.1.2 ellipsis_0.3.2 vctrs_0.4.1 ## [52] RColorBrewer_1.1-3 tools_4.2.0 glue_1.6.2 ## [55] purrr_0.3.4 jpeg_0.1-9 parallel_4.2.0 ## [58] fastmap_1.1.0 yaml_2.3.5 colorspace_2.0-3 ## [61] knitr_1.39 sass_0.4.1 ","categories":"","description":"","excerpt":" suppressPackageStartupMessages({ library(systemPipeR) }) Until …","ref":"/sp/spr/sp_run/step_run/","tags":"","title":"Run/manage workflows"},{"body":" SPS framework come with a plenty of useful general R utility functions, like pretty logging, package namespace checking, URL checking, and more.\nSince SPS 1.1, these functions are separated into a supporting package called spsUtil (systemPipeShiny Utility). You can install it from CRAN.\nInstallation Read the developer tools main page, not repeating here.\nFunctions reference manual In documents, we only highlight some important functions. Please read the reference manuals for details of every function.\nFunction highlights library(spsUtil) logging with msg basic Often times in an R function, we want to use some text to inform users the status and message. We can use functions like message, warning, stop to generate different levels of information.\n{spsUtil} provides some more informative and prettier ways to generate these kind of messages.\nmsg(\"my message\") ## [INFO] 2021-12-15 01:57:33 my message You can see it starts with a level information, then a time stamp, and follows the actual message. By default, it uses the INFO level, and you can change to whatever level you want. However, there are 3 keywords that have special meaning.\nLevels INFO: equals message method in native R WARNING: generates warnings the same as warning function ERROR: generates error the same as stop function and will prevent downstream code get evaluated. If the level is other than these 3, there is no special meaning in R, just cat the message out.\nmsg(\"I am info\", level = \"INFO\") ## [INFO] 2021-12-15 01:57:33 I am info msg(\"I am warning\", level = \"warning\") # not case sensitive ## Warning: [WARNING] 2021-12-15 01:57:33 I am warning msg(\"I am error\", level = \"ERROR\") ## Error: [ERROR] 2021-12-15 01:57:33 I am error msg(\"I am random level\", level = \"MY LEVEL\") ## [MY LEVEL] 2021-12-15 01:57:33 I am random level Prefix For the 3 key levels, you can specify the prefix in front of the level text to over write the default level text INFO, WARNING, or ERROR\nmsg(\"I am info\", level = \"INFO\", info_text = \"NEW-INFO\") ## [NEW-INFO] 2021-12-15 01:57:33 I am info msg(\"I am warning\", level = \"warning\", warning_text = \"MY-WARNING\") ## Warning: [MY-WARNING] 2021-12-15 01:57:33 I am warning msg(\"I am error\", level = \"ERROR\", error_text = \"STOP\") ## Error: [STOP] 2021-12-15 01:57:33 I am error Colors Colors are automatically enabled if it is supported. If you try all code above in your terminal or Rstudio, they all have colors. In Rmd, to enable the color, you need to add the following code chunk. You also need to install the fansi package.\n```{r echo=FALSE, results='asis'} options(crayon.enabled = TRUE) old_hooks \u003c- fansi::set_knit_hooks(knitr::knit_hooks, which = c(\"output\", \"message\", \"error\", \"warning\")) ``` PRE.fansi SPAN {padding-top: .25em; padding-bottom: .25em}; msg(\"I am info\", level = \"INFO\", info_text = \"NEW-INFO\") ## [NEW-INFO] 2021-12-15 01:57:33 I am info The 3 key levels has default colors:\n INFO: blue WARNING: orange ERROR: red You can specify colors for your own levels\nmsg(\"I am warning\", level = \"warning\") ## not super orange in Rmd translation -_-= ## Warning: [WARNING] 2021-12-15 01:57:33 I am warning msg(\"I am error\", level = \"error\") ## Error: [ERROR] 2021-12-15 01:57:33 I am error msg(\"oh yeah\", level = \"SUCCESS\", .other_color = \"green\") ## [SUCCESS] 2021-12-15 01:57:33 oh yeah msg(\"oh no\", level = \"FAIL\", .other_color = \"purple\") ## [FAIL] 2021-12-15 01:57:33 oh no Wrapper You can use this logging function in your own projects by wrapping it inside a upper level function, like what we do for spsinfo, spswarn, spserror. They have SPS- prefix added, and have some SPS global settings appended.\nspsOption('use_crayon', TRUE) spsinfo(\"info\", verbose = TRUE) ## default `verbose` mute the message ## [SPS-INFO] 2021-12-15 01:57:33 info spswarn(\"warning\") ## Warning: [SPS-WARNING] 2021-12-15 01:57:33 warning spserror(\"stop\") ## Error: [SPS-ERROR] 2021-12-15 01:57:33 stop To create a simple one for project is very easy. Assume your project is named “My Project”. You can create logging as:\nmpInfo \u003c- function(text){ spsUtil::msg(text, info_text = \"MP-INFO\") } mpWarn \u003c- function(text){ spsUtil::msg(text, level = \"warning\", warning_text = \"MP-WARNING\") } mpErr \u003c- function(text){ spsUtil::msg(text, level = \"error\", error_text = \"MP-ERROR\") } mpInfo(\"info\") ## [MP-INFO] 2021-12-15 01:57:33 info mpWarn(\"warning\") ## Warning: [MP-WARNING] 2021-12-15 01:57:33 warning mpErr(\"error\") ## Error: [MP-ERROR] 2021-12-15 01:57:33 error mute message with quiet In R, you can easily mute message and warnings with suppressMessages(), and suppressWarnings(), but not so easy with print or cat methods. spsUtil::quiet enables you to mute all these methods or choose what to mute.\n{ # muted quiet(warning(123)) quiet(message(123)) quiet(print(123)) quiet(cat(123)) # not muted quiet(warning(123), warning = FALSE) quiet(message(123), message = FALSE) quiet(print(123), print_cat = FALSE) quiet(cat(123), print_cat = FALSE) } ## Warning in force(x): 123 ## 123 ## [1] 123 ## 123 timeout Run expressions with a time limit, stop an expression if it takes too long\n# default timeout({Sys.sleep(0.1)}, time_out = 0.01) ## Error: Timout reached # timeout is evaluating expressions the same level as you call it timeout({abc \u003c- 123}) # so you should get `abc` even outside the function call abc ## [1] 123 # custom timeout callback timeout({Sys.sleep(0.1)}, time_out = 0.01, on_timeout = {print(\"It takes too long\")}) ## [1] \"It takes too long\" # final call back timeout({Sys.sleep(0.1)}, time_out = 0.01, on_final = {print(\"some final words\")}) # on error ## Error: Timout reached ## [1] \"some final words\" timeout({invisible()}, on_final = {print(\"runs even success\")}) # no return by have final expression on success ## [1] \"runs even success\" # assign to value my_val \u003c- timeout({10 + 1}) my_val ## [1] 11 check “empty” values with emptyIsFalse In R, values like NA, \"\", NULL, length(0) is not very meaningful in condition judgment and will give you errors. Yet, R does not have a native method to handle these “empty” values in if like other languages. They are meaningful in other ways, but in conditions, we may want to turn them to FALSE.\nif(\"\") TRUE else FALSE ## Error in if (\"\") TRUE else FALSE: argument is not interpretable as logical if(NULL) TRUE else FALSE ## Error in if (NULL) TRUE else FALSE: argument is of length zero if(character(0)) TRUE else FALSE ## Error in if (character(0)) TRUE else FALSE: argument is of length zero if(NA) TRUE else FALSE ## Error in if (NA) TRUE else FALSE: missing value where TRUE/FALSE needed You can see they all give errors. In other languages (javascript in this example), these values are often treated as FALSE.\nif (NaN) true; else false //\u003e false if (undefined) true; else false //\u003e false if (\"\") true; else false //\u003e false if (null) true; else false //\u003e false if (NaN) true; else false // false if (undefined) true; else false // false if (\"\") true; else false // false if (null) true; else false // false This is how emptyIsFalse work. If the input is one of these values, return FALSE, else TRUE\nif(emptyIsFalse(\"\")) TRUE else FALSE ## [1] FALSE if(emptyIsFalse(NULL)) TRUE else FALSE ## [1] FALSE if(emptyIsFalse(character(0))) TRUE else FALSE ## [1] FALSE if(emptyIsFalse(NA)) TRUE else FALSE ## [1] FALSE check missing packages checkNameSpace In our functions, sometimes we want to have the users to install certain packages to enable more functionalities, like the DESeq2::lfcShrink function. Or like in a Rmd source code, before other people can rerender the document, they must install certain packages. checkNameSpace checks all required packages and returns the missing names.\ncheckNameSpace(\"random_pkg\") ## Warning: [WARNING] 2021-12-15 01:57:34 These packages are missing from ## CRAN: random_pkg ## [1] \"random_pkg\" You can add it to your function to or on the top of your Rmd document to inform your users the missing packages and where to install.\npkgs \u003c- list( CRAN = c(\"pkg1\", \"pkg2\"), Bioconductor = c(\"bio_pkg1\", \"bio_pkg2\") ) missing_pkg \u003c- checkNameSpace(pkgs[[1]], from = names(pkgs)[1]) ## Warning: [WARNING] 2021-12-15 01:57:34 These packages are missing from ## CRAN: pkg1,pkg2 missing_pkg \u003c- c(missing_pkg, checkNameSpace(pkgs[[2]], from = names(pkgs)[2])) ## Warning: [WARNING] 2021-12-15 01:57:34 These packages are missing from ## Bioconductor: bio_pkg1,bio_pkg2 if(emptyIsFalse(missing_pkg)) stop(\"Install packages\") ## Error in eval(expr, envir, enclos): Install packages Or write your custom warning message:\n{ missing_pkg \u003c- mapply(function(pkg, from) { checkNameSpace(pkg, quietly = TRUE, from) }, pkg = pkgs, from = names(pkgs), SIMPLIFY = FALSE) cat( \"Use `install.packages(c('\", paste0(missing_pkg[['CRAN']], collapse = \"','\"), \"'))` to install CRAN packages\\n\", sep = \"\" ) cat( \"Use `BiocManager::install(c('\", paste0(missing_pkg[['Bioconductor']], collapse = \"','\"), \"'))` to install Bioconductor packages\\n\", sep = \"\" ) if(emptyIsFalse(unlist(missing_pkg))) stop(\"Install packages\") } ## Use `install.packages(c('pkg1','pkg2'))` to install CRAN packages ## Use `BiocManager::install(c('bio_pkg1','bio_pkg2'))` to install Bioconductor packages ## Error in eval(expr, envir, enclos): Install packages Stack methods Simple stack A simple stack data structure in R, with supporting of assiocated methods, like push, pop and others.\nmy_stack \u003c- simepleStack$new() # check length my_stack$len() #\u003e [1] 0 # add some thing my_stack$push(list(1, 2, 3)) # print current stack str(my_stack$get()) #\u003e List of 3 #\u003e $ : num 1 #\u003e $ : num 2 #\u003e $ : num 3 # check length my_stack$len() #\u003e [1] 3 # add before the current first my_stack$push(list(0), after = 0) # print current stack str(my_stack$get()) #\u003e List of 4 #\u003e $ : num 0 #\u003e $ : num 1 #\u003e $ : num 2 #\u003e $ : num 3 # pop one item my_stack$pop() #\u003e [[1]] #\u003e [1] 0 #\u003e # print current stack str(my_stack$get()) #\u003e List of 3 #\u003e $ : num 1 #\u003e $ : num 2 #\u003e $ : num 3 # pop one item from the tail my_stack$pop(tail = TRUE) #\u003e [[1]] #\u003e [1] 3 #\u003e # print current stack str(my_stack$get()) #\u003e List of 2 #\u003e $ : num 1 #\u003e $ : num 2 # pop more than one items my_stack$pop(2) #\u003e [[1]] #\u003e [1] 1 #\u003e #\u003e [[2]] #\u003e [1] 2 #\u003e # print current stack str(my_stack$get()) # nothing left #\u003e list() History stack Methods for a history stack data structure. It can store history of certain repeating actions. For example, building the back-end of a file/image editor, allow undo/redo actions.\nhis \u003c- historyStack$new() #\u003e Created a history stack which can record 25 steps # add some history his$add(1) #\u003e Added one item to position 1 his$add(2) #\u003e Added one item to position 2 his$add(3) #\u003e Added one item to position 3 his$add(4) #\u003e Added one item to position 4 his$add(5) #\u003e Added one item to position 5 # check status his$status() #\u003e $pos #\u003e [1] 5 #\u003e #\u003e $len #\u003e [1] 5 #\u003e #\u003e $limit #\u003e [1] 25 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] TRUE #\u003e # get item at current history position his$get() #\u003e $item #\u003e [1] 5 #\u003e #\u003e $pos #\u003e [1] 5 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] TRUE #\u003e # go back to previous step his$backward() #\u003e $item #\u003e [1] 4 #\u003e #\u003e $pos #\u003e [1] 4 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] FALSE #\u003e # going back to step 2 his$backward() #\u003e $item #\u003e [1] 3 #\u003e #\u003e $pos #\u003e [1] 3 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] FALSE #\u003e his$backward() #\u003e $item #\u003e [1] 2 #\u003e #\u003e $pos #\u003e [1] 2 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] FALSE #\u003e # going forward 1 step tp step 3 his$forward() #\u003e $item #\u003e [1] 3 #\u003e #\u003e $pos #\u003e [1] 3 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] FALSE #\u003e # check current status his$status() #\u003e $pos #\u003e [1] 3 #\u003e #\u003e $len #\u003e [1] 5 #\u003e #\u003e $limit #\u003e [1] 25 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] FALSE #\u003e # adding a new step at position 3 will remove the old step 4,5 before adding his$add(\"new 4\") #\u003e Added one item to position 4 # only 3 steps + 1 new step = 4 steps left his$status() #\u003e $pos #\u003e [1] 4 #\u003e #\u003e $len #\u003e [1] 4 #\u003e #\u003e $limit #\u003e [1] 25 #\u003e #\u003e $first #\u003e [1] FALSE #\u003e #\u003e $last #\u003e [1] TRUE #\u003e In-line operation In-place operations like i += 1 with inc(x), i -= 1 with inc(x, -1), i *= 2 with mult(x), i /= 2 with divi(x)\ni \u003c- 0 inc(i) # add 1 i ## [1] 1 inc(i) # add 1 i ## [1] 2 inc(i, -1) # minus 1 i ## [1] 1 inc(i, -1) # minus 1 i ## [1] 0 x \u003c- 1 mult(x) # times 2 x ## [1] 2 mult(x) # times 2 x ## [1] 4 divi(x) # divide 2 x ## [1] 2 divi(x) # divide 2 x ## [1] 1 Uniquefy duplicated strings with strUniquefy Fix duplicated values in a character vector, useful in column names and some ID structures that requires unique identifiers. If any duplicated string is found in the vector, a numeric index will be added after the these strings.\nstrUniquefy(c(1,1,1,2,3)) # default ## [1] \"1_1\" \"1_2\" \"1_3\" \"2\" \"3\" strUniquefy(c(1,1,1,2,3), mark_first = FALSE) # don't mark the first one ## [1] \"1\" \"1_1\" \"1_2\" \"2\" \"3\" strUniquefy(c(1,1,1,2,3), sep_b = \"(\", sep_a = \")\") # custom before, after symbols ## [1] \"1(1)\" \"1(2)\" \"1(3)\" \"2\" \"3\" strUniquefy(c(\"a\",\"b\",\"c\",\"a\",\"d\",\"b\")) # works with letters too ## [1] \"a_1\" \"b_1\" \"c\" \"a_2\" \"d\" \"b_2\" check a URL is reachable with checkUrl Useful if you need make some big HTTP requests.\ncheckUrl(\"https://google.com\") ## [1] TRUE checkUrl(\"https://randomwebsite123.com\", timeout = 1) ## Warning: [WARNING] 2021-12-15 01:57:35 Bad url https:// ## randomwebsite123.com ## Warning: [WARNING] 2021-12-15 01:57:35 Timeout was reached: [randomwebsite123.com] Connection timed out after 1001 milliseconds \n## [1] FALSE ","categories":"","description":"","excerpt":" SPS framework come with a plenty of useful general R utility …","ref":"/sps/dev/spsutil/","tags":"","title":"spsUtil"},{"body":"systemPipeRdata: Workflow templates and sample data systemPipeRdata is a helper package to generate with a single command workflow templates that are intended to be used by its parent package systemPipeR. The systemPipeR project provides a suite of R/Bioconductor packages for designing, building and running end-to-end analysis workflows on local machines, HPC clusters and cloud systems, while generating at the same time publication quality analysis reports.\nTo test workflows quickly or design new ones from existing templates, users can generate with a single command workflow instances fully populated with sample data and parameter files required for running a chosen workflow. Pre-configured directory structure of the workflow environment and the sample data used by systemPipeRdata are described here.\nInstallation To install the package, please use the BiocManager::install command:\nif (!requireNamespace(\"BiocManager\", quietly=TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeRdata\") To obtain the most recent updates immediately, one can install it directly from github as follow:\nif (!requireNamespace(\"BiocManager\", quietly=TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"tgirke/systemPipeRdata\", build_vignettes=TRUE, dependencies=TRUE) Due to the large size of the sample data (~320 MB) provided by systemPipeRdata, its download/install may take some time.\nTo install the parent package systemPipeR itself, please use the BiocManager::install method as instructed here.\n ","categories":"","description":"","excerpt":"systemPipeRdata: Workflow templates and sample data systemPipeRdata is …","ref":"/sp/sprdata/","tags":"","title":"systemPipeRdata"},{"body":" Load and unload tabs In SPS, all tabs including tabs for modules and other default tabs can be loaded and unloaded. This is controlled by SPS options\nUnder current version, these options are:\n Option Description Default Other module_wf load workflow module? TRUE FALSE module_rnaseq load RNAseq module? TRUE FALSE module_ggplot load quick ggplot module? TRUE FALSE tab_welcome load welcome tab? TRUE FALSE tab_vs_main load custom visualization main tab? TRUE FALSE tab_canvas load Canvas tab? TRUE FALSE tab_about load about tab? TRUE FALSE Each of them controls whether to load or unload a tab. By default, all tabs are loaded, but you can unload them by turn them to FALSE.\nThe original UI look like this:\n Default UI To unload some tabs, scroll to the option lines in global.R file:\nspsOption(.list = list( ... tab_welcome = TRUE, tab_vs_main = TRUE, tab_canvas = FALSE, tab_about = FALSE, module_wf = FALSE, module_rnaseq = FALSE, module_ggplot = TRUE, ... )) We unload the “Canvas tab”, “workflow module tab”, “RNASeq module tab” and “About tab”. When you restart the app, you should see some tabs are gone:\nThe original UI look like this:\n Unload some tabs Exception for module main page You may have noticed, there is no option to unload the module main tab, which is named “Modules” on the left sidebar. This is because this tab is controlled by its sub-tabs, the module tab options. To unload this tab, all the module tabs have to be unloaded the same time like following. If any module is loaded, this module main tab cannot be unloaded.\nspsOption(.list = list( ... module_wf = FALSE, module_rnaseq = FALSE, module_ggplot = FALSE, ... )) No module loaded ","categories":"","description":"","excerpt":" Load and unload tabs In SPS, all tabs including tabs for modules and …","ref":"/sps/adv_features/displaytabs/","tags":"","title":"Toggle tabs"},{"body":"BioC2021 BioC2021{blk}\n systemPipe: Workflow and Visualization Toolkit - Workshop\n Workshop Website{blk} Bioc2021 Workshop{blk} GitHub Material{blk} BioC2020 BioC2020{blk}\n systemPipeShiny: An Interactive Framework for Workflow Management and Visualization - F1000{blk}\n systemPipeR: a generic workflow environment federates R with command-line software - F1000{blk}\n BioC2019 BioC2019{blk} systemPipeR's New CWL Command-line Interface - Workshop GitHub Material{blk} [ View Slides in Separate Browser Tab ]{blk}\n Bioc2018 BioC2018{blk}\n Poster Bioc2018{blk}\n Bioc2016 BioC2016{blk} [ View Slides in Separate Browser Tab ]{blk}\n Material for Bioc2016 Tutorial Intro Slide Show{blk} Tutorial Material Introduction to systemPipeR HTML{blk} PDF{blk} Rmd{blk} Demo Workflow: RIBO-Seq HTML{blk} PDF{blk} Rmd{blk} Installation Please install systemPipeRdata from this GitHub repository as shown below. This package provides the data and Rmd files for the tutorial. Its parent package systemPipeR is a dependency and it should install along with all its own dependencies automatically. If it doesn’t then please also install the package, using the BiocManager::install command given below.\nif (!requireNamespace(\"BiocManager\", quietly=TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"tgirke/systemPipeRdata\", build_vignettes=TRUE, dependencies=TRUE) BioC2015 BioC2015{blk} [ View Slides in Separate Browser Tab ]{blk}\n ","categories":"","description":"","excerpt":"BioC2021 BioC2021{blk}\n systemPipe: Workflow and Visualization …","ref":"/outreach/conferences/","tags":"","title":"Conferences"},{"body":"createParam has a second different set of input syntax version 2. To use this new version createParam(..., syntaxVersion = \"v2\") must be provided.\nNew in v2 What are the new features included in the v2?\n Support duplicated argument flags. Some programs uses the same flag, like -f file1 -f file2 -f file3 for multiple files. This feature is added in v2. CWL argument component support. CWL positions in inputs and arguments components support. positional argument without any prefix. Prefix other than dash - or --. Some programs do not use dash as flags, for example some uses @. This is supported in v2. CWL standard out more types support, long, float, double, boolean Input Imagine we want to create CWL for command:\nsuppressPackageStartupMessages({ library(systemPipeR) }) mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 \u003e abc.txt To use createParam, simply write the command in a pseudo-bash script format:\ncommand \u003c- ' mycmd \\ p: -s; File; sample1.txt \\ p: -s; File; sample2.txt \\ p: --c; ; \\ p: -o; File; out: myout.txt \\ ref_genome; File; a.fasta \\ p: --nn; int; 12 \\ mystdout; File; stdout: abc.txt ' Format First line of the command-line object will be treated as the baseCommand;\n Each line specifies one argument and its default value.\n Each line is composed with exact 2 ; to separate 3 columns. Some columns can leave empty\n Text before first ; will be will used as prefix/names. If it starts with keyword “p:”, anything after “p:” and before the first ; will be used as prefix, and the name of this position will be the prefix but with leading dash(s) “-”, “--” removed. If there is any duplication, a number index will be added to the end for the names. If there is no keyword “p:” before first ;, all text before first ; will be the name.\n If there is keyword “p:” before first ; but nothing before and after the second ;, this position will be treated as CWL argument instead of input.\n Text between first and second ; is type. Must be one of File, Directory, string, int, double, float, long, boolean.\n Text after second ; and before \\ or end of the line is the default value. If it starts with keyword “out” or “stdout”, this position will also be added to outputs or standard output.\n There is only 1 line can have “stdout” and usually it is the last position argument.\n Ending with “\\” is recommended but not required.\n Below is a table of examples to demonstrate if values given or not given in different columns how createParam would translate them to.\n example name/prefix column type column value column translate to first line mycmd -\u003ebase command no type, no value p: –prefix; ; -\u003e arguments with prefix, type, or value p: -prefix; type; default_value -\u003e normal input no prefix name; type; default_value -\u003e inputs no prefix prefix other than dash p: @prefix; type; default_value -\u003e inputs, prefix no dash output binding specified in third column p: -prefix; type; out: default_value -\u003e inputs, outputs standard out binding specified in third column name; type; stdout: default_value -\u003e stdout run createParam Function The string above that we just defined will be used as input for createParam.\nIf the format is correct, after parsing, the function will print the three components of the cwl file:\n BaseCommand: Specifies the program to execute. Inputs: Defines the input parameters of the process. Arguments: Usually flags with some fixed values. Outputs: Defines the parameters representing the output of the process. Stardard out: stardard out capture of command-line. cmd \u003c- createParam(command, writeParamFiles = FALSE, syntaxVersion = \"v2\") ## *****BaseCommand***** ## mycmd ## *****Arguments***** ## argument1: ## prefix: --c ## position: 3 ## *****Inputs***** ## s1: ## type: File ## prefix: -s ## default value: sample1.txt ## position: 1 ## s2: ## type: File ## prefix: -s ## default value: sample2.txt ## position: 2 ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## *****Outputs***** ## output1: ## type: File ## default value: myout.txt ## *****Standard Outputs***** ## mystdout: ## type: File ## default value: abc.txt ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 \u003e abc.txt If the user chooses not to save the param files on the above operation, later, one can use the writeParamFiles function.\nwriteParamFiles(cmd, overwrite = TRUE, syntaxVersion = \"v2\") ## Written content of 'commandLine' to file: ## param/cwl/mycmd/mycmd.cwl ## Written content of 'commandLine' to file: ## param/cwl/mycmd/mycmd.yml By default, the files will be saved inside ./param/cwl/base_cmd. It means a child folder under param then cwl, and create a new folder named by the base command of the command-line.\nAccess and edit param files All access and edit functions have the ending of 2. Syntax v1 and v2 are not interchangeable. Params created by v1 cannot be used with v2 utility functions, vice versa.\nUsage\nprintParam2(sysargs, base = FALSE, args = FALSE, inputs = FALSE, outputs = FALSE, stdout = FALSE, raw_cmd = FALSE, all = TRUE) appendParam2(sysargs, x, position = c(\"inputs\", \"args\", \"outputs\"), after = NULL, verbose = FALSE) replaceParam2(sysargs, x, index=NULL,position = c(\"inputs\", \"baseCommand\", \"args\", \"outputs\", \"stdout\"), verbose = FALSE) removeParam2(sysargs, index=NULL, position = c(\"inputs\", \"args\", \"outputs\", \"stdout\"), verbose = FALSE) renameParam2(sysargs, index=NULL, new_names, position = c(\"inputs\", \"args\", \"outputs\", \"stdout\"), verbose = FALSE) Format of utility functions printParam2: print CWL components of desired, default is to print all.\n removeParam2: removes items in certain positions you select.\n replaceParam2: replaces the values in command-line with indices given in list by those given in values\n renameParam2: rename the names of items in certain position.\n appendParam2: Add arguments to the original command line. Adding new basecommand or standard out is not allowed.\n x format For append and replace functions, there is an argument x. It can be either a length 1 character string or or a list.\n If x is a character, it requires exact 3 semi-colons ; to separate the string in to 4 columns. Values before the third column are the same as createParam inputs, first column: prefix/argument name, second column: type, third column: default value. The fourth column (new): numeric, index of the new item, this will be translated into position entries in CWL.\n No \\ should be added to the end. If the key word out or stdout is included in the default value column, the new component will be treated as outputs or standard outputs. Often times, inputs and outputs are paired in CWL, and this is done automatically in createParam for you, but this is not the case here. Since the position argument limit to modify only one place. It will be good to check if the paired inputs component is there or otherwise append the inputs (see examples below). If x is a list, it must be named. Following items must be included in list: name, preF, type, value, index. They refer to name, prefix, param type, default value, and position index correspondingly.\n baseCommand modification is not supported to use list format. inputs position requires the list contains following items: “name”, “preF”, “type”, “value”, “index”. args position requires the list contains following items: “name”, “preF”, “index”. outputs position requires the list contains following items: “name”, “type”, “value”. stdout position requires the list contains following items: “name”, “type”, “value”. It will be more clear when we walk through examples below.\nPrint a component printParam2 by default print out all CWL component positions. To select a few of them to print, turn all = FALSE and turn desired positions in any combination to TRUE.\n# print only base command printParam2(cmd, base = TRUE, all = FALSE) ## *****BaseCommand***** ## mycmd # print inputs and outputs printParam2(cmd, inputs = TRUE, outputs = TRUE, all = FALSE) ## *****Inputs***** ## s1: ## type: File ## prefix: -s ## default value: sample1.txt ## position: 1 ## s2: ## type: File ## prefix: -s ## default value: sample2.txt ## position: 2 ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## *****Outputs***** ## output1: ## type: File ## default value: myout.txt # print parsed raw command printParam2(cmd, raw_cmd = TRUE, all = FALSE) ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 \u003e abc.txt Appending new components Adding new inputs new_cmd \u003c- 'p: -abc; string; abc; 7' cmd \u003c- appendParam2(cmd, new_cmd, position = \"inputs\") printParam2(cmd, inputs = TRUE, raw_cmd = TRUE, all = FALSE) ## *****Inputs***** ## s1: ## type: File ## prefix: -s ## default value: sample1.txt ## position: 1 ## s2: ## type: File ## prefix: -s ## default value: sample2.txt ## position: 2 ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## abc: ## type: string ## prefix: -abc ## default value: abc ## position: 7 ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt We can see that a new parameter -abc and its value abc has been added to the last command flag before the standard out.\nAlternatively, we can do the same with list format:\nnew_cmd_list \u003c- list(name = \"abc\", preF = \"-abc\", type = \"string\", value = \"abc\", index = 7) appendParam2(cmd, new_cmd_list, position = \"inputs\") Adding new output new_cmd \u003c- 'new_out; File; out: new_file.txt;' commandline \u003c- appendParam2(cmd, new_cmd, position = \"outputs\", verbose = T) ## Detected type is: out ## Appnding to the 2th position in the list ## *****BaseCommand***** ## mycmd ## *****Arguments***** ## argument1: ## prefix: --c ## position: 3 ## *****Inputs***** ## s1: ## type: File ## prefix: -s ## default value: sample1.txt ## position: 1 ## s2: ## type: File ## prefix: -s ## default value: sample2.txt ## position: 2 ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## abc: ## type: string ## prefix: -abc ## default value: abc ## position: 7 ## *****Outputs***** ## output1: ## type: File ## default value: myout.txt ## new_out: ## type: File ## default value: new_file.txt ## *****Standard Outputs***** ## mystdout: ## type: File ## default value: abc.txt ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt ## Note: New output appended. However, outputs are often come in pairs with inputs. Make sure the corresponding input is there, or append it. printParam2(cmd, outputs = TRUE, raw_cmd = TRUE, all = FALSE) ## *****Outputs***** ## output1: ## type: File ## default value: myout.txt ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt Alternatively, we can do the same with list format:\nnew_cmd_list \u003c- list(name = \"new_out\", type = \"File\", value = \"abc.txt\") appendParam2(cmd, new_cmd_list, position = \"outputs\") However, the problem as you may have seen in the message of running appendParam2 is that inputs and outputs are often paired in CWL. So most times, we want to also to append the related inputs part to make CWL work.\nnew_cmd \u003c- 'p: -new; File; new_file.txt; 99' commandline \u003c- appendParam2(cmd, new_cmd, position = \"inputs\") printParam2(cmd, all = FALSE, inputs = TRUE, outputs = TRUE, raw_cmd = TRUE) ## *****Inputs***** ## s1: ## type: File ## prefix: -s ## default value: sample1.txt ## position: 1 ## s2: ## type: File ## prefix: -s ## default value: sample2.txt ## position: 2 ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## abc: ## type: string ## prefix: -abc ## default value: abc ## position: 7 ## *****Outputs***** ## output1: ## type: File ## default value: myout.txt ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt --c -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt This time, most of the string is similar to the output one, but remember to remove keyword out: and add prefix if necessary.\nReplacing existing ones Replace argument new_cmd \u003c- list(name = \"new_arg2\", preF = \"--haha\", index = 7) cmd \u003c- replaceParam2(cmd, new_cmd, index = \"argument1\", position = \"args\") printParam2(cmd, args = TRUE, raw_cmd = TRUE, all = FALSE) ## *****Arguments***** ## new_arg2: ## prefix: --haha ## position: 7 ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt -o myout.txt a.fasta --nn 12 -abc abc --haha \u003e abc.txt We can see from above that one good thing of list format is that the component name and prefix can be different, whereas in string format, the name is always the prefix word without leading dash(s).\n Replacing other posistions Replacing other positions will be very similar to the example above, we will not list them all here. One quick note is that the index in replaceParam2 is different than the index item in the list new_cmd. In replaceParam2 it means which argument in cmd we want to replace, it can be the name of that component or using a number to index it. In new_cmd, index means the CWL parameter position, it can only be a number. This will be reflected in the parsed raw command.\nIf we change the index in new_cmd to a different number, watch closely how parsed raw command change:\nBefore\nprintParam2(cmd, raw_cmd = TRUE, all = FALSE) ## *****Parsed raw command line***** ## mycmd -s sample1.txt -s sample2.txt -o myout.txt a.fasta --nn 12 -abc abc --haha \u003e abc.txt After\nnew_cmd \u003c- list(name = \"new_arg2\", preF = \"--haha\", index = 1) cmd \u003c- replaceParam2(cmd, new_cmd, index = \"new_arg2\", position = \"args\") ## Param name new_arg2 exists, it will be renamed to: new_arg2_4dq printParam2(cmd, raw_cmd = TRUE, all = FALSE) ## *****Parsed raw command line***** ## mycmd -s sample1.txt --haha -s sample2.txt -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt Rename a component Replace a single component Replace the new argument we just replaced for example:\ncmd \u003c- renameParam2(cmd, new_names = \"my_arg_renamed\", index = 1, position = \"args\") printParam2(cmd, args = TRUE, raw_cmd = TRUE, all = FALSE) ## *****Arguments***** ## my_arg_renamed: ## prefix: --haha ## position: 1 ## *****Parsed raw command line***** ## mycmd -s sample1.txt --haha -s sample2.txt -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt Replace multiple components cmd \u003c- renameParam2(cmd, new_names = c(\"file1\", \"file2\"), index = c(\"s1\", \"s2\"), position = \"inputs\") printParam2(cmd, inputs = TRUE, raw_cmd = TRUE, all = FALSE) ## *****Inputs***** ## file1: ## type: File ## prefix: -s ## default value: sample1.txt ## position: 1 ## file2: ## type: File ## prefix: -s ## default value: sample2.txt ## position: 2 ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## abc: ## type: string ## prefix: -abc ## default value: abc ## position: 7 ## *****Parsed raw command line***** ## mycmd -s sample1.txt --haha -s sample2.txt -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt length of new_names must be the same as index.\n Remove components cmd \u003c- removeParam2(cmd, index = 1:2, position = \"inputs\") printParam2(cmd, all = FALSE, inputs = TRUE, raw_cmd = TRUE) ## *****Inputs***** ## o: ## type: File ## prefix: -o ## default value: myout.txt ## position: 4 ## ref_genome: ## type: File ## prefix: ## default value: a.fasta ## position: 5 ## nn: ## type: int ## prefix: --nn ## default value: 12 ## position: 6 ## abc: ## type: string ## prefix: -abc ## default value: abc ## position: 7 ## *****Parsed raw command line***** ## mycmd --haha -o myout.txt a.fasta --nn 12 -abc abc \u003e abc.txt ","categories":"","description":"","excerpt":"createParam has a second different set of input syntax version 2. To …","ref":"/sp/spr/cwl/create_param_v2/","tags":"","title":"createParam V2"},{"body":" In this section, we will discuss the built-in modules in SPS\n ","categories":"","description":"","excerpt":" In this section, we will discuss the built-in modules in SPS\n ","ref":"/sps/modules/","tags":"","title":"Modules"},{"body":" SPS notification system In SPS, there is a notification dropdown where developers can broadcast new messages to users. The dropdown is located on the top-right corner.\n Notification Dropdown \nWhen a notification item is clicked, details of the notification will be displayed in a modal.\n Notification Detail Moadal Official notification If you only use the original SPS, we will send out new notifications every time we update the package or other important things that we want to inform you. You should see the icon of the dropdown becomes. + the message number. If there is no message or you have clicked the dropdown, it will become + 0.\nCustom notification If you do not want to receive the official notification or want to write your own note to your users, first let us understand how it works.\nMechanism Every time when you run the sps() main function, it will look for a remote URL that stores the notification information in yaml{blk} format. If this file can be successfully parsed, you will see the notification dropdown menu on SPS UI, otherwise no dropdown displayed.\nTo define your own notification URL, you need to change the option note_url in the global.R file. Read more about changing SPS options. The default value is a file on Github, which also can be used as your template to write custom notification messages:\nhttps://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/remote_resource/notifications.yaml{blk}\nNotification template If you download the link above, you should see something like this:\n############ Create remote messages to notify users in the app ################# ## When app starts, it will first try to load this file from online. ## You should place this file somewhere publically reachable online, like Github. ## This file should not be included in your app deployment. ## Add the url of this file to the SPS option `note_url` in \"global.R\" file # type: one of 'package' or 'general', required # expire: note will be displayed before the date, required, YYYY-MM-DD format # title: string, required # icon: any font-awesome icon name, default is the \"info-circle\" # status: one of primary, success, info, warning, danger, default is \"primary\" # pkg_name: string, required if type == 'package', such as \"systemPipeShiny\" # version: string, required if type == 'package', such as \"1.0.0\" # message: string, optional, the text body of the notification. Be careful with indentations. - note: type: general pkg_name: version: title: Notification broadcasting expire: 2099-01-01 icon: status: message: | ## SPS notifications What you are looking at is the SPS notification broadcasting system. It display messages to your users by reading a remote `yaml` file stored online. SPS will fetch the content of this file and translate it to different notes you can see here. So you do not need to re-deploy the app every time there is a new notification. 1. You can customize your own notifications by using [this file as template](https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/remote_resource/notifications.yaml). 2. After the modification, place this file in public accessible location, like Github, do not inlcude this file in app deployment. 3. During app deployment, indicate the URL of this file in `global.R` file, `note_url:` option. Template details Most entries are easy-to-understand. Here are some key points.\nIndentation Indentation is very important in a yaml file. In the template, we use 4 spaces as 1 level of indentation.\nNotification start and end Always start with a - note: to define a notification item. After you finish typing the message body, leave at least one line blank before starting another notification.\ntype general: Use this type to create a general notification. It will ignore pkg_name and version information.\npackage: A notification that is related to a package updates. This type of note will first check if the user has installed the package (single one) with a version that is higher than the specified version number in pkg_name and version entries. If so, the notification will not be displayed. If not the user will see the notification before expiration date.\nexpire The expire decides how long to show users the notification. If current date has passed the date in expire, the notification will not be displayed.\nMessage body Use | to start a new line and put the markdown format text body in the next indentation level.\n","categories":"","description":"","excerpt":" SPS notification system In SPS, there is a notification dropdown …","ref":"/sps/adv_features/notification/","tags":"","title":"Notification system"},{"body":"","categories":"","description":"","excerpt":"","ref":"/spr_wf/templates/riboseq/","tags":"","title":"RIBO-Seq"},{"body":" Guidelines from bioconductor_docker.\n Running the systemPipeR with Docker Get a copy of the public docker image docker pull systempipe/systempipe_docker:latest To run RStudio Server: docker run -e PASSWORD=systemPipe -p 8787:8787 \\ systempipe/systempipe_docker:latest You can then open a web browser pointing to your docker host on port 8787. If you’re on Linux and using default settings, the docker host is 127.0.0.1 (or localhost, so the full URL to RStudio would be http://localhost:8787). If you are on Mac or Windows and running Docker Toolbox, you can determine the docker host with the docker-machine ip default command.\nIn the above command, -e PASSWORD= is setting the RStudio password and is required by the RStudio Docker image. It can be whatever you like except it cannot be rstudio. Log in to RStudio with the username rstudio and whatever password was specified, in this example systemPipe.\nTo run R from the command line: docker run -it --user rstudio systempipe/systempipe_docker:latest R To open a Bash shell on the container: docker run -it --user rstudio systempipe/systempipe_docker:latest bash Install Prerequisites: Linux Mac Windows\nInstructions here on how to install Docker Engine on Ubuntu.\nsudo apt-get update sudo apt-get install \\ apt-transport-https \\ ca-certificates \\ curl \\ gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo \\ \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\ $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list \u003e /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io ## Verify that Docker Engine is installed correctly by running the hello-world image. sudo docker run hello-world Uninstall sudo apt-get remove docker docker-engine docker.io containerd runc Docker Hub Account To be able to share a custom image, please go to https://hub.docker.com and create a free account.\n Log in to the Docker Hub locally Login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.\ndocker login # Username: XXXX # Password: xxx # Login Succeeded Run Docker docker run-dP systempipe/systempipe_docker:latest Make sure the container is running:\ndocker ps # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS # NAMES #5d007f66a7b3 systempipe/systempipe_docker:latest \"/init\" 5 minutes ago Up 5 minutes 0.0.0.0:49153-\u003e8787/tcp determined_easle Login to the container Please check the NAMES in this example, determined_easle, to login into the container.\ndocker exec -it determined_easle /bin/bash Other alternatives to run the container To run RStudio Server: docker run -e PASSWORD=systemPipe -p 8787:8787 \\ systempipe/systempipe_docker:latest To run R from the command line: docker run -it --user rstudio systempipe/systempipe_docker:latest R To open a Bash shell on the container: docker run -it --user rstudio systempipe/systempipe_docker:latest bash Check R Version into the container R --version Stop Docker docker stop determined_easle Create your first repository Link Create a repository: Sign in to Docker Hub. Click Create a Repository on the Docker Hub welcome page: Name it /my-repo. Click Create. Build and push a container image to Docker Hub from your computer Start by creating a Dockerfile to specify your application mkdir docker_test cd docker_test touch Dockerfile # Docker inheritance FROM systempipe/systempipe_docker:latest ## Install BiocStyle RUN R -e 'BiocManager::install(\"BiocStyle\")' # Install required Bioconductor package from devel version RUN R -e 'BiocManager::install(\"tgirke/systemPipeR\")' RUN R -e 'BiocManager::install(\"tgirke/systemPipeRdata\")' WORKDIR /home/rstudio/SPRojects COPY --chown=rstudio:rstudio . /home/rstudio/SPRojects # Metadata LABEL name=\"systempipe/systempipe_docker\" \\ version=$BIOCONDUCTOR_DOCKER_systempipe \\ url=\"https://github.com/systemPipeR/systempipe/systempipe_docker\" \\ vendor=\"systemPipeR Project\" \\ maintainer=\"email@gmail.com\" \\ description=\"Bioconductor docker image containing the systemPipeR Project\" \\ license=\"Artistic-2.0\" Run docker build to build your Docker image docker build -t systempipe/systempipe_docker . Run docker run to test your Docker image locally docker run -e PASSWORD=systemPipe -p 8787:8787 systempipe/systempipe_docker:latest Run docker push to push your Docker image to Docker Hub docker push systempipe/systempipe_docker Your repository in Docker Hub should now display a new latest tag under Tags Make changes to the container and Create the new image Create a folder, for example:\ndocker run -dP systempipe/systempipe_docker docker ps ## To check the NAME \u003clucid_grothendieck\u003e docker exec -it lucid_grothendieck /bin/bash root@33c758eb1626:/# R setwd(\"home/rstudio/\") systemPipeRdata::genWorkenvir(\"rnaseq\") exit docker commit -m \"Added rnaseq template\" -a \"Dani Cassol\" lucid_grothendieck dcassol/systempipeworkshop2021:rnaseq docker push systempipe/systempipe_docker:rnaseq Run the new image:\ndocker run -e PASSWORD=systemPipe -p 8787:8787 systempipe/systempipe_docker:rnaseq Commands List which docker machines are available locally {bash, eval=FALSE}docker images\nList running containers {bash, eval=FALSE}docker ps\nList all containers {bash, eval=FALSE}docker ps -a\nResume a stopped container {bash, eval=FALSE}docker start \u003cCONTAINER ID\u003e\nShell into a running container {bash, eval=FALSE}docker exec -it \u003cCONTAINER ID\u003e /bin/bash\nStop OR remove a cointainer {bash, eval=FALSE}docker stop \u003cCONTAINER ID\u003e {bash, eval=FALSE}docker rm \u003cCONTAINER ID\u003e\nRemove a image {bash, eval=FALSE}docker rmi dcassol/systempipeworkshop2021:rnaseq\n Docker and GitHub Actions To create a new token, go to Docker Hub Settings 1.1. Account Settings » Security » New Access Token 1.2. Add Access Token Description » Create 1.3. Copy the Access Token » Copy and Close\nGo to the Repository at GitHub 2.1. Settings \u003e Secrets \u003e New repository secret 2.2. Create a new secret with the name DOCKER_HUB_USERNAME and your Docker ID as value 2.3. Click at Add secret 2.4. Create a new secret with the name DOCKER_HUB_ACCESS_TOKEN and your Personal Access Token (PAT) as value (generated in the previous step)\nSet up the GitHub Actions workflow steps: - name: Checkout Repo uses: actions/checkout@v2 - name: Login to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} Common Problems ## Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.24/auth: dial unix /var/run/docker.sock: connect: permission denied Solution:\nsudo chmod 666 /var/run/docker.sock Singularity Container Please download the Docker image of systemPipe, as follow:\nsingularity pull docker://systempipe/systempipe_docker:latest You can also use the build command to download pre-built images from Docker. Unlike pull, build will convert the image to the latest Singularity image format after downloading it.\nsingularity build systempipe_docker_latest.sif docker://systempipe/systempipe_docker:latest To run the container:\nsingularity shell systempipe_docker_latest.sif Resources Docker Run: How to create images from an application Docker Hub Quickstart Configure GitHub Actions Singularity ","categories":"","description":"","excerpt":" Guidelines from bioconductor_docker.\n Running the systemPipeR with …","ref":"/sp/sp_docker/","tags":"","title":"SPR Docker container"},{"body":" suppressPackageStartupMessages({ library(systemPipeR) }) In the last section, we have learned how to run/manage workflows. In this section, we will learn advanced options how to visualize workflows.\nFirst let’s set up the workflow using the example workflow template. For real production purposes, we recommend you to check out the complex templates over here.\ndependency graph The workflow plot is also called the dependency graph. It shows users how one step is depend on another. This is very important in SPR. A step will not be run unless all dependencies has been executed successfully.\nTo understand a workflow, we can simply call the sal object to print on console like so\nsal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Success ## 2. export_iris --\u003e Status: Success ## 3. gzip --\u003e Status: Success ## Total Files: 3 | Existing: 3 | Missing: 0 ## 3.1. gzip ## cmdlist: 3 | Success: 3 ## 4. gunzip --\u003e Status: Success ## Total Files: 3 | Existing: 3 | Missing: 0 ## 4.1. gunzip ## cmdlist: 3 | Success: 3 ## 5. stats --\u003e Status: Success However, when the workflow becomes very long and complex, the relation between steps are hard to see from console. Workflow plot is the useful tool to understand the workflow.\nFor example, the VARseq workflow is complex, we can show it by:\nsystemPipeRdata::genWorkenvir(\"varseq\") setwd(\"varseq\") sal \u003c- SPRproject() sal \u003c- importWF(sal, file_path = \"systemPipeVARseq.Rmd\") sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_SPR --\u003e Status: Pending ## 2. fastq_report_pre --\u003e Status: Pending ## 3. trimmomatic --\u003e Status: Pending ## Total Files: 32 | Existing: 0 | Missing: 32 ## 3.1. trimmomatic-pe ## cmdlist: 8 | Pending: 8 ## 4. preprocessing --\u003e Status: Pending ## Total Files: 16 | Existing: 0 | Missing: 16 ## 4.1. preprocessReads-pe ## cmdlist: 8 | Pending: 8 ## 5. fastq_report_pos --\u003e Status: Pending ## 6. bwa_index --\u003e Status: Pending ## Total Files: 5 | Existing: 0 | Missing: 5 ## 6.1. bwa_index_-a_bwtsw ## cmdlist: 1 | Pending: 1 ## 7. fasta_index --\u003e Status: Pending ## Total Files: 1 | Existing: 1 | Missing: 0 ## 7.1. gatk_CreateSequenceDictionary ## cmdlist: 1 | Pending: 1 ## 8. faidx_index --\u003e Status: Pending ## Total Files: 1 | Existing: 1 | Missing: 0 ## 8.1. samtools_faidx ## cmdlist: 1 | Pending: 1 ## 9. bwa_alignment --\u003e Status: Pending ## Total Files: 32 | Existing: 0 | Missing: 32 ## 9.1. bwa_mem ## cmdlist: 8 | Pending: 8 ## 9.2. samtools-view ## cmdlist: 8 | Pending: 8 ## 9.3. samtools-sort ## cmdlist: 8 | Pending: 8 ## 9.4. samtools-index ## cmdlist: 8 | Pending: 8 ## 10. align_stats --\u003e Status: Pending ## 11. bam_urls --\u003e Status: Pending ## 12. fastq2ubam --\u003e Status: Pending ## Total Files: 8 | Existing: 0 | Missing: 8 ## 12.1. gatk ## cmdlist: 8 | Pending: 8 ## 13. merge_bam --\u003e Status: Pending ## Total Files: 8 | Existing: 0 | Missing: 8 ## 13.1. gatk ## cmdlist: 8 | Pending: 8 ## 14. sort --\u003e Status: Pending ## Total Files: 8 | Existing: 0 | Missing: 8 ## 14.1. gatk ## cmdlist: 8 | Pending: 8 ## 15. mark_dup --\u003e Status: Pending ## Total Files: 16 | Existing: 0 | Missing: 16 ## 15.1. gatk ## cmdlist: 8 | Pending: 8 ## 16. fix_tag --\u003e Status: Pending ## Total Files: 16 | Existing: 0 | Missing: 16 ## 16.1. gatk ## cmdlist: 8 | Pending: 8 ## 17. hap_caller --\u003e Status: Pending ## Total Files: 16 | Existing: 0 | Missing: 16 ## 17.1. gatk ## cmdlist: 8 | Pending: 8 ## 18. import --\u003e Status: Pending ## Total Files: 1 | Existing: 0 | Missing: 1 ## 18.1. bash ## cmdlist: 1 | Pending: 1 ## 19. call_variants --\u003e Status: Pending ## Total Files: 2 | Existing: 0 | Missing: 2 ## 19.1. gatk ## cmdlist: 1 | Pending: 1 ## 20. filter --\u003e Status: Pending ## Total Files: 2 | Existing: 0 | Missing: 2 ## 20.1. bash ## cmdlist: 1 | Pending: 1 ## 21. create_vcf --\u003e Status: Pending ## Total Files: 8 | Existing: 0 | Missing: 8 ## 21.1. bcftools ## cmdlist: 8 | Pending: 8 ## 22. create_vcf_BCFtool --\u003e Status: Pending ## Total Files: 40 | Existing: 0 | Missing: 40 ## 22.1. mark ## cmdlist: 8 | Pending: 8 ## 22.2. sort ## cmdlist: 8 | Pending: 8 ## 22.3. index ## cmdlist: 8 | Pending: 8 ## 22.4. raw_call ## cmdlist: 8 | Pending: 8 ## 22.5. vcf_call ## cmdlist: 8 | Pending: 8 ## 23. filter_vcf --\u003e Status: Pending ## 24. filter_vcf_BCFtools --\u003e Status: Pending ## 25. annotate_vcf --\u003e Status: Pending ## 26. combine_var --\u003e Status: Pending ## 27. summary_var --\u003e Status: Pending ## 28. venn_diagram --\u003e Status: Pending ## 29. plot_variant --\u003e Status: Pending ## Directly printing the sal object as above does not give us the dependencies between steps and it is hard to see the full picture. Here, we can use plotWF to visualize the full workflow.\nplotWF(sal) {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_SPR - bwa_index - fasta_index - faidx_index - fastq2ubam - merge_bam - sort - mark_dup - fix_tag - hap_caller - create_vcf - filter_vcf - plot_variant\\n }\\n load_SPR - fastq_report_pre\\n faidx_index - bwa_alignment\\n bwa_alignment - merge_bam\\n hap_caller - import\\n filter - create_vcf\\n filter_vcf - annotate_vcf\\n fastq_report_pre - trimmomatic\\n trimmomatic - fastq_report_pos\\n fastq_report_pre - preprocessing\\n bwa_alignment - align_stats\\n bwa_alignment - bam_urls\\n import - call_variants\\n call_variants - filter\\n annotate_vcf - combine_var\\n combine_var - summary_var\\n annotate_vcf - venn_diagram\\n bwa_alignment - create_vcf_BCFtool\\n create_vcf_BCFtool - filter_vcf_BCFtools\\n load_SPR[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_SPR\n0/0/0/1; 0s tooltip=\\\"step load_SPR: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n fastq_report_pre[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=fastq_report_pre\n0/0/0/1; 0s tooltip=\\\"step fastq_report_pre: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n trimmomatic[style=\\\"solid, rounded\\\" label=trimmomatic\n0/0/0/32; 0s , shape=\\\"box\\\" tooltip=\\\"step trimmomatic: 0 samples passed; 0 samples have warnings; 0 samples have errors; 32 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n preprocessing[style=\\\"solid, rounded\\\" label=preprocessing\n0/0/0/16; 0s , shape=\\\"box\\\" tooltip=\\\"step preprocessing: 0 samples passed; 0 samples have warnings; 0 samples have errors; 16 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n fastq_report_pos[style=\\\"solid, \\\"label=fastq_report_pos\n0/0/0/1; 0s tooltip=\\\"step fastq_report_pos: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n bwa_index[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=bwa_index\n0/0/0/5; 0s , shape=\\\"box\\\" tooltip=\\\"step bwa_index: 0 samples passed; 0 samples have warnings; 0 samples have errors; 5 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n fasta_index[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=fasta_index\n1/0/0/1; 0s , shape=\\\"box\\\" tooltip=\\\"step fasta_index: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n faidx_index[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=faidx_index\n1/0/0/1; 0s , shape=\\\"box\\\" tooltip=\\\"step faidx_index: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n bwa_alignment[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=bwa_alignment\n0/0/0/32; 0s , shape=\\\"box\\\" tooltip=\\\"step bwa_alignment: 0 samples passed; 0 samples have warnings; 0 samples have errors; 32 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n align_stats[style=\\\"solid, \\\"label=align_stats\n0/0/0/1; 0s tooltip=\\\"step align_stats: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n bam_urls[style=\\\"solid, \\\"label=bam_urls\n0/0/0/1; 0s tooltip=\\\"step bam_urls: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n fastq2ubam[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=fastq2ubam\n0/0/0/8; 0s , shape=\\\"box\\\" tooltip=\\\"step fastq2ubam: 0 samples passed; 0 samples have warnings; 0 samples have errors; 8 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n merge_bam[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=merge_bam\n0/0/0/8; 0s , shape=\\\"box\\\" tooltip=\\\"step merge_bam: 0 samples passed; 0 samples have warnings; 0 samples have errors; 8 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n sort[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=sort\n0/0/0/8; 0s , shape=\\\"box\\\" tooltip=\\\"step sort: 0 samples passed; 0 samples have warnings; 0 samples have errors; 8 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n mark_dup[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=mark_dup\n0/0/0/16; 0s , shape=\\\"box\\\" tooltip=\\\"step mark_dup: 0 samples passed; 0 samples have warnings; 0 samples have errors; 16 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n fix_tag[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=fix_tag\n0/0/0/16; 0s , shape=\\\"box\\\" tooltip=\\\"step fix_tag: 0 samples passed; 0 samples have warnings; 0 samples have errors; 16 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n hap_caller[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=hap_caller\n0/0/0/16; 0s , shape=\\\"box\\\" tooltip=\\\"step hap_caller: 0 samples passed; 0 samples have warnings; 0 samples have errors; 16 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n import[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=import\n0/0/0/1; 0s , shape=\\\"box\\\" tooltip=\\\"step import: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n call_variants[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=call_variants\n0/0/0/2; 0s , shape=\\\"box\\\" tooltip=\\\"step call_variants: 0 samples passed; 0 samples have warnings; 0 samples have errors; 2 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n filter[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=filter\n0/0/0/2; 0s , shape=\\\"box\\\" tooltip=\\\"step filter: 0 samples passed; 0 samples have warnings; 0 samples have errors; 2 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n create_vcf[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=create_vcf\n0/0/0/8; 0s , shape=\\\"box\\\" tooltip=\\\"step create_vcf: 0 samples passed; 0 samples have warnings; 0 samples have errors; 8 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n create_vcf_BCFtool[style=\\\"solid, rounded\\\" label=create_vcf_BCFtool\n0/0/0/40; 0s , shape=\\\"box\\\" tooltip=\\\"step create_vcf_BCFtool: 0 samples passed; 0 samples have warnings; 0 samples have errors; 40 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n filter_vcf[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=filter_vcf\n0/0/0/1; 0s tooltip=\\\"step filter_vcf: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n filter_vcf_BCFtools[style=\\\"solid, \\\"label=filter_vcf_BCFtools\n0/0/0/1; 0s tooltip=\\\"step filter_vcf_BCFtools: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n annotate_vcf[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=annotate_vcf\n0/0/0/1; 0s tooltip=\\\"step annotate_vcf: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n combine_var[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=combine_var\n0/0/0/1; 0s tooltip=\\\"step combine_var: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n summary_var[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=summary_var\n0/0/0/1; 0s tooltip=\\\"step summary_var: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n venn_diagram[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=venn_diagram\n0/0/0/1; 0s tooltip=\\\"step venn_diagram: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n plot_variant[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=plot_variant\n0/0/0/1; 0s tooltip=\\\"step plot_variant: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-67538412\",\"responsive\":true,\"width\":null,\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Advanced use The VARseq workflow is too large and too complex. Here, for demonstration purposes, we still use the simple workflow.\nsal \u003c- SPRproject() ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' sal \u003c- importWF(sal, file_path = system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\"), verbose = FALSE) plotWF(sal, rstudio = TRUE) {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats\\n }\\n \\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n0/0/0/1; 0s tooltip=\\\"step load_library: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n0/0/0/1; 0s tooltip=\\\"step export_iris: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n0/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 0 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n0/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 0 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n0/0/0/1; 0s tooltip=\\\"step stats: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-24351876\",\"responsive\":true,\"width\":null,\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Rstudio By default, the plot is opened in a new browser tab, because workflow can be very large and long. Viewing in the small Rstudio window is not ideal. This is controlled by the rstudio argument, and it is default rstudio = FALSE. It means whether to open the plot in a new browser or view it inside the current tool, for example many people use IDEs like Rstudio. If you insist to view it in the built-in viewer, or sometimes rendering the R markdown from an interactive session, where we do not want to open in a new browser tab, rstudio = TRUE must be added.\nHeight and width Workflow plot height and width are adjustable by height and width. They can take any valid CSS unit. By default, it take 100% of the parent element width, and automatically calculate the height based on need. Sometimes these fraction based or automatically generated units are not right.\nWe can manually set them\nplotWF(sal, width = \"50%\", rstudio = TRUE) {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats\\n }\\n \\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n0/0/0/1; 0s tooltip=\\\"step load_library: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n0/0/0/1; 0s tooltip=\\\"step export_iris: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n0/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 0 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n0/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 0 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n0/0/0/1; 0s tooltip=\\\"step stats: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-12746853\",\"responsive\":true,\"width\":\"50%\",\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} plotWF(sal, height = \"300px\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats\\n }\\n \\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n0/0/0/1; 0s tooltip=\\\"step load_library: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n0/0/0/1; 0s tooltip=\\\"step export_iris: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n0/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 0 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n0/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 0 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n0/0/0/1; 0s tooltip=\\\"step stats: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-65384271\",\"responsive\":true,\"width\":null,\"height\":\"300px\",\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Color and text On the plot, different colors and numbers indicate different status. This information can be found also in the plot legends.\nShapes:\n circular steps: pure R code steps rounded squares steps: sysargs steps, steps that will invoke command-line calls blue colored steps and arrows: main branch (see main branch section below) Step colors\n black: pending steps Green: successful steps, all pass Orange: successful steps, but some samples have warning Red: failed steps, at least one sample failed Number and colors\n\nThere are 4 numbers in the second row of each step, separated by /\n First No.: number of passed samples Second No.: number of warning samples Third No.: number of error samples Fourth No.: number of total samples Duration\n\nThis is shown after the sample information, as how long it took to run this step. Units are a few seconds (s), some minutes (m), or some hours (h).\nFor example, let’s append a warning step and an error step to the sal\nappendStep(sal) \u003c- LineWise(step_name = \"warning_step\", {warning(\"this creates a warning\")}, dependency = \"stats\") appendStep(sal) \u003c- LineWise(step_name = \"error_step\", {stop(\"this creates an error\")}, dependency = \"stats\") sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## 6. warning_step --\u003e Status: Pending ## 7. error_step --\u003e Status: Pending ## sal \u003c- runWF(sal) Then let’s plot it\nplotWF(sal, width = \"80%\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n stats - warning_step\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-65382147\",\"responsive\":true,\"width\":\"80%\",\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Do you see the color difference?\nOn hover By default plotWF uses SVG to make the plot so it is interactive. When the mouse is hovering on each step, detailed information will be displayed, like sample information, processing time, duration, etc.\nEmbedding In additional to SVG embedding, PNG embedding is supported, but the plot will no longer be interactively, good for browsers without optimal SVG support.\nplotWF(sal, plot_method = \"png\", width = \"80%\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n stats - warning_step\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-72346185\",\"responsive\":true,\"width\":\"80%\",\"height\":null,\"plot_method\":\"renderImageElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Right click on the plot of SVG and PNG, we can see, SVGs are not directly savable, but PNGs are. However, PNGs are not vectorized, so it means it becomes blurry when we zoom in.\nResponsiveness This is a term often used in web development. It means will the plot resize itself if the user resize the document window? By default, plotWF will be responsive, meaning it will fit current window container size and adjust the size once the window size has changed. To always display the full sized plot, use responsive = FALSE. It is useful for embedding the plot in a full-screen mode.\nplotWF(sal, responsive = FALSE, width = \"80%\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n stats - warning_step\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-65713482\",\"responsive\":false,\"width\":\"80%\",\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Now resize your window width and watch plot above vs. other plots.\nPan-zoom The Pan-zoom option enables users to drag the plot instead of scrolling, and to use mouse wheel to zoom in/out. If you do not like the scroll bars in responsive = FALSE, try this option. Note it cannot be used with responsive = TRUE together. If both TRUE, responsive will be automatically set to FALSE. To enable this function internet connection is required to download Javascript libraries on-the-fly.\nplotWF(sal, pan_zoom = TRUE) ## Warning in plotWF(sal, pan_zoom = TRUE): Pan-zoom and responsive cannot be used ## together. Pan-zoom has priority, now `responsive` has set to FALSE {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n stats - warning_step\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-18526374\",\"responsive\":false,\"width\":null,\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":true,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Layout There a few different layout you can choose. There is no best layout. It all depends on the workflow structure you have. The default is compact but we recommend you to try different layouts to find the best fitting one.\n compact: try to plot steps as close as possible. vertical: main branch will be placed vertically and side branches will be placed on the same horizontal level and sub steps of side branches will be placed vertically. horizontal: main branch is placed horizontally and side branches and sub steps will be placed vertically. execution: a linear plot to show the workflow execution order of all steps. Here we are talking about the concept of main branch. It is a way to decide the plot center. We will discuss more below.\nvertical\nplotWF(sal, layout = \"vertical\", height = \"600px\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n rankdir=\\\"TB\\\";\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n subgraph {\\n rank=\\\"same\\\";\\n stats - warning_step\\n }\\n\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-56182347\",\"responsive\":true,\"width\":null,\"height\":\"600px\",\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} If the plot is very long, use height to make it smaller.\nhorizontal\nplotWF(sal, layout = \"horizontal\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n rank=\\\"same\\\";\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n subgraph {\\n rankdir=\\\"TB\\\";\\n stats - warning_step\\n }\\n\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-38612745\",\"responsive\":true,\"width\":null,\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} execution\nplotWF(sal, layout = \"execution\", height = \"600px\", responsive = FALSE) {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n rank=\\\"TB\\\";\\n load_library - export_iris - gzip - gunzip - stats - warning_step - error_step\\n }\\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-72513486\",\"responsive\":false,\"width\":null,\"height\":\"600px\",\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":null,\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} If the plot is too long, we can use height to limit it and/or use responsive to make it scrollable.\nMain branch From the examples above, you can see that there are many steps which do not point to any other steps in downstream. These dead-ends are called ending steps. If we connect the first step, steps in between and these ending step, this will become a branch. Imagine the workflow is a top-bottom tree structure and the root is the first step. Therefore, there are many possible ways to connect the workflow. For the convenience of plotting, we introduce a concept of “main branch”, meaning one of the possible connecting strategies that will be placed at the center of the plot. Other steps that are not in this major branch will surround this major space. This “main branch” will not affect how a workflow is run, but just an algorithm to compute the best visualization. It will have impact on how we plot the workflow.\nThis main branch will not impact the compact layout so much but will have a huge effect on horizontal and vertical layouts.\nThe algorithm in plotWF will automatically choose a best branch for you by default. In simple words, it favors: (a). branches that connect first and last step; (b). as long as possible.\nYou can also choose a branch you want by branch_method = \"choose\". It will first list all possible branches, and then give you a prompt to ask for your favorite branch. Here, for rendering the Rmarkdown, we cannot have a prompt, so we use a second argument in combination, branch_no = x to directly choose a branch and skip the prompt. Also, we use the verbose = TRUE to imitate the branch listing in console. In a real case, you only need branch_method = \"choose\".\nTo have the main branch marked, mark_main_branch = TRUE must be added (default FALSE). Watch closely how the plot change by choosing different branches. Here we use vertical layout to demo. Remember, the main branch is marked in blue.\nChoose branch 1\nplotWF(sal, mark_main_branch = TRUE, layout = \"vertical\", branch_method = \"choose\", branch_no = 1, verbose = FALSE, height = \"450px\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n rankdir=\\\"TB\\\";\\n node[color=\\\"dodgerblue\\\"];\\n load_library - export_iris - gzip - gunzip - stats - warning_step[color=\\\"dodgerblue\\\"]\\n }\\n subgraph {\\n rank=\\\"same\\\";\\n stats - error_step\\n }\\n\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-78153462\",\"responsive\":true,\"width\":null,\"height\":\"450px\",\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Choose branch 2\nplotWF(sal, mark_main_branch = TRUE, layout = \"vertical\", branch_method = \"choose\", branch_no = 2, verbose = FALSE, height = \"450px\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n rankdir=\\\"TB\\\";\\n node[color=\\\"dodgerblue\\\"];\\n load_library - export_iris - gzip - gunzip - stats - error_step[color=\\\"dodgerblue\\\"]\\n }\\n subgraph {\\n rank=\\\"same\\\";\\n stats - warning_step\\n }\\n\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-72463185\",\"responsive\":true,\"width\":null,\"height\":\"450px\",\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Do you see the difference?\nLegends The legend can also be removed by show_legend = FALSE\nplotWF(sal, show_legend = FALSE, height = \"500px\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_library - export_iris - gzip - gunzip - stats - error_step\\n }\\n stats - warning_step\\n \\n load_library[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_library\n1/0/0/1; 0s tooltip=\\\"step load_library: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:49; End time: 2022-06-06 13:47:49; Duration: 00:00:00\\\"]\\n export_iris[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=export_iris\n1/0/0/1; 0s tooltip=\\\"step export_iris: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n gunzip[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=gunzip\n3/0/0/3; 0s , shape=\\\"box\\\" tooltip=\\\"step gunzip: 3 samples passed; 0 samples have warnings; 0 samples have errors; 3 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n stats[style=\\\"solid, \\\"label=stats\n1/0/0/1; 0.2s tooltip=\\\"step stats: 1 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:0.2\\\"]\\n warning_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=warning_step\n0/1/0/1; 0s tooltip=\\\"step warning_step: 0 samples passed; 1 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n error_step[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=error_step\n0/0/1/1; 0s tooltip=\\\"step error_step: 0 samples passed; 0 samples have warnings; 1 samples have errors; 1 samples in total; Start time: 2022-06-06 13:47:50; End time: 2022-06-06 13:47:50; Duration: 00:00:00\\\"]\\n\\n}\\n\",\"plotid\":\"sprwf-46572138\",\"responsive\":true,\"width\":null,\"height\":\"500px\",\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"\"},\"evals\":[],\"jsHooks\":[]} Output formats There are current three output formats: \"html\" and \"dot\", \"dot_print\". If first two were chosen, you also need provide a path out_path to save the file.\n html: a single html file contains the plot. dot: a DOT script file with the code to reproduce the plot in a graphiz DOT engine. dot_print: directly cat the dot script to console. HTML HTML format is very useful if you want to view the plot later or share it to other people. This format is also helpful when you are working on a remote computer cluster. To view the workflow plot, a browser device (viewer) must be available, but often time this is not the case for computer clusters. When you plot a workflow and see the message \"Couldn't get a file descriptor referring to the console\", it means your computer (cluster) does not have a browser device. Saving to HTML format is the best option.\nplotWF(sal, out_format = \"html\", out_path = \"example_out.html\") file.exists(\"example_out.html\") ## [1] TRUE DOT Saving workflow plot to dot format allows one to reproduce the plot with the Graphviz language.\nplotWF(sal, out_format = \"dot\", out_path = \"example_out.dot\") file.exists(\"example_out.dot\") ## [1] TRUE DOT print Instead of saving the Graphviz plotting code to a file, this option directly prints out the code on console. If you have a Graphviz plotting device in hand, simply copy and paste the code to that engine to reproduce the plot. For example, use our Workflow Plot Editor.\nplotWF(sal, out_format = \"dot_print\") Saving Static image file Some users may want to save the plot to a static image, like .png format. We will need do some extra work to save the file. The reason we cannot directly save it to a png file is the plot is generated in real-time by a browser javascript engine. It requires one type of javascript engine, like Chrome, MS Edge, Viewer in Rstudio, to render the plot before we can see it, no matter you use SVG or PNG embedding.\nInteractive With the plot_ctr = TRUE (default) option, a plot control panel is displayed on the top-left corner. One can choose from different formats like png, jpg, svg or pdf to download them from the webpage. To enable these buttons, internet connection is required. The underlying Javascript libraries are download on-the-fly. Please make sure internet is connected. There are known conflicts of underlying web format creating libraries with R markdown web libraries, so some of these buttons may not work inside R markdown as you are seeing in this vignette right now. However, they should work properly if the workflow plot is saved to a stand-alone HTML file. If you are working in Rstudio, you can also use the export button in the viewer to save an image file. Note: due to the web libraries conflicts of this website and the libraries used in plotWF. Some buttons may not work when you click, but it will work when you open make workflow plots interactively and view it in a stand-alone browser tab.\n Non-interactive If you cannot have an interactive session, like submitting a job to a cluster, but still want the png, we recommend to use the {webshot2} package to screenshot the plot. It runs headless Chrome in the back-end (which has a javascript engine).\nInstall the package\nremotes::install_github(\"rstudio/webshot2\") Save to html first\nplotWF(sal, out_format = \"html\", out_path = \"example_out.html\") file.exists(\"example_out.html\") Use webshot2 to save the image\nwebshot2::webshot(\"example_out.html\", \"example_out.png\") In logs The workflow steps will also become clickable if in_log = TRUE. This will create links for each step that navigate to corresponding log section in the SPR workflow log file. Normally this option is handled by SPR log file generating function renderLogs to create this plot on top of the log file, so when a certain step is click, it will navigate to the detailed section down the page.\nVisit this page to see a real example. Try to click on the step in the workflow plot and watch what happens.\nSession sessionInfo() ## R version 4.2.0 (2022-04-22) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.4 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] systemPipeR_2.3.4 ShortRead_1.54.0 ## [3] GenomicAlignments_1.32.0 SummarizedExperiment_1.26.1 ## [5] Biobase_2.56.0 MatrixGenerics_1.8.0 ## [7] matrixStats_0.62.0 BiocParallel_1.30.2 ## [9] Rsamtools_2.12.0 Biostrings_2.64.0 ## [11] XVector_0.36.0 GenomicRanges_1.48.0 ## [13] GenomeInfoDb_1.32.2 IRanges_2.30.0 ## [15] S4Vectors_0.34.0 BiocGenerics_0.42.0 ## ## loaded via a namespace (and not attached): ## [1] lattice_0.20-45 png_0.1-7 assertthat_0.2.1 ## [4] digest_0.6.29 utf8_1.2.2 R6_2.5.1 ## [7] evaluate_0.15 highr_0.9 ggplot2_3.3.6 ## [10] blogdown_1.10 pillar_1.7.0 zlibbioc_1.42.0 ## [13] rlang_1.0.2 rstudioapi_0.13 jquerylib_0.1.4 ## [16] Matrix_1.4-1 rmarkdown_2.14 labeling_0.4.2 ## [19] stringr_1.4.0 htmlwidgets_1.5.4 RCurl_1.98-1.6 ## [22] munsell_0.5.0 DelayedArray_0.22.0 compiler_4.2.0 ## [25] xfun_0.31 pkgconfig_2.0.3 htmltools_0.5.2 ## [28] tidyselect_1.1.2 tibble_3.1.7 GenomeInfoDbData_1.2.8 ## [31] bookdown_0.26 fansi_1.0.3 dplyr_1.0.9 ## [34] crayon_1.5.1 bitops_1.0-7 grid_4.2.0 ## [37] DBI_1.1.2 jsonlite_1.8.0 gtable_0.3.0 ## [40] lifecycle_1.0.1 magrittr_2.0.3 scales_1.2.0 ## [43] cli_3.3.0 stringi_1.7.6 farver_2.1.0 ## [46] hwriter_1.3.2.1 latticeExtra_0.6-29 bslib_0.3.1 ## [49] generics_0.1.2 ellipsis_0.3.2 vctrs_0.4.1 ## [52] RColorBrewer_1.1-3 tools_4.2.0 glue_1.6.2 ## [55] purrr_0.3.4 jpeg_0.1-9 parallel_4.2.0 ## [58] fastmap_1.1.0 yaml_2.3.5 colorspace_2.0-3 ## [61] knitr_1.39 sass_0.4.1 ","categories":"","description":"","excerpt":" …","ref":"/sp/spr/sp_run/step_vis/","tags":"","title":"Visualize workflows"},{"body":" document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Define environment settings and samples A typical workflow starts with generating the expected working environment containing the proper directory structure, input files, and parameter settings. To simplify this task, one can load one of the existing NGS workflows templates provided by systemPipeRdata into the current working directory. The following does this for the rnaseq template. The name of the resulting workflow directory can be specified under the mydirname argument. The default NULL uses the name of the chosen workflow. An error is issued if a directory of the same name and path exists already. On Linux and OS X systems one can also create new workflow instances from the command-line of a terminal as shown here. To apply workflows to custom data, the user needs to modify the targets file and if necessary update the corresponding .cwl and .yml files. A collection of pre-generated .cwl and .yml files are provided in the param/cwl subdirectory of each workflow template. They are also viewable in the GitHub repository of systemPipeRdata (see here).\nlibrary(systemPipeR) library(systemPipeRdata) genWorkenvir(workflow = \"rnaseq\", mydirname = NULL) ## [1] \"Generated rnaseq directory. Next run in rnaseq directory, the R code from *.Rmd template interactively. Alternatively, workflows can be exectued with a single command as instructed in the vignette.\" setwd(\"rnaseq\") Project initialization To create a Workflow within systemPipeR, we can start by defining an empty container and checking the directory structure:\nsal \u003c- SPRproject() ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/rnaseq/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/rnaseq/.SPRproject/SYSargsList.yml' Required packages and resources The systemPipeR package needs to be loaded (H Backman and Girke 2016).\nappendStep(sal) \u003c- LineWise({ library(systemPipeR) }, step_name = \"load_SPR\") Read Preprocessing Preprocessing with preprocessReads function The function preprocessReads allows to apply predefined or custom read preprocessing functions to all FASTQ files referenced in a SYSargsList container, such as quality filtering or adaptor trimming routines. Internally, preprocessReads uses the FastqStreamer function from the ShortRead package to stream through large FASTQ files in a memory-efficient manner. The following example performs adaptor trimming with the trimLRPatterns function from the Biostrings package.\nHere, we are appending this step at the SYSargsList object created previously. All the parameters are defined on the preprocessReads/preprocessReads-se.yml file.\ntargetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") appendStep(sal) \u003c- SYSargsList(step_name = \"preprocessing\", targets = targetspath, dir = TRUE, wf_file = \"preprocessReads/preprocessReads-se.cwl\", input_file = \"preprocessReads/preprocessReads-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = \"load_SPR\") The paths to the resulting output FASTQ files can be checked as follows:\noutfiles(sal)[[2]] ## DataFrame with 18 rows and 1 column ## preprocessReads_se ## \u003ccharacter\u003e ## M1A ./results/M1A.fastq_.. ## M1B ./results/M1B.fastq_.. ## A1A ./results/A1A.fastq_.. ## A1B ./results/A1B.fastq_.. ## V1A ./results/V1A.fastq_.. ## ... ... ## M12B ./results/M12B.fastq.. ## A12A ./results/A12A.fastq.. ## A12B ./results/A12B.fastq.. ## V12A ./results/V12A.fastq.. ## V12B ./results/V12B.fastq.. After the trimming step a new targets file is generated containing the paths to the trimmed FASTQ files. The new targets information can be used for the next workflow step instance, e.g. running the NGS alignments with the trimmed FASTQ files.\nThe following example shows how one can design a custom read preprocessing function using utilities provided by the ShortRead package, and then run it in batch mode with the ‘preprocessReads’ function. For here, it is possible to replace the function used on the preprocessing step and modify the sal object. First, we defined the function:\nappendStep(sal) \u003c- LineWise({ filterFct \u003c- function(fq, cutoff = 20, Nexceptions = 0) { qcount \u003c- rowSums(as(quality(fq), \"matrix\") \u003c= cutoff, na.rm = TRUE) # Retains reads where Phred scores are \u003e= cutoff with N exceptions fq[qcount \u003c= Nexceptions] } }, step_name = \"custom_preprocessing_function\", dependency = \"preprocessing\") After, we can edit the input parameter:\nyamlinput(sal, 2)$Fct yamlinput(sal, 2, \"Fct\") \u003c- \"'filterFct(fq, cutoff=20, Nexceptions=0)'\" yamlinput(sal, 2)$Fct ## check the new function Preprocessing with TrimGalore! TrimGalore! is a wrapper tool to consistently apply quality and adapter trimming to fastq files, with some extra functionality for removing Reduced Representation Bisulfite-Seq (RRBS) libraries.\ntargetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") appendStep(sal) \u003c- SYSargsList(step_name = \"trimGalore\", targets = targetspath, dir = TRUE, wf_file = \"trim_galore/trim_galore-se.cwl\", input_file = \"trim_galore/trim_galore-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = \"load_SPR\", run_step = \"optional\") Preprocessing with Trimmomatic targetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") appendStep(sal) \u003c- SYSargsList(step_name = \"trimmomatic\", targets = targetspath, dir = TRUE, wf_file = \"trimmomatic/trimmomatic-se.cwl\", input_file = \"trimmomatic/trimmomatic-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = \"load_SPR\", run_step = \"optional\") FASTQ quality report The following seeFastq and seeFastqPlot functions generate and plot a series of useful quality statistics for a set of FASTQ files including per cycle quality box plots, base proportions, base-level quality trends, relative k-mer diversity, length and occurrence distribution of reads, number of reads above quality cutoffs and mean quality distribution.\nThe function seeFastq computes the quality statistics and stores the results in a relatively small list object that can be saved to disk with save() and reloaded with load() for later plotting. The argument klength specifies the k-mer length and batchsize the number of reads to a random sample from each FASTQ file.\nappendStep(sal) \u003c- LineWise({ files \u003c- getColumn(sal, step = \"preprocessing\", \"outfiles\") # get outfiles from preprocessing step fqlist \u003c- seeFastq(fastq = files, batchsize = 10000, klength = 8) pdf(\"./results/fastqReport.pdf\", height = 18, width = 4 * length(fqlist)) seeFastqPlot(fqlist) dev.off() }, step_name = \"fastq_quality\", dependency = \"preprocessing\") Figure 1: FASTQ quality report\n Parallelization of FASTQ quality report on a single machine with multiple cores.\nappendStep(sal) \u003c- LineWise({ files \u003c- getColumn(sal, step = \"preprocessing\", \"outfiles\") # get outfiles from preprocessing step f \u003c- function(x) seeFastq(fastq = files[x], batchsize = 1e+05, klength = 8) fqlist \u003c- bplapply(seq(along = files), f, BPPARAM = MulticoreParam(workers = 4)) ## Number of workers = 4 pdf(\"./results/fastqReport.pdf\", height = 18, width = 4 * length(fqlist)) seeFastqPlot(unlist(fqlist, recursive = FALSE)) dev.off() }, step_name = \"fastq_quality\", dependency = \"preprocessing\") NGS Alignment software After quality control, the sequence reads can be aligned to a reference genome or transcriptome database. The following sessions present some NGS sequence alignment software. Select the most accurate aligner and determining the optimal parameter for your custom data set project.\nFor all the following examples, it is necessary to install the respective software and export the PATH accordingly. If it is available Environment Module in the system, you can load all the request software with moduleload(args) function.\nAlignment with HISAT2 The following steps will demonstrate how to use the short read aligner Hisat2 (Kim, Langmead, and Salzberg 2015) in both interactive job submissions and batch submissions to queuing systems of clusters using the systemPipeR's new CWL command-line interface.\n Build Hisat2 index. appendStep(sal) \u003c- SYSargsList(step_name = \"hisat_index\", targets = NULL, dir = FALSE, wf_file = \"hisat2/hisat2-index.cwl\", input_file = \"hisat2/hisat2-index.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = NULL, dependency = \"preprocessing\") The parameter settings of the aligner are defined in the workflow_hisat2-se.cwl and workflow_hisat2-se.yml files. The following shows how to construct the corresponding SYSargsList object, and append to sal workflow.\n Alignment with HISAT2 and SAMtools It possible to build an workflow with HISAT2 and SAMtools.\nappendStep(sal) \u003c- SYSargsList(step_name = \"hisat_mapping\", targets = \"preprocessing\", dir = TRUE, wf_file = \"workflow-hisat2/workflow_hisat2-se.cwl\", input_file = \"workflow-hisat2/workflow_hisat2-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(preprocessReads_se = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = c(\"hisat_index\")) Alignment with Tophat2 The NGS reads of this project can also be aligned against the reference genome sequence using Bowtie2/TopHat2 (Kim et al. 2013; Langmead and Salzberg 2012).\n Build Bowtie2 index. appendStep(sal) \u003c- SYSargsList(step_name = \"bowtie_index\", targets = NULL, dir = FALSE, wf_file = \"bowtie2/bowtie2-index.cwl\", input_file = \"bowtie2/bowtie2-index.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = NULL, dependency = \"preprocessing\", run_step = \"optional\") The parameter settings of the aligner are defined in the workflow_tophat2-mapping.cwl and tophat2-mapping-pe.yml files. The following shows how to construct the corresponding SYSargsList object, using the outfiles from the preprocessing step.\nappendStep(sal) \u003c- SYSargsList(step_name = \"tophat2_mapping\", targets = \"preprocessing\", dir = TRUE, wf_file = \"tophat2/workflow_tophat2-mapping-se.cwl\", input_file = \"tophat2/tophat2-mapping-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(preprocessReads_se = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = c(\"bowtie_index\"), run_session = \"compute\", run_step = \"optional\") Alignment with Bowtie2 (e.g. for miRNA profiling) The following example runs Bowtie2 as a single process without submitting it to a cluster.\nappendStep(sal) \u003c- SYSargsList(step_name = \"bowtie2_mapping\", targets = \"preprocessing\", dir = TRUE, wf_file = \"bowtie2/workflow_bowtie2-mapping-se.cwl\", input_file = \"bowtie2/bowtie2-mapping-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(preprocessReads_se = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = c(\"bowtie_index\"), run_session = \"compute\", run_step = \"optional\") Alignment with BWA-MEM (e.g. for VAR-Seq) The following example runs BWA-MEM as a single process without submitting it to a cluster.\n Build the index: appendStep(sal) \u003c- SYSargsList(step_name = \"bwa_index\", targets = NULL, dir = FALSE, wf_file = \"bwa/bwa-index.cwl\", input_file = \"bwa/bwa-index.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = NULL, dependency = \"preprocessing\", run_step = \"optional\") Prepare the alignment step: appendStep(sal) \u003c- SYSargsList(step_name = \"bwa_mapping\", targets = \"preprocessing\", dir = TRUE, wf_file = \"bwa/bwa-se.cwl\", input_file = \"bwa/bwa-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(preprocessReads_se = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = c(\"bwa_index\"), run_session = \"compute\", run_step = \"optional\") Alignment with Rsubread (e.g. for RNA-Seq) The following example shows how one can use within the environment the R-based aligner , allowing running from R or command-line.\n Build the index: appendStep(sal) \u003c- SYSargsList(step_name = \"rsubread_index\", targets = NULL, dir = FALSE, wf_file = \"rsubread/rsubread-index.cwl\", input_file = \"rsubread/rsubread-index.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = NULL, dependency = \"preprocessing\", run_step = \"optional\") Prepare the alignment step: appendStep(sal) \u003c- SYSargsList(step_name = \"rsubread\", targets = \"preprocessing\", dir = TRUE, wf_file = \"rsubread/rsubread-mapping-se.cwl\", input_file = \"rsubread/rsubread-mapping-se.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(preprocessReads_se = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\"), dependency = c(\"rsubread_index\"), run_session = \"compute\", run_step = \"optional\") Alignment with gsnap (e.g. for VAR-Seq and RNA-Seq) Another R-based short read aligner is gsnap from the gmapR package (Wu and Nacu 2010). The code sample below introduces how to run this aligner on multiple nodes of a compute cluster.\n Build the index: appendStep(sal) \u003c- SYSargsList(step_name = \"gsnap_index\", targets = NULL, dir = FALSE, wf_file = \"gsnap/gsnap-index.cwl\", input_file = \"gsnap/gsnap-index.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = NULL, dependency = \"preprocessing\", run_step = \"optional\") Prepare the alignment step: appendStep(sal) \u003c- SYSargsList(step_name = \"gsnap\", targets = \"targetsPE.txt\", dir = TRUE, wf_file = \"gsnap/gsnap-mapping-pe.cwl\", input_file = \"gsnap/gsnap-mapping-pe.yml\", dir_path = system.file(\"extdata/cwl\", package = \"systemPipeR\"), inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\"), dependency = c(\"gsnap_index\"), run_session = \"compute\", run_step = \"optional\") Create symbolic links for viewing BAM files in IGV The genome browser IGV supports reading of indexed/sorted BAM files via web URLs. This way it can be avoided to create unnecessary copies of these large files. To enable this approach, an HTML directory with Http access needs to be available in the user account (e.g. home/publichtml) of a system. If this is not the case then the BAM files need to be moved or copied to the system where IGV runs. In the following, htmldir defines the path to the HTML directory with http access where the symbolic links to the BAM files will be stored. The corresponding URLs will be written to a text file specified under the _urlfile_ argument.\nappendStep(sal) \u003c- LineWise({ symLink2bam(sysargs = stepsWF(sal)[[7]], htmldir = c(\"~/.html/\", \"somedir/\"), urlbase = \"http://myserver.edu/~username/\", urlfile = \"IGVurl.txt\") }, step_name = \"igv\", dependency = \"hisat_mapping\") Read counting for mRNA profiling experiments Create txdb (needs to be done only once).\nappendStep(sal) \u003c- LineWise({ library(GenomicFeatures) txdb \u003c- makeTxDbFromGFF(file = \"data/tair10.gff\", format = \"gff\", dataSource = \"TAIR\", organism = \"Arabidopsis thaliana\") saveDb(txdb, file = \"./data/tair10.sqlite\") }, step_name = \"create_txdb\", dependency = \"hisat_mapping\") The following performs read counting with summarizeOverlaps in parallel mode with multiple cores.\nappendStep(sal) \u003c- LineWise({ library(BiocParallel) txdb \u003c- loadDb(\"./data/tair10.sqlite\") eByg \u003c- exonsBy(txdb, by = \"gene\") outpaths \u003c- getColumn(sal, step = \"hisat_mapping\", \"outfiles\", column = 2) bfl \u003c- BamFileList(outpaths, yieldSize = 50000, index = character()) multicoreParam \u003c- MulticoreParam(workers = 4) register(multicoreParam) registered() counteByg \u003c- bplapply(bfl, function(x) summarizeOverlaps(eByg, x, mode = \"Union\", ignore.strand = TRUE, inter.feature = TRUE, singleEnd = TRUE)) # Note: for strand-specific RNA-Seq set 'ignore.strand=FALSE' and for PE # data set 'singleEnd=FALSE' countDFeByg \u003c- sapply(seq(along = counteByg), function(x) assays(counteByg[[x]])$counts) rownames(countDFeByg) \u003c- names(rowRanges(counteByg[[1]])) colnames(countDFeByg) \u003c- names(bfl) rpkmDFeByg \u003c- apply(countDFeByg, 2, function(x) returnRPKM(counts = x, ranges = eByg)) write.table(countDFeByg, \"results/countDFeByg.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") write.table(rpkmDFeByg, \"results/rpkmDFeByg.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") }, step_name = \"read_counting\", dependency = \"create_txdb\") Please note, in addition to read counts this step generates RPKM normalized expression values. For most statistical differential expression or abundance analysis methods, such as edgeR or DESeq2, the raw count values should be used as input. The usage of RPKM values should be restricted to specialty applications required by some users, e.g. manually comparing the expression levels of different genes or features.\nRead and alignment count stats Generate a table of read and alignment counts for all samples.\nappendStep(sal) \u003c- LineWise({ read_statsDF \u003c- alignStats(args) write.table(read_statsDF, \"results/alignStats.xls\", row.names = FALSE, quote = FALSE, sep = \"\\t\") }, step_name = \"align_stats\", dependency = \"hisat_mapping\") The following shows the first four lines of the sample alignment stats file provided by the systemPipeR package. For simplicity the number of PE reads is multiplied here by 2 to approximate proper alignment frequencies where each read in a pair is counted.\nread.table(system.file(\"extdata\", \"alignStats.xls\", package = \"systemPipeR\"), header = TRUE)[1:4, ] ## FileName Nreads2x Nalign Perc_Aligned Nalign_Primary Perc_Aligned_Primary ## 1 M1A 192918 177961 92.24697 177961 92.24697 ## 2 M1B 197484 159378 80.70426 159378 80.70426 ## 3 A1A 189870 176055 92.72397 176055 92.72397 ## 4 A1B 188854 147768 78.24457 147768 78.24457 Read counting for miRNA profiling experiments Download miRNA genes from miRBase.\nappendStep(sal) \u003c- LineWise({ system(\"wget https://www.mirbase.org/ftp/CURRENT/genomes/ath.gff3 -P ./data/\") gff \u003c- rtracklayer::import.gff(\"./data/ath.gff3\") gff \u003c- split(gff, elementMetadata(gff)$ID) bams \u003c- getColumn(sal, step = \"bowtie2_mapping\", \"outfiles\", column = 2) bfl \u003c- BamFileList(bams, yieldSize = 50000, index = character()) countDFmiR \u003c- summarizeOverlaps(gff, bfl, mode = \"Union\", ignore.strand = FALSE, inter.feature = FALSE) countDFmiR \u003c- assays(countDFmiR)$counts # Note: inter.feature=FALSE important since pre and mature miRNA ranges # overlap rpkmDFmiR \u003c- apply(countDFmiR, 2, function(x) returnRPKM(counts = x, ranges = gff)) write.table(assays(countDFmiR)$counts, \"results/countDFmiR.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") write.table(rpkmDFmiR, \"results/rpkmDFmiR.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") }, step_name = \"read_counting_mirna\", dependency = \"bowtie2_mapping\") Correlation analysis of samples The following computes the sample-wise Spearman correlation coefficients from the rlog (regularized-logarithm) transformed expression values generated with the DESeq2 package. After transformation to a distance matrix, hierarchical clustering is performed with the hclust function and the result is plotted as a dendrogram (sample_tree.pdf).\nappendStep(sal) \u003c- LineWise({ library(DESeq2, warn.conflicts = FALSE, quietly = TRUE) library(ape, warn.conflicts = FALSE) countDFpath \u003c- system.file(\"extdata\", \"countDFeByg.xls\", package = \"systemPipeR\") countDF \u003c- as.matrix(read.table(countDFpath)) colData \u003c- data.frame(row.names = targetsWF(sal)[[2]]$SampleName, condition = targetsWF(sal)[[2]]$Factor) dds \u003c- DESeqDataSetFromMatrix(countData = countDF, colData = colData, design = ~condition) d \u003c- cor(assay(rlog(dds)), method = \"spearman\") hc \u003c- hclust(dist(1 - d)) plot.phylo(as.phylo(hc), type = \"p\", edge.col = 4, edge.width = 3, show.node.label = TRUE, no.margin = TRUE) }, step_name = \"sample_tree_rlog\", dependency = \"read_counting\") Figure 2: Correlation dendrogram of samples for rlog values.\n DEG analysis with edgeR The following *run_edgeR* function is a convenience wrapper for identifying differentially expressed genes (DEGs) in batch mode with *edgeR’s GML method (Robinson, McCarthy, and Smyth 2010) for any number of pairwise sample comparisons specified under the cmp* argument. Users are strongly encouraged to consult the edgeR vignette for more detailed information on this topic and how to properly run edgeR on data sets with more complex experimental designs.\nappendStep(sal) \u003c- LineWise({ targetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") targets \u003c- read.delim(targetspath, comment = \"#\") cmp \u003c- readComp(file = targetspath, format = \"matrix\", delim = \"-\") countDFeBygpath \u003c- system.file(\"extdata\", \"countDFeByg.xls\", package = \"systemPipeR\") countDFeByg \u003c- read.delim(countDFeBygpath, row.names = 1) edgeDF \u003c- run_edgeR(countDF = countDFeByg, targets = targets, cmp = cmp[[1]], independent = FALSE, mdsplot = \"\") DEG_list \u003c- filterDEGs(degDF = edgeDF, filter = c(Fold = 2, FDR = 10)) }, step_name = \"edger\", dependency = \"read_counting\") Filter and plot DEG results for up and down-regulated genes. Because of the small size of the toy data set used by this vignette, the FDR value has been set to a relatively high threshold (here 10%). More commonly used FDR cutoffs are 1% or 5%. The definition of ‘up’ and ‘down’ is given in the corresponding help file. To open it, type ?filterDEGs in the R console.\n Figure 3: Up and down regulated DEGs identified by edgeR.\n DEG analysis with DESeq2 The following *run_DESeq2* function is a convenience wrapper for identifying DEGs in batch mode with DESeq2* (Love, Huber, and Anders 2014) for any number of pairwise sample comparisons specified under the cmp* argument. Users are strongly encouraged to consult the DESeq2 vignette for more detailed information on this topic and how to properly run DESeq2 on data sets with more complex experimental designs.\nappendStep(sal) \u003c- LineWise({ degseqDF \u003c- run_DESeq2(countDF = countDFeByg, targets = targets, cmp = cmp[[1]], independent = FALSE) DEG_list2 \u003c- filterDEGs(degDF = degseqDF, filter = c(Fold = 2, FDR = 10)) }, step_name = \"deseq2\", dependency = \"read_counting\") Venn Diagrams The function overLapper can compute Venn intersects for large numbers of sample sets (up to 20 or more) and vennPlot can plot 2-5 way Venn diagrams. A useful feature is the possibility to combine the counts from several Venn comparisons with the same number of sample sets in a single Venn diagram (here for 4 up and down DEG sets).\nappendStep(sal) \u003c- LineWise({ vennsetup \u003c- overLapper(DEG_list$Up[6:9], type = \"vennsets\") vennsetdown \u003c- overLapper(DEG_list$Down[6:9], type = \"vennsets\") vennPlot(list(vennsetup, vennsetdown), mymain = \"\", mysub = \"\", colmode = 2, ccol = c(\"blue\", \"red\")) }, step_name = \"vennplot\", dependency = \"edger\") Figure 4: Venn Diagram for 4 Up and Down DEG Sets.\n GO term enrichment analysis of DEGs Obtain gene-to-GO mappings The following shows how to obtain gene-to-GO mappings from biomaRt (here for A. thaliana) and how to organize them for the downstream GO term enrichment analysis. Alternatively, the gene-to-GO mappings can be obtained for many organisms from Bioconductor’s *.db genome annotation packages or GO annotation files provided by various genome databases. For each annotation, this relatively slow preprocessing step needs to be performed only once. Subsequently, the preprocessed data can be loaded with the load function as shown in the next subsection.\nappendStep(sal) \u003c- LineWise({ library(\"biomaRt\") listMarts() # To choose BioMart database listMarts(host = \"plants.ensembl.org\") m \u003c- useMart(\"plants_mart\", host = \"https://plants.ensembl.org\") listDatasets(m) m \u003c- useMart(\"plants_mart\", dataset = \"athaliana_eg_gene\", host = \"https://plants.ensembl.org\") listAttributes(m) # Choose data types you want to download go \u003c- getBM(attributes = c(\"go_id\", \"tair_locus\", \"namespace_1003\"), mart = m) go \u003c- go[go[, 3] != \"\", ] go[, 3] \u003c- as.character(go[, 3]) go[go[, 3] == \"molecular_function\", 3] \u003c- \"F\" go[go[, 3] == \"biological_process\", 3] \u003c- \"P\" go[go[, 3] == \"cellular_component\", 3] \u003c- \"C\" go[1:4, ] dir.create(\"./data/GO\") write.table(go, \"data/GO/GOannotationsBiomart_mod.txt\", quote = FALSE, row.names = FALSE, col.names = FALSE, sep = \"\\t\") catdb \u003c- makeCATdb(myfile = \"data/GO/GOannotationsBiomart_mod.txt\", lib = NULL, org = \"\", colno = c(1, 2, 3), idconv = NULL) save(catdb, file = \"data/GO/catdb.RData\") }, step_name = \"get_go_biomart\", dependency = \"edger\") Batch GO term enrichment analysis Apply the enrichment analysis to the DEG sets obtained in the above differential expression analysis. Note, in the following example the FDR filter is set here to an unreasonably high value, simply because of the small size of the toy data set used in this vignette. Batch enrichment analysis of many gene sets is performed with the GOCluster_Report function. When method=\"all\", it returns all GO terms passing the p-value cutoff specified under the cutoff arguments. When method=\"slim\", it returns only the GO terms specified under the myslimv argument. The given example shows how one can obtain such a GO slim vector from BioMart for a specific organism.\nappendStep(sal) \u003c- LineWise({ load(\"data/GO/catdb.RData\") DEG_list \u003c- filterDEGs(degDF = edgeDF, filter = c(Fold = 2, FDR = 50), plot = FALSE) up_down \u003c- DEG_list$UporDown names(up_down) \u003c- paste(names(up_down), \"_up_down\", sep = \"\") up \u003c- DEG_list$Up names(up) \u003c- paste(names(up), \"_up\", sep = \"\") down \u003c- DEG_list$Down names(down) \u003c- paste(names(down), \"_down\", sep = \"\") DEGlist \u003c- c(up_down, up, down) DEGlist \u003c- DEGlist[sapply(DEGlist, length) \u003e 0] BatchResult \u003c- GOCluster_Report(catdb = catdb, setlist = DEGlist, method = \"all\", id_type = \"gene\", CLSZ = 2, cutoff = 0.9, gocats = c(\"MF\", \"BP\", \"CC\"), recordSpecGO = NULL) library(\"biomaRt\") m \u003c- useMart(\"plants_mart\", dataset = \"athaliana_eg_gene\", host = \"https://plants.ensembl.org\") goslimvec \u003c- as.character(getBM(attributes = c(\"goslim_goa_accession\"), mart = m)[, 1]) BatchResultslim \u003c- GOCluster_Report(catdb = catdb, setlist = DEGlist, method = \"slim\", id_type = \"gene\", myslimv = goslimvec, CLSZ = 10, cutoff = 0.01, gocats = c(\"MF\", \"BP\", \"CC\"), recordSpecGO = NULL) gos \u003c- BatchResultslim[grep(\"M6-V6_up_down\", BatchResultslim$CLID), ] gos \u003c- BatchResultslim pdf(\"GOslimbarplotMF.pdf\", height = 8, width = 10) goBarplot(gos, gocat = \"MF\") dev.off() goBarplot(gos, gocat = \"BP\") goBarplot(gos, gocat = \"CC\") }, step_name = \"go_enrichment\", dependency = \"get_go_biomart\") Plot batch GO term results The data.frame generated by GOCluster_Report can be plotted with the goBarplot function. Because of the variable size of the sample sets, it may not always be desirable to show the results from different DEG sets in the same bar plot. Plotting single sample sets is achieved by subsetting the input data frame as shown in the first line of the following example.\n Figure 5: GO Slim Barplot for MF Ontology.\n Clustering and heat maps The following example performs hierarchical clustering on the rlog transformed expression matrix subsetted by the DEGs identified in the above differential expression analysis. It uses a Pearson correlation-based distance measure and complete linkage for cluster join.\nappendStep(sal) \u003c- LineWise({ library(pheatmap) geneids \u003c- unique(as.character(unlist(DEG_list[[1]]))) y \u003c- assay(rlog(dds))[geneids, ] pdf(\"heatmap1.pdf\") pheatmap(y, scale = \"row\", clustering_distance_rows = \"correlation\", clustering_distance_cols = \"correlation\") dev.off() }, step_name = \"hierarchical_clustering\", dependency = c(\"sample_tree_rlog\", \"edger\")) Figure 7: Heat map with hierarchical clustering dendrograms of DEGs.\n Visualize workflow systemPipeR workflows instances can be visualized with the plotWF function.\nThis function will make a plot of selected workflow instance and the following information is displayed on the plot:\n Workflow structure (dependency graphs between different steps); Workflow step status, e.g. Success, Error, Pending, Warnings; Sample status and statistics; Workflow timing: running duration time. If no argument is provided, the basic plot will automatically detect width, height, layout, plot method, branches, etc.\nplotWF(sal, show_legend = TRUE, width = \"80%\") {\"x\":{\"dot\":\"digraph {\\n node[fontsize=20];\\n subgraph {\\n load_SPR - preprocessing - hisat_index - hisat_mapping - create_txdb - read_counting - sample_tree_rlog - hierarchical_clustering\\n }\\n preprocessing - fastq_quality\\n hisat_mapping - igv\\n read_counting - edger\\n edger - hierarchical_clustering\\n read_counting - deseq2\\n hisat_mapping - align_stats\\n preprocessing - bowtie_index\\n preprocessing - bwa_index\\n preprocessing - rsubread_index\\n preprocessing - gsnap_index\\n load_SPR - trimGalore\\n load_SPR - trimmomatic\\n edger - vennplot\\n edger - get_go_biomart\\n get_go_biomart - go_enrichment\\n bowtie_index - tophat2_mapping\\n bowtie_index - bowtie2_mapping\\n bowtie2_mapping - read_counting_mirna\\n bwa_index - bwa_mapping\\n rsubread_index - rsubread\\n gsnap_index - gsnap\\n load_SPR[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=load_SPR\n0/0/0/1; 0s tooltip=\\\"step load_SPR: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n preprocessing[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=preprocessing\n0/0/0/18; 0s , shape=\\\"box\\\" tooltip=\\\"step preprocessing: 0 samples passed; 0 samples have warnings; 0 samples have errors; 18 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n trimGalore[style=\\\"solid, rounded\\\" label=trimGalore\n0/0/0/36; 0s , shape=\\\"box\\\" tooltip=\\\"step trimGalore: 0 samples passed; 0 samples have warnings; 0 samples have errors; 36 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n trimmomatic[style=\\\"solid, rounded\\\" label=trimmomatic\n0/0/0/18; 0s , shape=\\\"box\\\" tooltip=\\\"step trimmomatic: 0 samples passed; 0 samples have warnings; 0 samples have errors; 18 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n fastq_quality[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=fastq_quality\n0/0/0/1; 0s tooltip=\\\"step fastq_quality: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n hisat_index[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=hisat_index\n0/0/0/8; 0s , shape=\\\"box\\\" tooltip=\\\"step hisat_index: 0 samples passed; 0 samples have warnings; 0 samples have errors; 8 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n hisat_mapping[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, rounded\\\" label=hisat_mapping\n0/0/0/72; 0s , shape=\\\"box\\\" tooltip=\\\"step hisat_mapping: 0 samples passed; 0 samples have warnings; 0 samples have errors; 72 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n bowtie_index[style=\\\"solid, rounded\\\" label=bowtie_index\n0/0/0/6; 0s , shape=\\\"box\\\" tooltip=\\\"step bowtie_index: 0 samples passed; 0 samples have warnings; 0 samples have errors; 6 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n tophat2_mapping[style=\\\"dashed, rounded\\\" label=tophat2_mapping\n0/0/0/90; 0s , shape=\\\"box\\\" tooltip=\\\"step tophat2_mapping: 0 samples passed; 0 samples have warnings; 0 samples have errors; 90 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n bowtie2_mapping[style=\\\"dashed, rounded\\\" label=bowtie2_mapping\n0/0/0/18; 0s , shape=\\\"box\\\" tooltip=\\\"step bowtie2_mapping: 0 samples passed; 0 samples have warnings; 0 samples have errors; 18 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n bwa_index[style=\\\"solid, rounded\\\" label=bwa_index\n0/0/0/5; 0s , shape=\\\"box\\\" tooltip=\\\"step bwa_index: 0 samples passed; 0 samples have warnings; 0 samples have errors; 5 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n bwa_mapping[style=\\\"dashed, rounded\\\" label=bwa_mapping\n0/0/0/18; 0s , shape=\\\"box\\\" tooltip=\\\"step bwa_mapping: 0 samples passed; 0 samples have warnings; 0 samples have errors; 18 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n rsubread_index[style=\\\"solid, rounded\\\" label=rsubread_index\n0/0/0/5; 0s , shape=\\\"box\\\" tooltip=\\\"step rsubread_index: 0 samples passed; 0 samples have warnings; 0 samples have errors; 5 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n rsubread[style=\\\"dashed, rounded\\\" label=rsubread\n0/0/0/54; 0s , shape=\\\"box\\\" tooltip=\\\"step rsubread: 0 samples passed; 0 samples have warnings; 0 samples have errors; 54 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n gsnap_index[style=\\\"solid, rounded\\\" label=gsnap_index\n0/0/0/2; 0s , shape=\\\"box\\\" tooltip=\\\"step gsnap_index: 0 samples passed; 0 samples have warnings; 0 samples have errors; 2 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n gsnap[style=\\\"dashed, rounded\\\" label=gsnap\n0/0/0/36; 0s , shape=\\\"box\\\" tooltip=\\\"step gsnap: 0 samples passed; 0 samples have warnings; 0 samples have errors; 36 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n igv[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=igv\n0/0/0/1; 0s tooltip=\\\"step igv: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n create_txdb[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=create_txdb\n0/0/0/1; 0s tooltip=\\\"step create_txdb: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n read_counting[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=read_counting\n0/0/0/1; 0s tooltip=\\\"step read_counting: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n align_stats[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=align_stats\n0/0/0/1; 0s tooltip=\\\"step align_stats: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n read_counting_mirna[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=read_counting_mirna\n0/0/0/1; 0s tooltip=\\\"step read_counting_mirna: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n sample_tree_rlog[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=sample_tree_rlog\n0/0/0/1; 0s tooltip=\\\"step sample_tree_rlog: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n edger[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=edger\n0/0/0/1; 0s tooltip=\\\"step edger: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n deseq2[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=deseq2\n0/0/0/1; 0s tooltip=\\\"step deseq2: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n vennplot[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=vennplot\n0/0/0/1; 0s tooltip=\\\"step vennplot: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n get_go_biomart[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=get_go_biomart\n0/0/0/1; 0s tooltip=\\\"step get_go_biomart: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n go_enrichment[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=go_enrichment\n0/0/0/1; 0s tooltip=\\\"step go_enrichment: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n hierarchical_clustering[fillcolor=\\\"#d3d6eb\\\" style=\\\"filled, \\\"label=hierarchical_clustering\n0/0/0/1; 0s tooltip=\\\"step hierarchical_clustering: 0 samples passed; 0 samples have warnings; 0 samples have errors; 1 samples in total; Start time: 2022-06-03 19:02:27; End time: 2022-06-03 19:02:27; Duration: 00:00:00\\\"]\\n subgraph cluster_legend {\\n rankdir=TB;\\n color=\\\"#eeeeee\\\";\\n style=filled;\\n ranksep =1;\\n label=\\\"Legends\\\";\\n fontsize = 30;\\n node [style=filled, fontsize=10];\\n legend_img- step_state[color=\\\"#eeeeee\\\"];\\n\\n legend_img[shape=none, image=\\\"plotwf_legend-src.png\\\", label = \\\" \\\", height=1, width=3, style=\\\"\\\"];\\n\\n step_state[style=\\\"filled\\\", shape=\\\"box\\\" color=white, label =\\n Step Colors\\n Pending steps; Successful steps; Failed steps\\n Targets Files / Code Chunk 0 (pass) | 0 (warning) | 0 (error) | 0 (total); Duration\\n ];\\n\\n }\\n\\n}\\n\",\"plotid\":\"sprwf-28743165\",\"responsive\":true,\"width\":\"80%\",\"height\":null,\"plot_method\":\"renderSVGElement\",\"rmd\":true,\"msg\":\"\",\"plot_ctr\":true,\"pan_zoom\":false,\"legend_uri\":\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBEbyBub3QgZWRpdCB0aGlzIGZpbGUgd2l0aCBlZGl0b3JzIG90aGVyIHRoYW4gZGlhZ3JhbXMubmV0IC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ5NnB4IiBoZWlnaHQ9IjI3OHB4IiB2aWV3Qm94PSItMC41IC0wLjUgNDk2IDI3OCIgY29udGVudD0iJmx0O214ZmlsZSBob3N0PSZxdW90O2FwcC5kaWFncmFtcy5uZXQmcXVvdDsgbW9kaWZpZWQ9JnF1b3Q7MjAyMS0xMS0yNFQyMDozOTo0NC45MjNaJnF1b3Q7IGFnZW50PSZxdW90OzUuMCAoWDExOyBMaW51eCB4ODZfNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85Ni4wLjQ2NjQuNDUgU2FmYXJpLzUzNy4zNiZxdW90OyB2ZXJzaW9uPSZxdW90OzE1LjguMyZxdW90OyBldGFnPSZxdW90O1RfZEV4bkw3U0xYMmJ1WDhQYVgzJnF1b3Q7IHR5cGU9JnF1b3Q7Z29vZ2xlJnF1b3Q7Jmd0OyZsdDtkaWFncmFtIGlkPSZxdW90O1Z3OVZWaUdzeC1zTF9OaktlN0pQJnF1b3Q7Jmd0OzdWcmJjdUk0RVAwYUhwT3lKZDk0REFSbVhtWjNLMnpWUGl0WUdGVmt5V1BMZ2N6WHIyVEwrQ0lEM3NHUVRSVWtsZGd0cVMyZDAycDF0NW5BZWJ6L2xxSmsrNE9IbUU2QUZlNG44SGtDZ0EwQW1LaGZLL3pRRXN2eFMwbVVrbERMYXNHSy9NSlZSeTNOU1lpelZrZkJPUlVrYVF2WG5ERzhGaTBaU2xPK2EzZmJjTnArYW9JaWJBaFdhMFJONlQ4a0ZOdFNPcldzV3Y0ZGsyaGJQZG1yV21KVWRkYUNiSXRDdm11STRHSUM1eW5ub3J5SzkzTk1GWG9WTHVXNDVaSFd3OFJTek1TUUFacUpkMFJ6dlRZOUwvRlJMVFpLZVo1TTRFeitZeUZXNHl4NWQ1aTR1dEZLY0Nyd3ZvOEE5Rm9wczh3SjJvZGxTNFBCUE1ZaS9aQmRLa1dCSHFKdEJVQjl2NnVCQjQ1YnlyWk4wS0duQ2Rka1J3ZmROUjd5UWtQU0R3ODhEMDhibHQyV0NMeEswRnExN3FUNVM5bFd4Rkwvc3kwdk40VFNPYWM4TGNiQzBNVkI2Q2cwUmNyZmNOWENPSlBEWnhGRldkWUhkL2FHeFhwN0R2c214cUFmWTQycEE0ZEI2b3lBcUhOZFJKZkxSZkM4T0lib1ZWRU1wZ05SOUM5SDBiMHVpb3ZsRWl6bnQwWHhMR3p3Y3RpOHNXSGpUT2pUS1RCUjNManFSOG9SSlJHVE1vbzM0aGlvU2xWamJQbVJjaTRmVG9ReXNXQkVoSDNyU2c3VE54RE9PSldOWFpqbDlFVWJ5d3FrdFZ3R2xpak0xQ0tKUEhPZmRFTk13bEFObjZVNEk3LzBrYUl3U1RoaG9waXpPNXU0ejBwWExuaFc4bUlmQmJ4QlZvT0RKcDN5ZG9saVFoWDZmNU5ZUmh6QStnUHY1TjhYSGlNMmxJN1RCeHp3L1VlM2ZjUUIwNVBBSHNLcXcvUVN2Z0tEcnhCbFczd243RGhoMEhVTndnS0RNT2RLaEUwTnduNGdKdVBOV00zK3E1Rm0yN2ZiWm03dzZIZG9jODFRc3M4eGprRmJsYmswZUp2ek9Na0Z2cE4yWXFzNXhsYnI0Y3k3Rm1kMlQ3amcwZUlJVCtRU202eDVQM09Wc2hXNFBKVDRQc2tPUWJLdjIrUlZwUDdMcDhoRUZWZTY1RFJLZFdXcllROVY5LzhVeElWNGczSXFicmU5dktETGxPOFpUTG4yWTA5a0IwWUlpRzB6a1gyNTc2d1RmQVYyaHk5bzlXU0IxOXBaWmw0dHZhRmNYUGhBQ2J1N3hGTXVFWFpkSXJSc2c3amdXc1NaNlh1cTZqc3NvaVpyZFNwbFgrSzhQaUhBQTBOOEdlajFaZTRJSUEvSTdqRUxuMVFoc3piSEJwYWRTbDFoejFXZEVoNHd3cUZSNUR5TFVIUDlQU1pXeVZKTWtTRHZiZlY5a09nbi9LWDJaUE13bVQ2Q0RnUGRxa25HODNTTjlVRFFLSEIyZEVGZ0czRmZWNWRBYVlTRm9hdmc2YkQ0WWRRTnFEQmNSSjNPenNyTy8zY2VaYWJVQWQ1N0RLeHAvWEYvajFQSE1sTG1NNXBIWk5pc2NNZ0VMRVNDNjAxK1A3ZU9CSWhkcHdvZDA2bGVMWlEzNnh4L0pvSndodWlkdEZNbm9UV0F0RDRQTWdwcFpxMWpsUHhMd1RzMCticm83UTRNUGZ4NnF1QjdpK3BpKy9VWkJHYVU3L2k5a2N3SURBS3o2akVLZzR6TGxsdlJ1Q3crbjB1akdaTGVtRWl6RlBLU00wWllORkhxU3hKZTB5R0UycFprdEtDeVErb0taNW4weUYvSUgrczVkdDRFMmRiTnpNSU9nbllZQkwzS0FzNzRaemlHVVpnMWw4b1VRdkora1MyYzlSS3ZhUDBXRmJ2NllWMHlvL1NKRkxHc2dtK21mTVRBNXgyTStZZzdPWWlMaGVreCtHZE8wcTlXZVA5OG0vWGJOZ3VCR1ZIMFZlRkhzVml6N3JRU09CblBoODJMcjJ6Y3JXRzROVXhoMjRNRlpqR3I3MVhhYjFpRHZLMi9WMVZtZnZYWDArRGlYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjQiIHk9IjkwIiB3aWR0aD0iNDkwIiBoZWlnaHQ9IjkyIiBmaWxsPSIjZDVlOGQ0IiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iMTgyIiB3aWR0aD0iNDkwIiBoZWlnaHQ9Ijk0IiBmaWxsPSIjZmZlOGRlIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjQ5MCIgaGVpZ2h0PSI4NiIgZmlsbD0iI2VmZjJmYyIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjcyIiBmaWxsLW9wYWNpdHk9IjAuOCIgZmlsbD0iI2Y1ZjVmNSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMXB4OyBtYXJnaW4tbGVmdDogMTE1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogOHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPnNvbGlkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5zb2xpZDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwcHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiA4cHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+ZGFzaGVkPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5OCIgeT0iMTIiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iOHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5kYXNoZWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAzMnB4OyBtYXJnaW4tbGVmdDogMTE2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5NYW5hZ2VtZW50PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMzUiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTFweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TWFuYWdlbWVudDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMycHg7IG1hcmdpbi1sZWZ0OiAxOThweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMXB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkNvbXB1dGU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIzNSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21wdXRlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZWxsaXBzZSBjeD0iMjMyLjUiIGN5PSIxMjMiIHJ4PSI1MS41IiByeT0iMjciIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjJweDsgbWFyZ2luLWxlZnQ6IDkycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+ZWxsaXBzZTwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTE2IiB5PSI2NSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5lbGxpcHNlPC90ZXh0Pjwvc3dpdGNoPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogODVweDsgbWFyZ2luLWxlZnQ6IDExNHB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+UjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTQiIHk9Ijg4IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlI8L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA4M3B4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5Db21tYW5kLWxpbmU8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSI4NiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5Db21tYW5kLWxpbmU8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iOTYiIHdpZHRoPSIxMDUiIGhlaWdodD0iNTAiIHJ4PSI3LjUiIHJ5PSI3LjUiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMSkiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDUxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNjFweDsgbWFyZ2luLWxlZnQ6IDE3NnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDhweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPnJlY3RhbmdsZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyMDEiIHk9IjYzIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjhweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cmVjdGFuZ2xlPC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDE4Mi41IDM4IEwgMjg3LjUgMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIi8+PHBhdGggZD0iTSAzNTQgMzcuNjIgTCA0NTkgMzcuNjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiYSgwLCAwLCAwLCAxKSIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IjE4IDE4IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMjhweDsgbWFyZ2luLWxlZnQ6IDExNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDExcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+TWFuZGF0b3J5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNSIgeT0iMTMxIiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjExcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1hbmRhdG9yeTwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyOHB4OyBtYXJnaW4tbGVmdDogMTk4cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTFweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5PcHRpb25hbDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxOTgiIHk9IjEzMSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMXB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5PcHRpb25hbDwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTg0IiB5PSIxOTAiIHdpZHRoPSI5NSIgaGVpZ2h0PSI0MCIgZmlsbD0iI2QzZDZlYiIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDQ2cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA1cHg7IG1hcmdpbi1sZWZ0OiA5M3B4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOiA4cHgiPmZpbGw8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExNiIgeT0iMTA5IiBmaWxsPSJyZ2JhKDAsIDAsIDAsIDEpIiBmb250LWZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmZpbGw8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjM0OSIgeT0iMTkwIiB3aWR0aD0iOTUiIGhlaWdodD0iNDAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9Im5vbmUiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpc2NhbGUoMikiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA0NnB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogMTc2cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6IDhweCI+bm8gZmlsbDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk4IiB5PSIxMDkiIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+bm8gZmlsbDwvdGV4dD48L3N3aXRjaD48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KXNjYWxlKDIpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMXB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDI0cHg7IG1hcmdpbi1sZWZ0OiAzNXB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2JhKDAsIDAsIDAsIDEpOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtUaW1lcyBOZXcgUm9tYW4mcXVvdDs7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBub25lOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPlJ1bm5pbmcgPGJyIHN0eWxlPSJmb250LXNpemU6IDEwcHgiIC8+U2Vzc2lvbjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzNSIgeT0iMjciIGZpbGw9InJnYmEoMCwgMCwgMCwgMSkiIGZvbnQtZmFtaWx5PSJUaW1lcyBOZXcgUm9tYW4iIGZvbnQtc2l6ZT0iMTBweCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlJ1bm5pbmcuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTNweDsgbWFyZ2luLWxlZnQ6IDM1cHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYmEoMCwgMCwgMCwgMSk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTBweDsgZm9udC1mYW1pbHk6ICZxdW90O1RpbWVzIE5ldyBSb21hbiZxdW90OzsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IG5vbmU7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxMHB4Ij48c3BhbiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgOyBmb250LXNpemU6IDEwcHgiPlJ1bm5pbmc8L3NwYW4+PC9kaXY+UmVxdWlyZW1lbnQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzUiIHk9IjExNiIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+UnVubmluZ1JlcXVpcmUuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSlzY2FsZSgyKSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA2OHB4OyBtYXJnaW4tbGVmdDogMzVweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiYSgwLCAwLCAwLCAxKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogJnF1b3Q7VGltZXMgTmV3IFJvbWFuJnF1b3Q7OyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogbm9uZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5TdGVwIDxiciBzdHlsZT0iZm9udC1zaXplOiAxMHB4IiAvPkNsYXNzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjM1IiB5PSI3MSIgZmlsbD0icmdiYSgwLCAwLCAwLCAxKSIgZm9udC1mYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIgZm9udC1zaXplPSIxMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iYm9sZCI+U3RlcC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3LmRpYWdyYW1zLm5ldC9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5WaWV3ZXIgZG9lcyBub3Qgc3VwcG9ydCBmdWxsIFNWRyAxLjE8L3RleHQ+PC9hPjwvc3dpdGNoPjwvc3ZnPg==\"},\"evals\":[],\"jsHooks\":[]} Running the workflow For running the workflow, runWF function will execute all the command lines store in the workflow container.\nsal \u003c- runWF(sal) Interactive job submissions in a single machine To simplify the short read alignment execution for the user, the command-line can be run with the runCommandline function. The execution will be on a single machine without submitting to a queuing system of a computer cluster. This way, the input FASTQ files will be processed sequentially. By default runCommandline auto detects SAM file outputs and converts them to sorted and indexed BAM files, using internally the Rsamtools package (Morgan et al. 2019). Besides, runCommandline allows the user to create a dedicated results folder for each workflow and a sub-folder for each sample defined in the targets file. This includes all the output and log files for each step. When these options are used, the output location will be updated by default and can be assigned to the same object.\nIf available, multiple CPU cores can be used for processing each file. The number of CPU cores (here 4) to use for each process is defined in the *.yml file. With yamlinput(args)['thread'] one can return this value from the SYSargs2 object.\nParallelization on clusters Alternatively, the computation can be greatly accelerated by processing many files in parallel using several compute nodes of a cluster, where a scheduling/queuing system is used for load balancing. For this the clusterRun function submits the computing requests to the scheduler using the run specifications defined by runCommandline.\nTo avoid over-subscription of CPU cores on the compute nodes, the value from yamlinput(args)['thread'] is passed on to the submission command, here ncpus in the resources list object. The number of independent parallel cluster processes is defined under the Njobs argument. The following example will run 18 processes in parallel using for each 4 CPU cores. If the resources available on a cluster allow running all 18 processes at the same time then the shown sample submission will utilize in total 72 CPU cores. Note, clusterRun can be used with most queueing systems as it is based on utilities from the batchtools package which supports the use of template files (*.tmpl) for defining the run parameters of different schedulers. To run the following code, one needs to have both a conf file (see .batchtools.conf.R samples here) and a template file (see *.tmpl samples here) for the queueing available on a system. The following example uses the sample conf and template files for the Slurm scheduler provided by this package.\nAccess the Previous Version Please find here the previous version.\nReferences H Backman, Tyler W, and Thomas Girke. 2016. “systemPipeR: NGS workflow and report generation environment.” BMC Bioinformatics 17 (1): 388. https://doi.org/10.1186/s12859-016-1241-0.\n Kim, Daehwan, Ben Langmead, and Steven L Salzberg. 2015. “HISAT: A Fast Spliced Aligner with Low Memory Requirements.” Nat. Methods 12 (4): 357–60.\n Kim, Daehwan, Geo Pertea, Cole Trapnell, Harold Pimentel, Ryan Kelley, and Steven L Salzberg. 2013. “TopHat2: Accurate Alignment of Transcriptomes in the Presence of Insertions, Deletions and Gene Fusions.” Genome Biol. 14 (4): R36. https://doi.org/10.1186/gb-2013-14-4-r36.\n Langmead, Ben, and Steven L Salzberg. 2012. “Fast Gapped-Read Alignment with Bowtie 2.” Nat. Methods 9 (4): 357–59. https://doi.org/10.1038/nmeth.1923.\n Love, Michael, Wolfgang Huber, and Simon Anders. 2014. “Moderated Estimation of Fold Change and Dispersion for RNA-seq Data with DESeq2.” Genome Biol. 15 (12): 550. https://doi.org/10.1186/s13059-014-0550-8.\n Morgan, Martin, Hervé Pagès, Valerie Obenchain, and Nathaniel Hayden. 2019. Rsamtools: Binary Alignment (BAM), FASTA, Variant Call (BCF), and Tabix File Import. http://bioconductor.org/packages/Rsamtools.\n Robinson, M D, D J McCarthy, and G K Smyth. 2010. “edgeR: A Bioconductor Package for Differential Expression Analysis of Digital Gene Expression Data.” Bioinformatics 26 (1): 139–40. https://doi.org/10.1093/bioinformatics/btp616.\n Wu, T D, and S Nacu. 2010. “Fast and SNP-tolerant Detection of Complex Variants and Splicing in Short Reads.” Bioinformatics 26 (7): 873–81. https://doi.org/10.1093/bioinformatics/btq057.\n ","categories":"","description":"","excerpt":" document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/steps/","tags":"","title":"Workflow step examples"},{"body":" SPS Canvas is a place to display and edit scrennshots from different plots. To start to use Canvas, you need to take some screenshots but clicking “To Canvas” buttons on different tabs/modules. After clicking, the screenshots will be automatically sent from these places to this Canvas.\nAfter SPS v1.1.0 this Canvas feature has been provided as a separate package {drawer}. If you like this feature and want to use outside of SPS, install {drawer}. It is fully compatible with both Shiny and R markdown.\nPrepare plots In other SPS tabs, adjust your plots to the optimal size by dragging the corner:\n Then use the ‵toCanvas‵ button of that plot to send a screenshot of current plot to the Canvas. Or you can click on the “down arrow” to save it to edit in other tools.\n Use the Canvas Figure 9 Canvas\n The Canvas area. Canvas drawing grids. By default, your objects are limited to these drawing grids, but you can change it from top options inside “canvas”. The grid area size is automatically calculated to fit your screen size when you start SPS. Object information. When you select any object on the Canvas, a bounding box will show to display the object’s dimensions, scale, angle and other information. You can disable them in the “View” menu To edit your screenshots, simply drag your screenshots from left to Canvas working area. You can add text or titles, and change the font color, decorations in this panel. Different Canvas options. Several menus and buttons help you to better control the Canvas. Hover your mouse on buttons will display a tooltip of their functionality. Keyboard shortcuts are also enabled with SPS Canvas. Go to “help” menu to see these options.\nSupport Canvas only works on recent browsers versions, like Chrome, latest Edge, Firefox. IE is not supported. Also, some browser privacy extensions will block javascript and HTML5 canvas fingerprint. This will cause the screenshot to be blank.\n","categories":"","description":"","excerpt":" SPS Canvas is a place to display and edit scrennshots from different …","ref":"/sps/canvas/","tags":"","title":"Canvas"},{"body":"We have discussed about how to run/manage a workflow. There are many useful methods (functions) of the SYSargsList. We have discussed some of them in previous secions like, appendStep, addResources, and more. We will be exploring them in details in this section. To get help quickly, use ?\\SYSargsList-class`` to call up the help files.\nsuppressPackageStartupMessages({ library(systemPipeR) }) We still use the simple workflow to demonstrate.\nsal \u003c- SPRproject() ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' sal \u003c- importWF(sal, file_path = system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\"), verbose = FALSE) sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## Accessor Methods systemPipeR provide several accessor methods and useful functions to explore SYSargsList workflow object.\nSeveral accessor methods are available that are named after the slot names of the SYSargsList workflow object.\nnames(sal) ## [1] \"stepsWF\" \"statusWF\" \"targetsWF\" ## [4] \"outfiles\" \"SE\" \"dependency\" ## [7] \"targets_connection\" \"projectInfo\" \"runInfo\" Check the length of the workflow: length(sal) ## [1] 5 Extract all steps of the workflow in a list: stepsWF(sal) ## $load_library ## Instance of 'LineWise' ## Code Chunk length: 1 ## ## $export_iris ## Instance of 'LineWise' ## Code Chunk length: 1 ## ## $gzip ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 3 (SE...VI), targetsheader: 1 (lines) ## modules: 0 ## wf: 1, clt: 1, yamlinput: 4 (inputs) ## input: 3, output: 3 ## cmdlist: 3 ## Sub Steps: ## 1. gzip (rendered: TRUE) ## ## ## ## $gunzip ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 3 (SE...VI), targetsheader: 1 (lines) ## modules: 0 ## wf: 1, clt: 1, yamlinput: 4 (inputs) ## input: 3, output: 3 ## cmdlist: 3 ## Sub Steps: ## 1. gunzip (rendered: TRUE) ## ## ## ## $stats ## Instance of 'LineWise' ## Code Chunk length: 5 Checking the command-line for each target sample: cmdlist() method printing the system commands for running command-line software as specified by a given *.cwl file combined with the paths to the input samples (e.g. FASTQ files) provided by a targets file. The example below shows the cmdlist() output for running gzip and gunzip on the first sample. Evaluating the output of cmdlist() can be very helpful for designing and debugging *.cwl files of new command-line software or changing the parameter settings of existing ones.\ncmdlist(sal, step = c(2,3), targets = 1) ## export_iris step have been dropped because it is not a SYSargs2 object. ## $gzip ## $gzip$SE ## $gzip$SE$gzip ## [1] \"gzip -c results/setosa.csv \u003e results/SE.csv.gz\" Check the workflow status: statusWF(sal) ## $load_library ## DataFrame with 1 row and 2 columns ## Step status.summary ## \u003ccharacter\u003e \u003ccharacter\u003e ## 1 load_library Pending ## ## $export_iris ## DataFrame with 1 row and 2 columns ## Step status.summary ## \u003ccharacter\u003e \u003ccharacter\u003e ## 1 export_iris Pending ## ## $gzip ## DataFrame with 3 rows and 5 columns ## Targets Total_Files Existing_Files Missing_Files gzip ## \u003ccharacter\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cmatrix\u003e ## SE SE 1 0 1 Pending ## VE VE 1 0 1 Pending ## VI VI 1 0 1 Pending ## ## $gunzip ## DataFrame with 3 rows and 5 columns ## Targets Total_Files Existing_Files Missing_Files gunzip ## \u003ccharacter\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cnumeric\u003e \u003cmatrix\u003e ## SE SE 1 0 1 Pending ## VE VE 1 0 1 Pending ## VI VI 1 0 1 Pending ## ## $stats ## DataFrame with 1 row and 2 columns ## Step status.summary ## \u003ccharacter\u003e \u003ccharacter\u003e ## 1 stats Pending Check the workflow targets files: targetsWF(sal[2]) ## $export_iris ## DataFrame with 0 rows and 0 columns Checking the expected outfiles files: The outfiles components of SYSargsList define the expected outfiles files for each step in the workflow, some of which are the input for the next workflow step.\noutfiles(sal[2]) ## $export_iris ## DataFrame with 0 rows and 0 columns Check the workflow dependencies: dependency(sal) ## $load_library ## [1] NA ## ## $export_iris ## [1] \"load_library\" ## ## $gzip ## [1] \"export_iris\" ## ## $gunzip ## [1] \"gzip\" ## ## $stats ## [1] \"gunzip\" Check the sample comparisons: Sample comparisons are defined in the header lines of the targets file starting with ‘# \u003cCMP\u003e’. This information can be accessed as follows:\ntargetsheader(sal, step = \"gzip\") ## $targetsheader ## [1] \"# Project ID: SPR Example gzip\" This demo workflow does not have any comparison groups, for a real analysis like RNAseq or ChIPseq, comparisons can be defined in the header, like this file.\nGet the workflow steps names: stepName(sal) ## [1] \"load_library\" \"export_iris\" \"gzip\" \"gunzip\" \"stats\" Get the Sample Id for on particular step: SampleName(sal, step = \"gzip\") ## [1] \"SE\" \"VE\" \"VI\" SampleName(sal, step = \"stats\") ## NULL Get the outfiles or targets column files: getColumn(sal, \"outfiles\", step = \"gzip\", column = \"gzip_file\") ## SE VE VI ## \"results/SE.csv.gz\" \"results/VE.csv.gz\" \"results/VI.csv.gz\" getColumn(sal, \"targetsWF\", step = \"gzip\", column = \"FileName\") ## SE VE VI ## \"results/setosa.csv\" \"results/versicolor.csv\" \"results/virginica.csv\" Get the R code for a LineWise step: codeLine(sal, step = \"export_iris\") ## export_iris ## mapply(function(x, y) write.csv(x, y), split(iris, factor(iris$Species)), file.path(\"results\", paste0(names(split(iris, factor(iris$Species))), \".csv\"))) View all the objects in the running environment: viewEnvir(sal) ## \u003cenvironment: 0x55761c0b2b20\u003e ## character(0) Copy one or multiple objects from the running environment to a new environment: copyEnvir(sal, list = c(\"plot\"), new.env = globalenv(), silent = FALSE) ## \u003cenvironment: 0x55761c0b2b20\u003e ## Copying to 'new.env': ## plot Accessing the *.yml data yamlinput(sal, step = \"gzip\") ## $file ## $file$class ## [1] \"File\" ## ## $file$path ## [1] \"_FILE_PATH_\" ## ## ## $SampleName ## [1] \"_SampleName_\" ## ## $ext ## [1] \"csv.gz\" ## ## $results_path ## $results_path$class ## [1] \"Directory\" ## ## $results_path$path ## [1] \"./results\" Subsetting the workflow details The SYSargsList class and its subsetting operator [: sal[1] ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## sal[1:3] ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## sal[c(1,3)] ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 2.1. gzip ## cmdlist: 3 | Pending: 3 ## or use a character vector\nsal[c(\"gzip\", \"stats\")] ## Instance of 'SYSargsList': ## WF Steps: ## 1. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 1.1. gzip ## cmdlist: 3 | Pending: 3 ## 2. stats --\u003e Status: Pending ## The SYSargsList class and its subsetting by steps and input samples: sal_sub \u003c- subset(sal, subset_steps = c(3,4), input_targets = (\"SE\"), keep_steps = TRUE) stepsWF(sal_sub) ## $load_library ## Instance of 'LineWise' ## Code Chunk length: 1 ## ## $export_iris ## Instance of 'LineWise' ## Code Chunk length: 1 ## ## $gzip ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 1 (SE...SE), targetsheader: 1 (lines) ## modules: 0 ## wf: 1, clt: 1, yamlinput: 4 (inputs) ## input: 1, output: 1 ## cmdlist: 1 ## Sub Steps: ## 1. gzip (rendered: TRUE) ## ## ## ## $gunzip ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 1 (SE...SE), targetsheader: 1 (lines) ## modules: 0 ## wf: 1, clt: 1, yamlinput: 4 (inputs) ## input: 1, output: 1 ## cmdlist: 1 ## Sub Steps: ## 1. gunzip (rendered: TRUE) ## ## ## ## $stats ## Instance of 'LineWise' ## Code Chunk length: 5 targetsWF(sal_sub) ## $load_library ## DataFrame with 0 rows and 0 columns ## ## $export_iris ## DataFrame with 0 rows and 0 columns ## ## $gzip ## DataFrame with 1 row and 2 columns ## FileName SampleName ## \u003ccharacter\u003e \u003ccharacter\u003e ## SE results/setosa.csv SE ## ## $gunzip ## DataFrame with 1 row and 2 columns ## gzip_file SampleName ## \u003ccharacter\u003e \u003ccharacter\u003e ## SE results/SE.csv.gz SE ## ## $stats ## DataFrame with 0 rows and 0 columns outfiles(sal_sub) ## $load_library ## DataFrame with 0 rows and 0 columns ## ## $export_iris ## DataFrame with 0 rows and 0 columns ## ## $gzip ## DataFrame with 1 row and 1 column ## gzip_file ## \u003ccharacter\u003e ## 1 results/SE.csv.gz ## ## $gunzip ## DataFrame with 1 row and 1 column ## gunzip_file ## \u003ccharacter\u003e ## 1 results/SE.csv ## ## $stats ## DataFrame with 0 rows and 0 columns In this way, we are only selecting sample SE to run in step 3 (gzip) and 4 (gunzip). Other samples in these steps are removed.\nThe SYSargsList class and its operator + sal[1] + sal[2] + sal[3] ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## Replacement Methods Update a input parameter in the workflow sal_c \u003c- sal ## check values yamlinput(sal_c, step = \"gzip\") ## $file ## $file$class ## [1] \"File\" ## ## $file$path ## [1] \"_FILE_PATH_\" ## ## ## $SampleName ## [1] \"_SampleName_\" ## ## $ext ## [1] \"csv.gz\" ## ## $results_path ## $results_path$class ## [1] \"Directory\" ## ## $results_path$path ## [1] \"./results\" ## check on command-line cmdlist(sal_c, step = \"gzip\", targets = 1) ## $gzip ## $gzip$SE ## $gzip$SE$gzip ## [1] \"gzip -c results/setosa.csv \u003e results/SE.csv.gz\" ## Replace yamlinput(sal_c, step = \"gzip\", paramName = \"ext\") \u003c- \"txt.gz\" ## check NEW values yamlinput(sal_c, step = \"gzip\") ## $file ## $file$class ## [1] \"File\" ## ## $file$path ## [1] \"_FILE_PATH_\" ## ## ## $SampleName ## [1] \"_SampleName_\" ## ## $ext ## [1] \"txt.gz\" ## ## $results_path ## $results_path$class ## [1] \"Directory\" ## ## $results_path$path ## [1] \"./results\" ## Check on command-line cmdlist(sal_c, step = \"gzip\", targets = 1) ## $gzip ## $gzip$SE ## $gzip$SE$gzip ## [1] \"gzip -c results/setosa.csv \u003e results/SE.txt.gz\" Here you can see we replace the yaml input of \"ext\" from \"csv.gz\" to \"txt.gz\", so the following rendered command is also changed. In this way, we can easily tweak command-line parameters of a certain steps. For example, we are training a machine learning model, the results are not ideal and we wish to increase the iteration numbers. Then we can use similar method above to change the iteration parameter and next use runWF(.., steps = \"train_model\", force = TRUE) to only rerun this step instead of rebuilding the whole workflow and rerun all steps.\nAppend and Replacement methods for R Code Steps appendCodeLine(sal_c, step = \"export_iris\", after = 1) \u003c- \"log_cal_100 \u003c- log(100)\" codeLine(sal_c, step = \"export_iris\") ## export_iris ## mapply(function(x, y) write.csv(x, y), split(iris, factor(iris$Species)), file.path(\"results\", paste0(names(split(iris, factor(iris$Species))), \".csv\"))) ## log_cal_100 \u003c- log(100) replaceCodeLine(sal_c, step=\"export_iris\", line = 2) \u003c- LineWise(code={ log_cal_100 \u003c- log(50) }) codeLine(sal_c, step = 1) ## load_library ## library(systemPipeR) Rename a Step renameStep(sal_c, step = 1) \u003c- \"newStep\" renameStep(sal_c, c(1, 2)) \u003c- c(\"newStep2\", \"newIndex\") sal_c ## Instance of 'SYSargsList': ## WF Steps: ## 1. newStep2 --\u003e Status: Pending ## 2. newIndex --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## names(outfiles(sal_c)) ## [1] \"newStep2\" \"newIndex\" \"gzip\" \"gunzip\" \"stats\" names(targetsWF(sal_c)) ## [1] \"newStep2\" \"newIndex\" \"gzip\" \"gunzip\" \"stats\" dependency(sal_c) ## $newStep2 ## [1] NA ## ## $newIndex ## [1] \"newStep2\" ## ## $gzip ## [1] \"newIndex\" ## ## $gunzip ## [1] \"gzip\" ## ## $stats ## [1] \"gunzip\" Replace a Step sal_test \u003c- sal[c(1,2)] replaceStep(sal_test, step = 1, step_name = \"gunzip\" ) \u003c- sal[3] sal_test ## Instance of 'SYSargsList': ## WF Steps: ## 1. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 1.1. gzip ## cmdlist: 3 | Pending: 3 ## 2. export_iris --\u003e Status: Pending ## Note: Please use this method with attention, because it can disrupt all the dependency graphs.\nRemoving a Step sal_test \u003c- sal[-2] sal_test ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 2.1. gzip ## cmdlist: 3 | Pending: 3 ## 3. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gunzip ## cmdlist: 3 | Pending: 3 ## 4. stats --\u003e Status: Pending ## Session sessionInfo() ## R version 4.2.0 (2022-04-22) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.4 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] systemPipeR_2.3.4 ShortRead_1.54.0 ## [3] GenomicAlignments_1.32.0 SummarizedExperiment_1.26.1 ## [5] Biobase_2.56.0 MatrixGenerics_1.8.0 ## [7] matrixStats_0.62.0 BiocParallel_1.30.2 ## [9] Rsamtools_2.12.0 Biostrings_2.64.0 ## [11] XVector_0.36.0 GenomicRanges_1.48.0 ## [13] GenomeInfoDb_1.32.2 IRanges_2.30.0 ## [15] S4Vectors_0.34.0 BiocGenerics_0.42.0 ## ## loaded via a namespace (and not attached): ## [1] lattice_0.20-45 png_0.1-7 assertthat_0.2.1 ## [4] digest_0.6.29 utf8_1.2.2 R6_2.5.1 ## [7] evaluate_0.15 ggplot2_3.3.6 blogdown_1.10 ## [10] pillar_1.7.0 zlibbioc_1.42.0 rlang_1.0.2 ## [13] rstudioapi_0.13 jquerylib_0.1.4 Matrix_1.4-1 ## [16] rmarkdown_2.14 stringr_1.4.0 htmlwidgets_1.5.4 ## [19] RCurl_1.98-1.6 munsell_0.5.0 DelayedArray_0.22.0 ## [22] compiler_4.2.0 xfun_0.31 pkgconfig_2.0.3 ## [25] htmltools_0.5.2 tidyselect_1.1.2 tibble_3.1.7 ## [28] GenomeInfoDbData_1.2.8 bookdown_0.26 fansi_1.0.3 ## [31] dplyr_1.0.9 crayon_1.5.1 bitops_1.0-7 ## [34] grid_4.2.0 DBI_1.1.2 jsonlite_1.8.0 ## [37] gtable_0.3.0 lifecycle_1.0.1 magrittr_2.0.3 ## [40] scales_1.2.0 cli_3.3.0 stringi_1.7.6 ## [43] hwriter_1.3.2.1 latticeExtra_0.6-29 bslib_0.3.1 ## [46] generics_0.1.2 ellipsis_0.3.2 vctrs_0.4.1 ## [49] RColorBrewer_1.1-3 tools_4.2.0 glue_1.6.2 ## [52] purrr_0.3.4 jpeg_0.1-9 parallel_4.2.0 ## [55] fastmap_1.1.0 yaml_2.3.5 colorspace_2.0-3 ## [58] knitr_1.39 sass_0.4.1 ","categories":"","description":"","excerpt":"We have discussed about how to run/manage a workflow. There are many …","ref":"/sp/spr/sp_run/sal_explore/","tags":"","title":"Explore workflow instances"},{"body":" SPS interative guides (tutorials) SPS provides some interactive guides for users to familiarize the app. There is a very simple one-step welcome guide that will initialize everytime on app start to indicate where the guide dropdown is (top-right corner).\n Welcome guide on start \nBy clicking the guide dropdown menu, you can open up the list of available guides. By default, we only proivde a main SPS guide.\n Guide dropdown menu \nIf any of the guide is clicked in the dropdown, the corresponding interactive guide will start.\n Guide started You can click “Next”, “Previous” or “Close” to navigate the guide or close the guide.\nCustom guide To build and provide your custom guides to your users, there is file guide_content.R created on SPS project initialization under the R folder: /R/guide_content.R. This is the place to define your own guide.\nThis file look like this:\n#################### Define your custom SPS tutorials ########################## # use `shinydashboardPlus::messageItem` to add your tutorials UI to this list guide_ui \u003c- list( ## An example is provided below shinydashboardPlus::messageItem( inputId = \"guide_main\", from = \"Main Guide\", icon = icon('home'), message = \"Brief introduction\" ) ) # use `cicerone::Cicerone$new()` to add your tutorials content to this list # See help `?cicerone::Cicerone` # A named list, each item's name must match the `inputId` in UI to trigger it in app. guide_content \u003c- try(list( ## An example is provided below, replace or add your own to the list guide_main = cicerone::Cicerone$new(overlay_click_next = TRUE)$ step(el = \"sidebarItemExpanded\", title = \"SPS tabs\", description = \"Browse SPS functionalities as tabs from the left\", position = \"right-center\")$ ... )) There are two parts that you need to define: UI and actual guide content.\nUI UI is what users see inside the dropdown menu. Guides UI needs to be stored in a list and each item should be a shinydashboardPlus::messageItem.\n inputId must be unique. from is the short description of the guide. icon should be a call of shiny::icon(), the icon of the guide in dropdown menu message: short description of the guide in dropdown menu To add multiple guides' UI, for example:\nguide_ui \u003c- list( ## An example is provided below shinydashboardPlus::messageItem( inputId = \"guide1\", ... ), shinydashboardPlus::messageItem( inputId = \"guide2\", ... ), ... ) Guide content The guide content is defined with the {cicerone{blk}} package with cicerone::Cicerone R6 class and also in a named list.\nThe name of each item in a list must match the name of inputId in guide UI. For example, we have two guides\nguide_ui \u003c- list( ## An example is provided below shinydashboardPlus::messageItem( inputId = \"guide1\", ... ), shinydashboardPlus::messageItem( inputId = \"guide2\", ... ), ... ) guide_content \u003c- try(list( guide1 = cicerone::Cicerone$new(overlay_click_next = TRUE)$ ..., guide2 = cicerone::Cicerone$new(overlay_click_next = TRUE)$ ... )) The “guide1” of inputId in the guide_ui must match “guide1” in guide_content list.\nThe “guide2” of inputId in the guide_ui must match “guide2” in guide_content list.\nDefine guide content How to define the guide content will not be expanded here, read details in the {cicerone{blk}} package manual. Here are some key points:\n The cicerone::Cicerone is R6 class, and it is obejct oriented, so you need to use cicerone::Cicerone$new() method to create a new object before you can add any guide step. R6 methods calling can be chained together, like how to define steps: guide_content \u003c- try(list( guide1 = cicerone::Cicerone$new()$ # chain object creation with step defining step(...)$ # chain step1 to step2 step(...)$ # step2 to step3 step(...)$ # step3 to step4 step(...) # DO NOT use `$` for the last step )) If you follow the manual of {cicerone} to define steps, the guide will look like this when users click it.\n Cicerone steps ","categories":"","description":"","excerpt":" SPS interative guides (tutorials) SPS provides some interactive …","ref":"/sps/adv_features/guide/","tags":"","title":"SPS Guide"},{"body":"document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Workflow templates The intended way of running systemPipeR workflows is via *.Rmd files, which can be executed either line-wise in interactive mode or with a single command from R or the command-line. This way comprehensive and reproducible analysis reports can be generated in PDF or HTML format in a fully automated manner by making use of the highly functional reporting utilities available for R. The following shows how to execute a workflow (e.g., systemPipeRNAseq.Rmd) from the command-line.\nRscript -e \"rmarkdown::render('systemPipeRNAseq.Rmd')\" Templates for setting up custom project reports are provided as **.Rmd* files by the helper package *systemPipeRdata* and in the vignettes subdirectory of systemPipeR. The corresponding HTML of these report templates are available here: systemPipeRNAseq, systemPipeRIBOseq, systemPipeChIPseq and systemPipeVARseq. To work with *.Rnw* or *.Rmd* files efficiently, basic knowledge of Sweave or knitr and Latex or R Markdown v2 is required.\nRNA-Seq sample Load the RNA-Seq sample workflow into your current working directory.\nlibrary(systemPipeRdata) genWorkenvir(workflow = \"rnaseq\") setwd(\"rnaseq\") Run workflow Next, run the chosen sample workflow systemPipeRNAseq (PDF, Rmd) by executing from the command-line make -B within the rnaseq directory. Alternatively, one can run the code from the provided *.Rmd template file from within R interactively.\nThe workflow includes following steps:\n Read preprocessing Quality filtering (trimming) FASTQ quality report Alignments: Tophat2 (or any other RNA-Seq aligner) Alignment stats Read counting Sample-wise correlation analysis Analysis of differentially expressed genes (DEGs) GO term enrichment analysis Gene-wise clustering ChIP-Seq sample Load the ChIP-Seq sample workflow into your current working directory.\nlibrary(systemPipeRdata) genWorkenvir(workflow = \"chipseq\") setwd(\"chipseq\") Run workflow Next, run the chosen sample workflow systemPipeChIPseq_single (PDF, Rmd) by executing from the command-line make -B within the chipseq directory. Alternatively, one can run the code from the provided *.Rmd template file from within R interactively.\nThe workflow includes the following steps:\n Read preprocessing Quality filtering (trimming) FASTQ quality report Alignments: Bowtie2 or rsubread Alignment stats Peak calling: MACS2, BayesPeak Peak annotation with genomic context Differential binding analysis GO term enrichment analysis Motif analysis VAR-Seq sample VAR-Seq workflow for the single machine Load the VAR-Seq sample workflow into your current working directory.\nlibrary(systemPipeRdata) genWorkenvir(workflow = \"varseq\") setwd(\"varseq\") Run workflow Next, run the chosen sample workflow systemPipeVARseq_single (PDF, Rmd) by executing from the command-line make -B within the varseq directory. Alternatively, one can run the code from the provided *.Rmd template file from within R interactively.\nThe workflow includes following steps:\n Read preprocessing Quality filtering (trimming) FASTQ quality report Alignments: gsnap, bwa Variant calling: VariantTools, GATK, BCFtools Variant filtering: VariantTools and VariantAnnotation Variant annotation: VariantAnnotation Combine results from many samples Summary statistics of samples VAR-Seq workflow for computer cluster The workflow template provided for this step is called systemPipeVARseq.Rmd (PDF, Rmd). It runs the above VAR-Seq workflow in parallel on multiple compute nodes of an HPC system using Slurm as the scheduler.\nRibo-Seq sample Load the Ribo-Seq sample workflow into your current working directory.\nlibrary(systemPipeRdata) genWorkenvir(workflow = \"riboseq\") setwd(\"riboseq\") Run workflow Next, run the chosen sample workflow systemPipeRIBOseq (PDF, Rmd) by executing from the command-line make -B within the ribseq directory. Alternatively, one can run the code from the provided *.Rmd template file from within R interactively.\nThe workflow includes following steps:\n Read preprocessing Adaptor trimming and quality filtering FASTQ quality report Alignments: Tophat2 (or any other RNA-Seq aligner) Alignment stats Compute read distribution across genomic features Adding custom features to the workflow (e.g. uORFs) Genomic read coverage along with transcripts Read counting Sample-wise correlation analysis Analysis of differentially expressed genes (DEGs) GO term enrichment analysis Gene-wise clustering Differential ribosome binding (translational efficiency) Version information Note: the most recent version of this tutorial can be found here.\nsessionInfo() ## R version 4.0.3 (2020-10-10) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.2 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /home/dcassol/src/R-4.0.3/lib/libRlapack.so ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 parallel stats graphics grDevices utils datasets ## [8] methods base ## ## other attached packages: ## [1] magrittr_2.0.1 batchtools_0.9.15 ## [3] ape_5.4-1 ggplot2_3.3.3 ## [5] systemPipeR_1.25.6 ShortRead_1.48.0 ## [7] GenomicAlignments_1.26.0 SummarizedExperiment_1.20.0 ## [9] Biobase_2.50.0 MatrixGenerics_1.2.1 ## [11] matrixStats_0.58.0 BiocParallel_1.24.1 ## [13] Rsamtools_2.6.0 Biostrings_2.58.0 ## [15] XVector_0.30.0 GenomicRanges_1.42.0 ## [17] GenomeInfoDb_1.26.2 IRanges_2.24.1 ## [19] S4Vectors_0.28.1 BiocGenerics_0.36.0 ## [21] BiocStyle_2.18.1 ## ## loaded via a namespace (and not attached): ## [1] colorspace_2.0-0 rjson_0.2.20 hwriter_1.3.2 ## [4] ellipsis_0.3.1 bit64_4.0.5 AnnotationDbi_1.52.0 ## [7] xml2_1.3.2 codetools_0.2-18 splines_4.0.3 ## [10] cachem_1.0.3 knitr_1.31 jsonlite_1.7.2 ## [13] annotate_1.68.0 GO.db_3.12.1 dbplyr_2.1.0 ## [16] png_0.1-7 pheatmap_1.0.12 graph_1.68.0 ## [19] BiocManager_1.30.10 compiler_4.0.3 httr_1.4.2 ## [22] GOstats_2.56.0 backports_1.2.1 assertthat_0.2.1 ## [25] Matrix_1.3-2 fastmap_1.1.0 limma_3.46.0 ## [28] formatR_1.7 htmltools_0.5.1.1 prettyunits_1.1.1 ## [31] tools_4.0.3 gtable_0.3.0 glue_1.4.2 ## [34] GenomeInfoDbData_1.2.4 Category_2.56.0 dplyr_1.0.4 ## [37] rsvg_2.1 rappdirs_0.3.3 V8_3.4.0 ## [40] Rcpp_1.0.6 vctrs_0.3.6 nlme_3.1-152 ## [43] blogdown_1.1.7 rtracklayer_1.50.0 xfun_0.21 ## [46] stringr_1.4.0 lifecycle_1.0.0.9000 XML_3.99-0.5 ## [49] edgeR_3.32.1 zlibbioc_1.36.0 scales_1.1.1 ## [52] BSgenome_1.58.0 VariantAnnotation_1.36.0 hms_1.0.0 ## [55] RBGL_1.66.0 RColorBrewer_1.1-2 yaml_2.2.1 ## [58] curl_4.3 memoise_2.0.0 biomaRt_2.46.3 ## [61] latticeExtra_0.6-29 stringi_1.5.3 RSQLite_2.2.3 ## [64] genefilter_1.72.1 checkmate_2.0.0 GenomicFeatures_1.42.1 ## [67] DOT_0.1 rlang_0.4.10 pkgconfig_2.0.3 ## [70] bitops_1.0-6 evaluate_0.14 lattice_0.20-41 ## [73] purrr_0.3.4 bit_4.0.4 tidyselect_1.1.0 ## [76] GSEABase_1.52.1 AnnotationForge_1.32.0 bookdown_0.21 ## [79] R6_2.5.0 generics_0.1.0 base64url_1.4 ## [82] DelayedArray_0.16.1 DBI_1.1.1 withr_2.4.1 ## [85] pillar_1.4.7 survival_3.2-7 RCurl_1.98-1.2 ## [88] tibble_3.0.6 crayon_1.4.1 BiocFileCache_1.14.0 ## [91] rmarkdown_2.6 jpeg_0.1-8.1 progress_1.2.2 ## [94] locfit_1.5-9.4 grid_4.0.3 data.table_1.13.6 ## [97] blob_1.2.1 Rgraphviz_2.34.0 digest_0.6.27 ## [100] xtable_1.8-4 brew_1.0-6 openssl_1.4.3 ## [103] munsell_0.5.0 askpass_1.1 References ","categories":"","description":"","excerpt":"document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/templates/","tags":"","title":"Workflow Templates"},{"body":"This part will introduce:\n How CWL describes command-line tools and the specification and terminology of each file. How SPR interact with CWL. How to create new CWL files with functions from SPR. Sections ","categories":"","description":"","excerpt":"This part will introduce:\n How CWL describes command-line tools and …","ref":"/sp/spr/cwl/","tags":"","title":"CWL"},{"body":" .td-content li a { font-size: 1.5rem; } SPS Function Reference Manuals There are many more useful functions one could use from SPS core and sub packages. We could not cover all the details in this manual. To take a look at these functions, click links below to go to the function reference manual of each package. Detailed function usage, example code, and example running results are shown inside.\n Package Description systemPipeShiny main package spsComps SPS components drawer image editing tool spsUtil utility functions table {font-size: 1.5rem} ","categories":"","description":"","excerpt":" .td-content li a { font-size: 1.5rem; } SPS Function Reference …","ref":"/sps/sps_funcs/","tags":"","title":"SPS Functions"},{"body":" The basic usage of SPS with these default modules/tabs has been discussed in previous sections. SPS provides much more than this. To fully use SPS’s framework functionalities, in this section, we will discuss how you can customize SPS and add new features. \n","categories":"","description":"","excerpt":" The basic usage of SPS with these default modules/tabs has been …","ref":"/sps/adv_features/","tags":"","title":"Advanced features"},{"body":"After the analysis, we often would like to generate some reports. In SPR, we provide two types of reports: technical report and analysis report. Both of them would give you an interactive HTML file.\nTechnical report systemPipeR compiles all the workflow execution logs in one central location, making it easier to check any standard output (stdout) or standard error (stderr) for any command-line tools used on the workflow or the R code stdout. Also, the workflow plot is appended at the beginning of the report, making it easier to click on the respective step.\nsal \u003c- renderLogs(sal) An example log file can be viewed over here.\nAnalysis report To communicate with researchers outside one’s field, text explanation is usually expected. When we design a workflow and import from a template, adding text description to help people understand the workflow is highly recommended. The template can also be used to display results. Remember only SPR chunks (spr=TRUE)\nwould be imported into the workflow. Therefore, other chunks are ignored until rendering the analysis report with renderReport. These non-SPR chunks will be evaluated (if they do not have eval=FALSE) in report rendering and all SPR chunks will all be muted. So these non-SPR chunks can be good places to add some images, tables, plots, or other light calculations.\nsal \u003c- renderReport(sal) Here the renderReport uses the copy of workflow template, which is stored in .SPRProject, as skeleton to generate the report. All text is copied over and all steps in current workflow are translated into reproducible code to the skeleton. If any step is added interactively, meaning they did not exist in the template when you used importWF, renderReport has an internal algorithm to find the right place to inject the translated code based on the order where they appear inside SYSargsList. However, there will be no text description of these new steps. The algorithm is smart but not 100%, so if any new step is been added interactively, we recommend you to add text description and code accordingly in the template and use importWF(..., update = TRUE) as discussed in import section to update. If all steps are added interactively, meaning you did not use importWF at all, sal2rmd will be called. We will discuss this function in the next section. To have a glimpse of what the renderReport file look like, check out our pre-configed workflow templates rendered pages here.\n","categories":"","description":"","excerpt":"After the analysis, we often would like to generate some reports. In …","ref":"/sp/spr/sp_run/step_reports/","tags":"","title":"Generate Reports"},{"body":" This secetion discusses how different security concerns are handled in SPS.\nsuppressPackageStartupMessages(library(systemPipeShiny)) SPS mode SPS has an option of mode. This option controls how the file upload is handled by SPS. It can be either “server” or “local”, which is asking whether you are running the app on the “server” or running on your “local” machine.\n “server”: for security, users do not have access of file system on the server, choose files from users' local computer. “local”: Assumes the Shiny server and users' local computer is the same machine, so users can access file Shiny server’s file system. It is first defined in the global.R file in a SPS project.\noptions(sps = list( mode = \"local\", ... )) You can check current setting after the app started for the first time\nspsOption(\"mode\") ## [1] \"local\" The most affected function is dynamicFile and its server side function dynamicFileServer.\nServer:\nAfter clicking the file selection button in SPS, server mode uses the default shiny file choose, which users can choose from their local computer. You can see from the picture above, this is a user operating system built-in file chooser.\nLocal:\nYou can see this is different than the “server” mode. “Local” mode is able to use the file system of the shiny deploy environment file system, and it is no longer the users' local system.\nThis may be confusing for the first time. Remember “server” and “local” mean where you deploy the shiny app, on the server or run on your local computer.\n Mode choose file from file pointing method Server user local computer copy to temp Local the computer where you deploy the app direct pointer Pro and cons of modes It does not matter if which mode you choose if you run the app on your own computer, because the deploy server and the user computer are the same.\n However “local” mode will not copy a file to temp after the file chooser, but directly create a pointer. “Server” mode will first upload/copy the file to temp and create a pointer. This will cause resources waste if you are running the app on your own computer. You already have the file on your computer but now it gets copied to temp before Shiny can use it. This will also waste some time to copy the file, especially for large files. There is a limit for default Shiny upload size which is 24MB in “server” mode. You can choose files as large as you desire on “local” mode. The security issue of local mode There is a security concern of “local” mode when the app is deployed on a remote server. “local” mode enables users to choose files from the remote server, so there is the risk of file leaking and file damaging.\nWe recommend DO NOT use “local” mode for remote deployment, like https://shinyapps.io. You can turn the option warning_toast = TRUE on global and testing the app before deploy. This option will check for security problems and inform you.\nThere are cases where you really need users to choose files from the remote server, like the Workflow module, where all workflow files are stored on the remote server. Then use a sandbox or container environment to isolate the app, and also turn on the login page login_screen = TRUE to limit access will be helpful.\nWarning toast Set warning_toast = TRUE option will check for potential security risks and show a pop-up message if there is any risk when app starts. This is option is helpful on pre-deployment testing.\n check if you have changed the default admin page url “admin” check if you have changed the default admin user “admin” check if you have changed the default user “user” check if you are on “local” mode The workflow module The workflow module enables users to manage, design, and run workflows directly from the app and in the final running workflow session, users are allowed to run arbitrary R code in a Rstudio like console in a child R session. Running any R code means they can modify your remote system, and use system commands.\nFor shinyapps.io, it runs in a container and it reset itself once a while, so security is not a big concern, but apparently, shinyapps.io is not a place you want to deploy heavy data analysis workflows. Most users will deploy the SPS with workflow modules in other cloud computing sites or their own servers. For these cases, we recommend you:\n Turn on the login to give access to limited people.\n Isolate the app with sandboxes or containers.\n ","categories":"","description":"","excerpt":" This secetion discusses how different security concerns are handled …","ref":"/sps/adv_features/app_security/","tags":"","title":"App security"},{"body":"systemPipeR workflow management system allows one to translate workflow into reproducible code and export the workflow build interactively to R Markdown template format or an executable bash script. This feature advances the reusability of the workflow, as well as the flexibility for workflow execution.\nsuppressPackageStartupMessages({ library(systemPipeR) }) We still use the simple workflow to demonstrate.\nsal \u003c- SPRproject() ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/data ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/param ## Creating directory: /home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/results ## Creating directory '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject' ## Creating file '/home/lab/Desktop/spr/systemPipeR.github.io/content/en/sp/spr/sp_run/.SPRproject/SYSargsList.yml' sal \u003c- importWF(sal, file_path = system.file(\"extdata\", \"spr_simple_wf.Rmd\", package = \"systemPipeR\"), verbose = FALSE) sal ## Instance of 'SYSargsList': ## WF Steps: ## 1. load_library --\u003e Status: Pending ## 2. export_iris --\u003e Status: Pending ## 3. gzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 3.1. gzip ## cmdlist: 3 | Pending: 3 ## 4. gunzip --\u003e Status: Pending ## Total Files: 3 | Existing: 0 | Missing: 3 ## 4.1. gunzip ## cmdlist: 3 | Pending: 3 ## 5. stats --\u003e Status: Pending ## R Markdown file sal2rmd function takes an SYSargsList workflow container and translates it to SPR workflow template R markdown format. This file can be imported with the importWF function. This is very similar to the text-enriched report, but with all text removed.\nsal2rmd(sal) ## sal2rmd starts, pre-checks... ## Open spr_template.Rmd to write ## Write Rmd header and description ## Now writing step 1 load_library ## Now writing step 2 export_iris ## Now writing step 3 gzip ## Now writing step 4 gunzip ## Now writing step 5 stats ## Success! File created at spr_template.Rmd Bash script sal2bash function takes an SYSargsList workflow container and translates it to an executable bash script, The benefit of this is that if the workflow is only composed with command-line steps, no R step (LineWise) step in involved, then one could generate the workflow on one computer and run in another computer without installing SPR or R at all.\nsal2bash(sal) ## Success: Make sure the script 'spr_wf.sh' and directory ./spr_bash is there before executing. It will be generated on the project root an executable bash script, called by default the spr_wf.sh. Also, a directory ./spr_wf will be created and store all the R scripts based on the workflow steps. Please note that this function will “collapse” adjacent R steps into one file as much as possible.\nfs::dir_tree(\"spr_bash\") ## spr_bash ## ├── rscript_step1_2.R ## ├── rscript_step5.R ## └── spr_wf.RData Session sessionInfo() ## R version 4.2.1 (2022-06-23) ## Platform: x86_64-pc-linux-gnu (64-bit) ## Running under: Ubuntu 20.04.5 LTS ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] systemPipeR_2.3.5 ShortRead_1.54.0 ## [3] GenomicAlignments_1.32.1 SummarizedExperiment_1.26.1 ## [5] Biobase_2.56.0 MatrixGenerics_1.8.1 ## [7] matrixStats_0.62.0 BiocParallel_1.30.4 ## [9] Rsamtools_2.12.0 Biostrings_2.64.1 ## [11] XVector_0.36.0 GenomicRanges_1.48.0 ## [13] GenomeInfoDb_1.32.4 IRanges_2.30.1 ## [15] S4Vectors_0.34.0 BiocGenerics_0.42.0 ## ## loaded via a namespace (and not attached): ## [1] sass_0.4.2 jsonlite_1.8.3 bslib_0.4.0 ## [4] assertthat_0.2.1 latticeExtra_0.6-30 GenomeInfoDbData_1.2.8 ## [7] yaml_2.3.6 pillar_1.8.1 lattice_0.20-45 ## [10] glue_1.6.2 digest_0.6.30 RColorBrewer_1.1-3 ## [13] colorspace_2.0-3 htmltools_0.5.3 Matrix_1.5-1 ## [16] pkgconfig_2.0.3 bookdown_0.29 zlibbioc_1.42.0 ## [19] scales_1.2.1 jpeg_0.1-9 tibble_3.1.8 ## [22] generics_0.1.3 ggplot2_3.3.6 cachem_1.0.6 ## [25] cli_3.4.1 magrittr_2.0.3 crayon_1.5.2 ## [28] deldir_1.0-6 evaluate_0.17 fs_1.5.2 ## [31] fansi_1.0.3 hwriter_1.3.2.1 blogdown_1.13 ## [34] tools_4.2.1 lifecycle_1.0.3 stringr_1.4.1 ## [37] interp_1.1-3 munsell_0.5.0 DelayedArray_0.22.0 ## [40] compiler_4.2.1 jquerylib_0.1.4 rlang_1.0.6 ## [43] grid_4.2.1 RCurl_1.98-1.9 rstudioapi_0.14 ## [46] htmlwidgets_1.5.4 bitops_1.0-7 rmarkdown_2.17 ## [49] gtable_0.3.1 codetools_0.2-18 DBI_1.1.3 ## [52] R6_2.5.1 knitr_1.40 dplyr_1.0.10 ## [55] fastmap_1.1.0 utf8_1.2.2 stringi_1.7.8 ## [58] parallel_4.2.1 Rcpp_1.0.9 vctrs_0.4.2 ## [61] png_0.1-7 tidyselect_1.2.0 xfun_0.34 ","categories":"","description":"","excerpt":"systemPipeR workflow management system allows one to translate …","ref":"/sp/spr/sp_run/step_export/","tags":"","title":"Export workflows"},{"body":" pre code { white-space: pre !important; overflow-x: scroll !important; word-break: keep-all !important; word-wrap: initial !important; } document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i systemPipeR Installation To install the systemPipeR package (H Backman and Girke 2016), please use the BiocManager::install command:\nif (!requireNamespace(\"BiocManager\", quietly = TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeR\") To obtain the most recent updates immediately, one can install it directly from GitHub as follow:\nif (!requireNamespace(\"BiocManager\", quietly = TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"tgirke/systemPipeR\", dependencies = TRUE) Third-party software tools in SPR Current, systemPipeR provides the param file templates for third-party software tools. Please check the listed software tools.\n Tool Name Description Step bwa BWA is a software package for mapping low-divergent sequences against a large reference genome, such as the human genome. Alignment Bowtie2 Bowtie 2 is an ultrafast and memory-efficient tool for aligning sequencing reads to long reference sequences. Alignment FASTX-Toolkit FASTX-Toolkit is a collection of command line tools for Short-Reads FASTA/FASTQ files preprocessing. Read Preprocessing TransRate Transrate is software for de-novo transcriptome assembly quality analysis. Quality Gsnap GSNAP is a genomic short-read nucleotide alignment program. Alignment Samtools Samtools is a suite of programs for interacting with high-throughput sequencing data. Post-processing Trimmomatic Trimmomatic is a flexible read trimming tool for Illumina NGS data. Read Preprocessing Rsubread Rsubread is a Bioconductor software package that provides high-performance alignment and read counting functions for RNA-seq reads. Alignment Picard Picard is a set of command line tools for manipulating high-throughput sequencing (HTS) data and formats such as SAM/BAM/CRAM and VCF. Manipulating HTS data Busco BUSCO assesses genome assembly and annotation completeness with Benchmarking Universal Single-Copy Orthologs. Quality Hisat2 HISAT2 is a fast and sensitive alignment program for mapping NGS reads (both DNA and RNA) to reference genomes. Alignment Tophat2 TopHat is a fast splice junction mapper for RNA-Seq reads. Alignment GATK Variant Discovery in High-Throughput Sequencing Data. Variant Discovery STAR STAR is an ultrafast universal RNA-seq aligner. Alignment Trim_galore Trim Galore is a wrapper around Cutadapt and FastQC to consistently apply adapter and quality trimming to FastQ files. Read Preprocessing TransDecoder TransDecoder identifies candidate coding regions within transcript sequences. Find Coding Regions Trinity Trinity assembles transcript sequences from Illumina RNA-Seq data. denovo Transcriptome Assembly Trinotate Trinotate is a comprehensive annotation suite designed for automatic functional annotation of transcriptomes. Transcriptome Functional Annotation MACS2 MACS2 identifies transcription factor binding sites in ChIP-seq data. Peak calling Kallisto kallisto is a program for quantifying abundances of transcripts from RNA-Seq data. Read counting BCFtools BCFtools is a program for variant calling and manipulating files in the Variant Call Format (VCF) and its binary counterpart BCF. Variant Discovery Bismark Bismark is a program to map bisulfite treated sequencing reads to a genome of interest and perform methylation calls in a single step. Bisulfite mapping Fastqc FastQC is a quality control tool for high throughput sequence data. Quality Blast BLAST finds regions of similarity between biological sequences. Blast References H Backman, Tyler W, and Thomas Girke. 2016. “systemPipeR: NGS workflow and report generation environment.” BMC Bioinformatics 17 (1): 388. https://doi.org/10.1186/s12859-016-1241-0.\n ","categories":"","description":"","excerpt":" pre code { white-space: pre !important; overflow-x: scroll …","ref":"/sp/spr/sprinstall/","tags":"","title":"SPR detailed installation instructions"},{"body":" How to deploy the application The easiest way to deploy SPS is shinyapps.io{blk}. To get started, it is required to create a shinyapps.io account. Please follow this tutorial{blk} with all the instructions to create an account. There are other ways to deploy, like AWS or Google Cloud with a custom Shiny server. There are a lot of tutorials to deploy the app other than shinyapps.io. We only use shinyapps.io as the example here to discuss how to deploy.\nGet started After you have created a SPS project, it is in a deploy-ready state, which means you can deploy it as soon as you create the project.\nWe have created some important helper code in deploy.R under the project root for you.\n Read the tutorial{blk} After you have the accounts and token set up according to the tutorial, open deploy.R. If you have used Bioconductor packages (mostly likely yes, unless you do not use the default modules), run the options line in R console before deploy, which is this\noptions(repos = BiocManager::repositories()) If you want to use develop version of Bioconductor packages (not recommended), uncomment following lines and follow the instructions in the file.\n# repos \u003c- BiocManager::repositories() # devel \u003c- \"3.13\" # repos[length(repos) + 1] \u003c- paste0(\"https://bioconductor.org/packages/\", devel, \"/bioc\") # names(repos)[length(repos)] \u003c- \"BioC\" # options(repos = repos) # getOption(\"repos\") If you wish shinyapps.io to install SPS modules, copy and uncomment following lines for the modules to global.R file below the line # load additional libraries that you want to use below.\n## Workflow module # requireNamespace(\"DOT\"); requireNamespace(\"networkD3\"); requireNamespace(\"pushbar\") # requireNamespace(\"readr\"); requireNamespace(\"rhandsontable\"); requireNamespace(\"shinyTree\") # requireNamespace(\"systemPipeR\"); requireNamespace(\"systemPipeRdata\"); requireNamespace(\"zip\") ## RNA-Seq module # requireNamespace(\"DESeq2\"); requireNamespace(\"Rtsne\"); requireNamespace(\"SummarizedExperiment\") # requireNamespace(\"UpSetR\"); requireNamespace(\"ape\"); requireNamespace(\"ggtree\") # requireNamespace(\"glmpca\"); requireNamespace(\"pheatmap\"); requireNamespace(\"systemPipeR\") ## Quick ggplot module # requireNamespace(\"esquisse\") The last section in deploy.R is some helper code to set up the account and deploy the app programmatically. If you use the tutorial{blk}, there is no need to do this section.\n Save your changes in the global.R.\n Deploy in Rstudio We recommend you to deploy the app with Rstudio. If you have set up your shinyapps.io account, we are ready to go.\n A Open global.R in Rstudio, use the “Run App” button to make sure your app can be run without problems locally. Run options(repos = BiocManager::repositories()) and other Bioconductor set up code as listed above. Click the button next to “Run App” and choose “Publish Application…” B If you have set up your account correctly, you should see your account to the right panel. Select all the files of your SPS project. Change the app “Title” to what you want. hit “Publish”. RAM requirement If you wish to load the workflow and/or RNAseq module(s) on shinyapps.io, you need at least 2GB of memory. Unfortunately, these 2 modules depend heavily on Bioconductor packages and these packages are not light-weighted. The max RAM for free account on shinyapps.io is 1GB which means you either need to upgrade your account or use other server to deploy your app.\nIf you decide to not load these modules which will allow you to deploy the app with a free account, change the settings to unload these modules in app options in global.R.\n","categories":"","description":"","excerpt":" How to deploy the application The easiest way to deploy SPS is …","ref":"/sps/deploy/","tags":"","title":"Deploy"},{"body":"SPS is not only a framework to run interactive workflow and visualize data, but also a framework with a abundant developer tools for building Shiny apps, writing R markdowns, integrating R-HTML and general R utilities.\nThese developer toolkits are distributed in supporting packages. If you like some of the functionality from SPS and think installing the whole framework is too expensive (time consuming), cherry-pick the functionality you want in following categories:\n spsCpmps: Shiny/Rmarkdown UI components, and Shiny server functions. drawer: Shiny/Rmarkdown/HTML interactive image editing tool. spsUtil: General R utilities, like pretty logging functions. Install All these supporting packages are available on CRAN. We recommend to use the modern package manager {pak} to install packages.\nif(!requireNamespace(\"pak\", quietly = TRUE)) install.packages(\"pak\", repos = \"https://r-lib.github.io/p/pak/dev/\") Pick and install packages as your need\npak::pkg_install(\"spsCpmps\") pak::pkg_install(\"drawer\") pak::pkg_install(\"spsUtil\") Linux If you are on Linux, you need to install some system dependencies before R package installation. To figure out what system dependencies and command, run:\ncat(paste(\"sudo\", pak::pkg_system_requirements(\"spsComps\")), sep = \"\\n\") sudo apt-get install -y make sudo apt-get install -y libicu-dev cat(paste(\"sudo\", pak::pkg_system_requirements(\"drawer\")), sep = \"\\n\") sudo apt-get install -y make sudo apt-get install -y pandoc sudo apt-get install -y libicu-dev cat(paste(\"sudo\", pak::pkg_system_requirements(\"spsUtil\")), sep = \"\\n\") sudo apt-get install -y libcurl4-openssl-dev sudo apt-get install -y libssl-dev sudo apt-get install -y libicu-dev We are rendering this doc in Ubuntu. If your Linux distribution is different, commands above will be different.\nFunctions reference manual In documents, we only highlight some important functions. Please read the reference manuals for details of every function.\n","categories":"","description":"","excerpt":"SPS is not only a framework to run interactive workflow and visualize …","ref":"/sps/dev/","tags":"","title":"Developer tools"},{"body":" .td-content li a { font-size: 1.5rem; } systempipeR Functions Reference Manuals The following reference manual was created by systemPipeR Development version.\n systemPipeR Reference Manual ","categories":"","description":"","excerpt":" .td-content li a { font-size: 1.5rem; } systempipeR Functions …","ref":"/sp/spr/spr_funcs/","tags":"","title":"Help Manual"},{"body":" SPS database is a small SQLite database which stores some basic app information, the project encryption key pair, account information. The database is controlled by 3 SPS R6 classes:\n spsDb: basic database management, queries. spsEncryption: Interact with the SHA256 key pair in the database to encrypt strings, and files. Also methods to view or change the key pair, inherits spsDb spsAcount: use the encyption key pair to manage users and admin accounts in SPS, inherits spsDb and spsEncryption. First to create a SPS project\nsuppressPackageStartupMessages(library(systemPipeShiny)) app_path \u003c- \".\" spsInit(app_path = app_path, overwrite = TRUE, open_files = FALSE) ## [SPS-DANGER] 2021-04-22 15:45:04 Done, Db created at '/tmp/Rtmp3KQ3pG/SPS_20210422/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-22 15:45:04 Key md5 1d1f76c8eecddb382ee2db097d6edbe9 ## [SPS-INFO] 2021-04-22 15:45:04 SPS project setup done! You can see a database created on a SPS project initiation, you should see a message like this:\n[SPS-DANGER] 2021-04-19 11:06:53 Done, Db created at Then we can use different class methods to interact with the database.\nspsDb class Reference manual under SPS Functions.\nCreate a class object:\nmydb \u003c- spsDb$new() ## [SPS-INFO] 2021-04-22 15:45:04 Created SPS database method container create new db If there is no database, we can create one:\n# delete current one first try(file.remove(\"config/sps.db\")) ## [1] TRUE # create a new one mydb$createDb() ## [SPS-INFO] 2021-04-22 15:45:04 Creating SPS db... ## [SPS-DANGER] 2021-04-22 15:45:04 Done, Db created at 'config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-22 15:45:04 Key md5 6306a50abcf3c7618566911a793b0405 If you create a new database, all information in the old database will be overwritten. All old information will be lost\nGet tables # meta info table mydb$queryValue(\"sps_meta\") ## info value ## 1 creation_date 20210422154504 # raw blob table to store keys mydb$queryValue(\"sps_raw\") ## info value ## 1 key blob[1.36 kB] # account table mydb$queryValue(\"sps_account\") ## account pass ## 1 admin bef2094c429fa5b0ff7a37abc6bf8dd31c29fa2acd783a2303935d2b8664ea21 ## 2 user 12842a62c410af0f4b4dc866283a90f7b7c42c9d5ca0d0e1c812dca11021b052 ## role ## 1 admin ## 2 user Insert new records(rows) To add a new row, values of all columns needs to be passed in a SQL string\nmydb$queryInsert(\"sps_meta\", value = \"'new1', '1'\") ## [SPS-INFO] 2021-04-22 15:45:04 Inerted 1 rows Or pass in a vector:\nmydb$queryInsert(\"sps_meta\", value = c(\"'new2'\", \"'2'\")) ## [SPS-INFO] 2021-04-22 15:45:04 Inerted 1 rows # check the new table mydb$queryValue(\"sps_meta\") ## info value ## 1 creation_date 20210422154504 ## 2 new1 1 ## 3 new2 2 change values mydb$queryUpdate(\"sps_meta\", value = '234', col = \"value\", WHERE = \"info = 'new1'\") ## [SPS-INFO] 2021-04-22 15:45:04 Updated 1 rows # check the update mydb$queryValue(\"sps_meta\") ## info value ## 1 creation_date 20210422154504 ## 2 new1 234 ## 3 new2 2 remove values mydb$queryDel(\"sps_meta\", WHERE = \"value = '234'\") ## [SPS-INFO] 2021-04-22 15:45:05 Deleted 1 rows # check again mydb$queryValue(\"sps_meta\") ## info value ## 1 creation_date 20210422154504 ## 2 new2 2 spsEncryption class Reference manual under SPS Functions.\nStart by creating a class object\nmy_ecpt \u003c- spsEncryption$new() ## [SPS-INFO] 2021-04-22 15:45:05 Created SPS encryption method container ## [SPS-INFO] 2021-04-22 15:45:05 Default SPS-db found and is working Get current key To see the public and private keys (in {openssil{blk}} format):\n# private my_ecpt$keyGet() ## [2048-bit rsa private key] ## md5: 6306a50abcf3c7618566911a793b0405 # public my_ecpt$keyGet()$pubkey ## [2048-bit rsa public key] ## md5: 6306a50abcf3c7618566911a793b0405 Change the encyption key Be super careful to change the encryption key. This will result any file encrypted by the old key pair unlockable and the password of all current accounts invalid.\nBy default it will prevent you to change the key in case you accidentally run this method\nmy_ecpt$keyChange() ## [SPS-DANGER] 2021-04-22 15:45:05 ## change this key will result all accounts' password failed to ## authenticate. You have to regenerate all password for all ## accounts. All encrypted file using the old key will fail to ## decrypt. There is NO way to RECOVER the old key, password ## and files. If you wish to continue, recall this function ## with `confirm = TRUE`. Unless you are super sure with a confirmation\nmy_ecpt$keyChange(confirm = TRUE) ## [SPS-INFO] 2021-04-22 15:45:05 md5 42e4b167ba388a9e797608eb4e466a18 Encrypt files # imagine a file has one line \"test\" writeLines(text = \"test\", con = \"test.txt\") my_ecpt$encrypt(\"test.txt\", \"test.bin\", overwrite = TRUE) Decrypt files my_ecpt$decrypt(\"test.bin\", \"test_decpt.txt\", overwrite = TRUE) Check the decrypted file content\nreadLines('test_decpt.txt') ## [1] \"test\" spsAcount class This class is discussed in details in the Accounts, login and admin.\n","categories":"","description":"","excerpt":" SPS database is a small SQLite database which stores some basic app …","ref":"/sps/adv_features/database/","tags":"","title":"SPS database"},{"body":" SPS accounts After a SPS project is initialized, some default accounts has been set up. They will not become useful unless you enable the login and admin features.\nThere are 2 default accounts created for you to test before deploy:\n name role password admin admin admin user user user The admin account can be used in both the main app login and admin page login, and the user account can only be used for main app login.\nPlease change these accounts before deployment.\nAccount management You can manage accounts in two ways: commandline and admin page. Here is how you manage from commandline, read how to do it from admin page below.\nThere are some helper code inside global.R file under your SPS project root.\n## account information ## PLEASE use following to add your own accounts and remove the default accounts for deployment # mydb \u003c- spsAccount$new() # mydb$accList() # mydb$accAdd(acc_name = \"XXX\", acc_pass = \"$xxxx\", role = \"admin\") # mydb$accRemove(\"admin\") # mydb$accRemove(\"user\") You can uncomment these lines to practice how to manage accounts, or read the reference manual about spsAccount class.\nFirst to create a SPS project\nsuppressPackageStartupMessages(library(systemPipeShiny)) app_path \u003c- \".\" spsInit(app_path = app_path, overwrite = TRUE, open_files = FALSE) ## [SPS-INFO] 2021-04-16 16:25:15 Start to create a new SPS project ## [SPS-INFO] 2021-04-16 16:25:15 Create project under /tmp/RtmpMoNp2X/SPS_20210416 ## [SPS-INFO] 2021-04-16 16:25:15 Now copy files ## [SPS-INFO] 2021-04-16 16:25:15 Create SPS database ## [SPS-INFO] 2021-04-16 16:25:15 Created SPS database method container ## [SPS-INFO] 2021-04-16 16:25:15 Creating SPS db... ## [SPS-DANGER] 2021-04-16 16:25:15 Done, Db created at '/tmp/RtmpMoNp2X/SPS_20210416/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-16 16:25:15 Key md5 db686a4f203edbdd0fe4c2a1642492d2 ## [SPS-INFO] 2021-04-16 16:25:15 SPS project setup done! Create a spsAccount object. SPS accounts are stored in the config/sps.db database inside your SPS projects.\nacc \u003c- spsAccount$new() ## [SPS-INFO] 2021-04-16 16:25:15 Created SPS account method container ## [SPS-INFO] 2021-04-16 16:25:15 Default SPS-db found and is working ## [SPS-INFO] 2021-04-16 16:25:15 Creating SPS db... ## [SPS-DANGER] 2021-04-16 16:25:15 Done, Db created at 'config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-16 16:25:15 Key md5 127f00770c4ed318c48fe92cd67bf783 See what accounts you have\nacc$accList() ## account role ## 1 admin admin ## 2 user user You can also listed passwords. They are SHA256 encrypted.\ntibble::as_tibble(acc$accList(include_pass = TRUE)) ## # A tibble: 2 x 3 ## account pass role ## \u003cchr\u003e \u003cchr\u003e \u003cchr\u003e ## 1 admin 0b1460498bf1b50e05cc07e53c7856fc23ecd3fc2bc404d52dbf3aae743f8a9a admin ## 2 user 796be5ca7dafddf5e1e7c032fc71386fe16274f63b6068bb2b064d4c9876eaae user See SPS database for encryption key details.\nAdd a new user\nacc$accAdd(acc_name = 'user2', acc_pass = '!newuser12345', role = \"user\") ## [SPS-INFO] 2021-04-16 16:25:15 Account user2 created. Change the role of user2 from “user” to “admin”\nacc$accRoleChange(acc_name = \"user2\", role = \"admin\") ## [SPS-INFO] 2021-04-16 16:25:15 Updated 1 rows ## [SPS-INFO] 2021-04-16 16:25:15 Account user2 role changed. Remove a user\nacc$accRemove(\"user2\") ## [SPS-INFO] 2021-04-16 16:25:15 Deleted 1 rows ## [SPS-INFO] 2021-04-16 16:25:15 Account user2 removed acc$accList() ## account role ## 1 admin admin ## 2 user user Change password\nacc$accPassChange(acc_name = \"user\", , acc_pass = '!newuser54321') ## [SPS-INFO] 2021-04-16 16:25:15 Updated 1 rows ## [SPS-INFO] 2021-04-16 16:25:15 Account user password created. Validate password\nacc$accMatch(acc_name = \"user\", acc_pass = '!newuser54321') ## [1] TRUE acc$accMatch(acc_name = \"user\", acc_pass = \"user\") ## [1] FALSE acc$accMatch(acc_name = \"abc\", acc_pass = \"123\") ## [1] FALSE Validate password + role\nacc$accMatch(acc_name = \"user\", acc_pass = '!newuser54321', match_role = TRUE, role = \"user\") ## [1] TRUE acc$accMatch(acc_name = \"user\", acc_pass = '!newuser54321', match_role = TRUE, role = \"admin\") ## [1] FALSE Main app login After the account has been set up properly, one can try to turn on the login page for the main app. Use spsOption(\"login_screen\", TRUE) or set login_screen = TRUE in global.R file.\nWhether enabling the login screen is fundamentally different how the Shiny app loads the UI and server code.\n Disabled: loads UI and server on app start Enabled: loads login UI and server on start, loads main app UI and server code only when login is successful. One advantage of using the login is the app starting time is fast. On app start, it only loads the login logic so it saves some time. The heavy part is the main app logic which will be loaded after a successful login. So the overall loading time is about the same. The difference is at what time point to load main app. Of course, if the user fails to login, main app will never be loaded. This can save some resources to handle unauthorized requests.\nThis difference may cause some javascript not working if you are loading your custom tabs with custom javascript. Set a wait signal in your javascript or report an issue to us if you have troubles.\n The login screen is also controlled by another setting login_theme. By default, if you turn on the “login_screen”, app will show you a random loading theme (login_theme = \"random\") before you see the login panel. You can interact with these themes or change to play with a different theme. Or you can specify your favorate from “vhelix” (DNA double helix), “hhelix” (DNA flow), or “biomatrix” (DNA Matrix).\n If you are not a fan of these themes, you can use login_theme = \"empty\" to directly go to login panel.\n Admin page SPS Admin page is panel of tabs to help app managers administrate the app. Under current version, SPS provides 2 main features: app information/statistics and account control.\nAdmin login To reach the Admin page, users first need to enable this feature (default is TRUE) in SPS options admin_page use either spsOption(\"admin_page\", TRUE) or set it in global.R. Afterwards, users need type in the correct url to find the page. This can be set with the SPS option admin_url. Default is “admin”, admin_url = \"admin\", but for security we recommend you to change it in deployment. \nTo access it, add “?” + “YOUR_ADMIN_URL” to your app url to visit it. For example:\nwe have a demo https://tgirke.shinyapps.io/systemPipeShiny_loading/\nto visit the admin page, then we visit https://tgirke.shinyapps.io/systemPipeShiny_loading/?admin\n Admin login page\n You can use the testing account “admin” and password “admin” to login, but for security we strongly recommend you to change it in deployment. \nApp information The first tab of the Admin page is current app and server information, like CPU, RAM, size, etc. On this tab, under details, some real-time statistic plots are rendered. You can interact with these plots to dig for more information.\n Admin page app info\n Account control Instead of changing account information from commandline, you can use this tab to add / remove / change password/ change roles of current app accounts.\n Admin page user control\n Create a new user\n ","categories":"","description":"","excerpt":" SPS accounts After a SPS project is initialized, some default …","ref":"/sps/adv_features/login/","tags":"","title":"Accounts, Login and Admin"},{"body":" Guidelines from bioconductor_docker.\n Running the systemPipeR with Docker Get a copy of the public docker image docker pull systempipe/systempipe_docker:latest To run RStudio Server: docker run -e PASSWORD=systemPipe -p 8787:8787 \\ systempipe/systempipe_docker:latest You can then open a web browser pointing to your docker host on port 8787. If you’re on Linux and using default settings, the docker host is 127.0.0.1 (or localhost, so the full URL to RStudio would be http://localhost:8787). If you are on Mac or Windows and running Docker Toolbox, you can determine the docker host with the docker-machine ip default command.\nIn the above command, -e PASSWORD= is setting the RStudio password and is required by the RStudio Docker image. It can be whatever you like except it cannot be rstudio. Log in to RStudio with the username rstudio and whatever password was specified, in this example systemPipe.\nTo run R from the command line: docker run -it --user rstudio systempipe/systempipe_docker:latest R To open a Bash shell on the container: docker run -it --user rstudio systempipe/systempipe_docker:latest bash Install Prerequisites: Linux Mac Windows\nInstructions here on how to install Docker Engine on Ubuntu.\nsudo apt-get update sudo apt-get install \\ apt-transport-https \\ ca-certificates \\ curl \\ gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo \\ \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\ $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list \u003e /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io ## Verify that Docker Engine is installed correctly by running the hello-world image. sudo docker run hello-world Uninstall sudo apt-get remove docker docker-engine docker.io containerd runc Docker Hub Account To be able to share a custom image, please go to https://hub.docker.com and create a free account.\n Log in to the Docker Hub locally Login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.\ndocker login # Username: XXXX # Password: xxx # Login Succeeded Run Docker docker run-dP systempipe/systempipe_docker:latest Make sure the container is running:\ndocker ps # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS # NAMES #5d007f66a7b3 systempipe/systempipe_docker:latest \"/init\" 5 minutes ago Up 5 minutes 0.0.0.0:49153-\u003e8787/tcp determined_easle Login to the container Please check the NAMES in this example, determined_easle, to login into the container.\ndocker exec -it determined_easle /bin/bash Other alternatives to run the container To run RStudio Server: docker run -e PASSWORD=systemPipe -p 8787:8787 \\ systempipe/systempipe_docker:latest To run R from the command line: docker run -it --user rstudio systempipe/systempipe_docker:latest R To open a Bash shell on the container: docker run -it --user rstudio systempipe/systempipe_docker:latest bash Check R Version into the container R --version Stop Docker docker stop determined_easle Create your first repository Link Create a repository: Sign in to Docker Hub. Click Create a Repository on the Docker Hub welcome page: Name it /my-repo. Click Create. Build and push a container image to Docker Hub from your computer Start by creating a Dockerfile to specify your application mkdir docker_test cd docker_test touch Dockerfile # Docker inheritance FROM systempipe/systempipe_docker:latest ## Install BiocStyle RUN R -e 'BiocManager::install(\"BiocStyle\")' # Install required Bioconductor package from devel version RUN R -e 'BiocManager::install(\"tgirke/systemPipeR\")' RUN R -e 'BiocManager::install(\"tgirke/systemPipeRdata\")' WORKDIR /home/rstudio/SPRojects COPY --chown=rstudio:rstudio . /home/rstudio/SPRojects # Metadata LABEL name=\"systempipe/systempipe_docker\" \\ version=$BIOCONDUCTOR_DOCKER_systempipe \\ url=\"https://github.com/systemPipeR/systempipe/systempipe_docker\" \\ vendor=\"systemPipeR Project\" \\ maintainer=\"email@gmail.com\" \\ description=\"Bioconductor docker image containing the systemPipeR Project\" \\ license=\"Artistic-2.0\" Run docker build to build your Docker image docker build -t systempipe/systempipe_docker . Run docker run to test your Docker image locally docker run -e PASSWORD=systemPipe -p 8787:8787 systempipe/systempipe_docker:latest Run docker push to push your Docker image to Docker Hub docker push systempipe/systempipe_docker Your repository in Docker Hub should now display a new latest tag under Tags Make changes to the container and Create the new image Create a folder, for example:\ndocker run -dP systempipe/systempipe_docker docker ps ## To check the NAME \u003clucid_grothendieck\u003e docker exec -it lucid_grothendieck /bin/bash root@33c758eb1626:/# R setwd(\"home/rstudio/\") systemPipeRdata::genWorkenvir(\"rnaseq\") exit docker commit -m \"Added rnaseq template\" -a \"Dani Cassol\" lucid_grothendieck dcassol/systempipeworkshop2021:rnaseq docker push systempipe/systempipe_docker:rnaseq Run the new image:\ndocker run -e PASSWORD=systemPipe -p 8787:8787 systempipe/systempipe_docker:rnaseq Commands List which docker machines are available locally docker images\nList running containers docker ps\nList all containers docker ps -a\nResume a stopped container docker start \u003cCONTAINER ID\u003e\nShell into a running container docker exec -it \u003cCONTAINER ID\u003e /bin/bash\nStop OR remove a cointainer docker stop \u003cCONTAINER ID\u003e docker rm \u003cCONTAINER ID\u003e\nRemove a image docker rmi dcassol/systempipeworkshop2021:rnaseq\n Docker and GitHub Actions To create a new token, go to Docker Hub Settings 1.1. Account Settings » Security » New Access Token 1.2. Add Access Token Description » Create 1.3. Copy the Access Token » Copy and Close\nGo to the Repository at GitHub 2.1. Settings \u003e Secrets \u003e New repository secret 2.2. Create a new secret with the name DOCKER_HUB_USERNAME and your Docker ID as value 2.3. Click at Add secret 2.4. Create a new secret with the name DOCKER_HUB_ACCESS_TOKEN and your Personal Access Token (PAT) as value (generated in the previous step)\nSet up the GitHub Actions workflow steps: - name: Checkout Repo uses: actions/checkout@v2 - name: Login to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} Common Problems ## Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.24/auth: dial unix /var/run/docker.sock: connect: permission denied Solution:\nsudo chmod 666 /var/run/docker.sock Singularity Container Please download the Docker image of systemPipe, as follow:\nsingularity pull docker://systempipe/systempipe_docker:latest You can also use the build command to download pre-built images from Docker. Unlike pull, build will convert the image to the latest Singularity image format after downloading it.\nsingularity build systempipe_docker_latest.sif docker://systempipe/systempipe_docker:latest To run the container:\nsingularity shell systempipe_docker_latest.sif Resources Docker Run: How to create images from an application Docker Hub Quickstart Configure GitHub Actions Singularity ","categories":"","description":"","excerpt":" Guidelines from bioconductor_docker.\n Running the systemPipeR with …","ref":"/sp/spr/sp_docker/","tags":"","title":"SPR Docker container"},{"body":" There are some options in SPS that will give you more information and help you on debugging. They are: verbose and traceback. You can config (enable/disable) themin a SPS project’s global.R file, or use spsOption(\"verbose\", TRUE) and spsOption(\"traceback\", TRUE) to turn on them.\nSome setup:\nsuppressPackageStartupMessages(library(systemPipeShiny)) app_dir \u003c- tempdir() spsInit(app_path = app_dir, overwrite = TRUE, change_wd = FALSE, open_files = FALSE) ## [SPS-INFO] 2021-04-16 17:46:53 Start to create a new SPS project ## [SPS-INFO] 2021-04-16 17:46:53 Create project under /tmp/RtmpUfKCYR/SPS_20210416 ## [SPS-INFO] 2021-04-16 17:46:53 Now copy files ## [SPS-INFO] 2021-04-16 17:46:53 Create SPS database ## [SPS-INFO] 2021-04-16 17:46:53 Created SPS database method container ## [SPS-INFO] 2021-04-16 17:46:53 Creating SPS db... ## [SPS-DANGER] 2021-04-16 17:46:53 Done, Db created at '/tmp/RtmpUfKCYR/SPS_20210416/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-16 17:46:53 Key md5 fc8c85a0e87073328864bd542d740801 ## [SPS-INFO] 2021-04-16 17:46:53 SPS project setup done! app_path \u003c- file.path(app_dir, glue::glue(\"SPS_{format(Sys.time(), '%Y%m%d')}\")) verbose In many SPS functions, there is this argument verbose and usually default is FALSE. It means do not print extra message, keep it clean. You can set in spsOption(\"verbose\", TRUE) or inside global.R file to turn on. These are called global settings, and you can use a local setting to overwrite it (func(..., verbose = TRUE)).\nLet’s use SPS main function sps for example, without the verbose\nspsOption(\"verbose\", FALSE) app \u003c- sps(app_path = app_path) ## Warning: [SPS-WARNING] 2021-04-16 17:46:53 These plot tabs has no image path: ## 'vs_example' ## It is recommended to add an image. It will be used to generate gallery. Now an empty image is used for these tabs' gallery. ## [SPS-INFO] 2021-04-16 17:46:55 App starts ... Turn on the verbose:\nspsOption(\"verbose\", TRUE) app \u003c- sps(app_path = app_path) ## [SPS-INFO] 2021-04-16 17:46:55 App has 19 default configs, resolving 19 custom configs ## [SPS-INFO] 2021-04-16 17:46:55 Now check the tab info in tabs.csv ## Warning: [SPS-WARNING] 2021-04-16 17:46:55 These plot tabs has no image path: ## 'vs_example' ## It is recommended to add an image. It will be used to generate gallery. Now an empty image is used for these tabs' gallery. ## [SPS-INFO] 2021-04-16 17:46:55 tab.csv info check pass ## [SPS-INFO] 2021-04-16 17:46:55 Using default tabs ## [SPS-INFO] 2021-04-16 17:46:55 check guide ## [SPS-INFO] 2021-04-16 17:46:55 Start to generate UI ## [SPS-INFO] 2021-04-16 17:46:55 parse title and logo ## [SPS-INFO] 2021-04-16 17:46:55 resolve default tabs UI ## [SPS-INFO] 2021-04-16 17:46:55 Loading custom tab UI ... ## [SPS-INFO] 2021-04-16 17:46:55 Loading notifications from developer... ## [SPS-INFO] 2021-04-16 17:46:55 Loading guide UI ## [SPS-INFO] 2021-04-16 17:46:55 Create UI header ... ## [SPS-INFO] 2021-04-16 17:46:55 Create UI sidebar menu ... ## [SPS-INFO] 2021-04-16 17:46:55 Create UI tab content ... ## [SPS-INFO] 2021-04-16 17:46:55 Add tab content to body ... ## [SPS-INFO] 2021-04-16 17:46:55 Merge header, menu, body to dashboard ... ## [SPS-INFO] 2021-04-16 17:46:55 Add overlay loading screen, admin panel. ## Merge everything to app container ... ## [SPS-INFO] 2021-04-16 17:46:55 UI created ## [SPS-INFO] 2021-04-16 17:46:55 Start to create server function ## [SPS-INFO] 2021-04-16 17:46:55 Resolve default tabs server ## [SPS-INFO] 2021-04-16 17:46:55 Load custom tabs servers ## [SPS-INFO] 2021-04-16 17:46:55 Server functions created ## [SPS-INFO] 2021-04-16 17:46:55 App starts ... Exception There is one exception which is the spsInit. It is used to create a SPS project for you, so it assumes you do not have a SPS project yet and therefore do not have the chance to reach SPS options. So the verbose global setting will not work here. You need to turn it on locally with verbose = TRUE.\nCompare messages of this with the initial spsInit creation on top.\nspsInit(verbose = TRUE, app_path = app_path, overwrite = TRUE, change_wd = FALSE, open_files = FALSE) ## [SPS-INFO] 2021-04-16 17:46:55 Start to create a new SPS project ## [SPS-INFO] 2021-04-16 17:46:55 Create project under /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416 ## [SPS-INFO] 2021-04-16 17:46:55 Now copy files ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/www ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/config ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/R ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/data ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/results ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/README.md ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/deploy.R ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/server.R ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/global.R ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/ui.R ## [SPS-INFO] 2021-04-16 17:46:55 File(s) copied for /tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/server.R ## [SPS-INFO] 2021-04-16 17:46:55 Create SPS database ## [SPS-INFO] 2021-04-16 17:46:55 Created SPS database method container ## [SPS-INFO] 2021-04-16 17:46:55 Db connected ## [SPS-INFO] 2021-04-16 17:46:55 Default SPS-db found and is working ## [SPS-INFO] 2021-04-16 17:46:55 Db connected ## [SPS-INFO] 2021-04-16 17:46:55 Creating SPS db... ## [SPS-INFO] 2021-04-16 17:46:55 Db write the meta table ## [SPS-INFO] 2021-04-16 17:46:56 Db write the raw table ## [SPS-INFO] 2021-04-16 17:46:56 Key generated and stored in db ## [SPS-INFO] 2021-04-16 17:46:56 Db create admin account ## [SPS-DANGER] 2021-04-16 17:46:56 Done, Db created at '/tmp/RtmpUfKCYR/SPS_20210416/SPS_20210416/config/sps.db'. DO NOT share this file with others or upload to open access domains. ## [SPS-INFO] 2021-04-16 17:46:56 Key md5 7dca8a45de4d7260f91ddb1a02d0a6bd ## [SPS-INFO] 2021-04-16 17:46:56 SPS project setup done! traceback When error happens, it will be helpful if we can know where it happened. This option will give you additional information of which function it happened, the system call list and error file and line of code if possible.\nThis feature is enabled in two functions sps and shinyCatch.\n sps: Adding tracebacks if there are some errors sourcing helper functions located in your SPS project under the R folder. shinyCatch: Traceback errors of expressions inside shinyCatch Let’s use shinyCatch to demo.\nBefore adding traceback:\nspsOption(\"traceback\", FALSE) shinyCatch({ stop(\"some error message\") }) ## [SPS-ERROR] 2021-04-16 17:46:56 some error message ## NULL After\nspsOption(\"traceback\", TRUE) shinyCatch({ stop(\"some error message\") }) ## 1. local({ ## if (length(a \u003c- commandArgs(TRUE)) != 2) ## stop(\"The number of arguments passed to Rscript should be 2.\") ## x = readRDS(a[1]) ## f = x[[1]] ## if (is.character(f)) ## f = eval(parse(text = f), envir = globalenv()) ## r = do.call(f, x[[2]], envir = globalenv()) ## saveRDS(r, a[2]) ## }) ## 2. eval.parent(substitute(eval(quote(expr), envir))) ## 3. eval(expr, p) ## 4. eval(expr, p) ## 5. eval(quote({ ## if (length(a \u003c- commandArgs(TRUE)) != 2) stop(\"The number of arguments passed to Rscript should be 2.\") ## x = readRDS(a[1]) ## f = x[[1]] ## if (is.character(f)) f = eval(parse(text = f), envir = globalenv()) ## r = do.call(f, x[[2]], envir = globalenv()) ## saveRDS(r, a[2]) ## }), new.env()) ## 6. eval(quote({ ## if (length(a \u003c- commandArgs(TRUE)) != 2) stop(\"The number of arguments passed to Rscript should be 2.\") ## x = readRDS(a[1]) ## f = x[[1]] ## if (is.character(f)) f = eval(parse(text = f), envir = globalenv()) ## r = do.call(f, x[[2]], envir = globalenv()) ## saveRDS(r, a[2]) ## }), new.env()) ## 7. do.call(f, x[[2]], envir = globalenv()) ## 8. (function (input, output, to_md = file_ext(output) != \"html\", quiet = TRUE) ## { ## options(htmltools.dir.version = FALSE) ## setwd(dirname(input)) ## input = basename(input) ## if (to_md) ## options(bookdown.output.markdown = TRUE) ## res = rmarkdown::render(input, \"blogdown::html_page\", output_file = output, envir = globalenv(), quiet = quiet, run_pandoc = !to_md, clean = !to_md) ## x = read_utf8(res) ## if (to_md) ## x = process_markdown(res, x) ## unlink(res) ## x ## })(\"content/en/sps/adv_features/debug.Rmd\", \"debug.md~\", TRUE, TRUE) ## 9. rmarkdown::render(input, \"blogdown::html_page\", output_file = output, envir = globalenv(), quiet = quiet, run_pandoc = !to_md, clean = !to_md) ## 10. knitr::knit(knit_input, knit_output, envir = envir, quiet = quiet) ## 11. process_file(text, output) ## 12. withCallingHandlers(if (tangle) process_tangle(group) else process_group(group), error = function(e) { ## setwd(wd) ## cat(res, sep = \"\\n\", file = output %n% \"\") ## message(\"Quitting from lines \", paste(current_lines(i), collapse = \"-\"), \" (\", knit_concord$get(\"infile\"), \") \") ## }) ## 13. process_group(group) ## 14. process_group.block(group) ## 15. call_block(x) ## 16. block_exec(params) ## 17. in_dir(input_dir(), evaluate(code, envir = env, new_device = FALSE, keep_warning = !isFALSE(options$warning), keep_message = !isFALSE(options$message), stop_on_error = if (options$error \u0026\u0026 options$include) 0 else 2, output_handler = knit_handlers(options$render, options))) ## 18. evaluate(code, envir = env, new_device = FALSE, keep_warning = !isFALSE(options$warning), keep_message = !isFALSE(options$message), stop_on_error = if (options$error \u0026\u0026 options$include) 0 else 2, output_handler = knit_handlers(options$render, options)) ## 19. evaluate::evaluate(...) ## 20. evaluate_call(expr, parsed$src[[i]], envir = envir, enclos = enclos, debug = debug, last = i == length(out), use_try = stop_on_error != 2, keep_warning = keep_warning, keep_message = keep_message, output_handler = output_handler, include_timing = include_timing) ## 21. timing_fn(handle(ev \u003c- withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, error = eHandler, message = mHandler))) ## 22. handle(ev \u003c- withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, error = eHandler, message = mHandler)) ## 23. withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, error = eHandler, message = mHandler) ## 24. withVisible(eval(expr, envir, enclos)) ## 25. eval(expr, envir, enclos) ## 26. eval(expr, envir, enclos) ## 27. shinyCatch({ ## stop(\"some error message\") ## }) ## 28. tryCatch(suppressMessages(suppressWarnings(withCallingHandlers(expr, message = function(m) toastr_actions$message(m), warning = function(m) toastr_actions$warning(m), error = function(m) if (trace_back) printTraceback(sys.calls())))), error = function(m) { ## toastr_actions$error(m) ## return(NULL) ## }) ## 29. tryCatchList(expr, classes, parentenv, handlers) ## 30. tryCatchOne(expr, names, parentenv, handlers[[1]]) ## 31. doTryCatch(return(expr), name, parentenv, handler) ## 32. suppressMessages(suppressWarnings(withCallingHandlers(expr, message = function(m) toastr_actions$message(m), warning = function(m) toastr_actions$warning(m), error = function(m) if (trace_back) printTraceback(sys.calls())))) ## 33. withCallingHandlers(expr, message = function(c) if (inherits(c, classes)) tryInvokeRestart(\"muffleMessage\")) ## 34. suppressWarnings(withCallingHandlers(expr, message = function(m) toastr_actions$message(m), warning = function(m) toastr_actions$warning(m), error = function(m) if (trace_back) printTraceback(sys.calls()))) ## 35. withCallingHandlers(expr, warning = function(w) if (inherits(w, classes)) tryInvokeRestart(\"muffleWarning\")) ## 36. withCallingHandlers(expr, message = function(m) toastr_actions$message(m), warning = function(m) toastr_actions$warning(m), error = function(m) if (trace_back) printTraceback(sys.calls())) ## [SPS-ERROR] 2021-04-16 17:46:56 some error message ## NULL Or use local setting to overwrite the global, even we have spsOption(\"traceback\", TRUE), but traceback is still muted by trace_back = FALSE.\nspsOption(\"traceback\", TRUE) shinyCatch({ stop(\"some error message\") }, trace_back = FALSE) ## [SPS-ERROR] 2021-04-16 17:46:56 some error message ## NULL Traceback with file and line number Let’s write an R file with functions, source it and then call the function from this file. Try it on your own computer:\ntemp_file \u003c- tempfile(fileext = \".R\") writeLines( \"myFunc \u003c- function(){ myFunc2() } myFunc2 \u003c- function(){ stop('some error message') } \", temp_file ) source(temp_file) shinyCatch({ myFunc() }) You can see the error happened in myFunc line No. 2 and then inside this function it calls another function myFunc2 which caused the final error. In myFunc2 it is also the line No. 2 caused the issue and error is coming from /tmp/... file.\nother Shiny built-in options There are some Shiny options can also be helpful on debugging:\n# developer mode, use ?devmode to see details devmode(TRUE) # inspect reactivity in shiny options(shiny.reactlog = TRUE) # similar to SPS's traceback but on the whole app level options(shiny.fullstacktrace = TRUE) # open the `browser` debug mode on error options(shiny.error = browser) # when a shiny app file saves, reload the app, not working with modular apps like SPS at this moment options(shiny.autoreload = TRUE) See Shiny option website{blk} for more details\n","categories":"","description":"","excerpt":" There are some options in SPS that will give you more information and …","ref":"/sps/adv_features/debug/","tags":"","title":"Debugging"},{"body":"systemPipeR 2.2.0 is available https://bioconductor.org/packages/3.15/bioc/html/systemPipeR.html\nsystemPipeRdata 2.0.0 is available https://bioconductor.org/packages/release/data/experiment/html/systemPipeRdata.html\nsystemPipeShiny 1.6 is available http://bioconductor.org/packages/3.15/bioc/html/systemPipeShiny.html\nsystemPipeTools 1.2.0 is available https://bioconductor.org/packages/3.15/bioc/html/systemPipeTools.html\n","categories":"","description":"","excerpt":"systemPipeR 2.2.0 is available …","ref":"/news/release_3_15/","tags":"","title":"Bioconductor 3.15"},{"body":"systemPipeTools 1.0.0 is available systemPipeTools package extends the widely used systemPipeR (SPR) workflow environment with an enhanced toolkit for data visualization, including utilities to automate the data visualization for analysis of differentially expressed genes (DEGs). systemPipeTools provides data transformation and data exploration functions via scatterplots, hierarchical clustering heatMaps, principal component analysis, multidimensional scaling, generalized principal components, t-Distributed Stochastic Neighbor embedding (t-SNE), and MA and volcano plots. All these utilities can be integrated with the modular design of the systemPipeR environment that allows users to easily substitute any of these features and/or custom with alternatives.\nsystemPipeShiny 1.2 is available systemPipeShiny 1.1.40 Major change Add is_demo option: only affect workflow module right now. Lock users inside a temp folder when using the WF module and give users a new temp folder every time they refresh. This will prevent directory exist problem if many users are using a same deploy instance.\n Add welcome_guide option: whether to enable the welcome guide which highlights the guide dropdown menu.\n Rewrite welcome tab with a gallery to show all SPS features.\n loadDF, dynamicFile and dynamicFileServer added back to this mainframe work package instead of spsComps, because these dependencies have already been using in SPS. Leave these functions in spsComps will introduce extra dependencies, and these functions are not too frequently used outside the framework.\n Minor change Option warning_toast now also checks if you are on “local” mode.\n Deleted some unwanted entries in reference generating yaml file.\n Fix some typos.\n More informative error message when the config file cannot be found for spsOptions\n Add some .onLoad methods so users can use the spsOption to get default values on package load.\n Updated essquise functions\n Add more guides.\n Removed the scroll to top button by shinyDashboardPlus, we have our own “go top” button.\n Add assertions to spsInit.\n Add some screenshots to readme.\n Bug fix Fix a bug when that loads the server twice Fix some default option values Fix a bug on addResourcePath when the working directory and app directory is not the same. Fix links not working caused by website change Fix code in spsInit overwrite all current SPS options. Fix errors on admin page when server stats cannot be found, better text and warning messages Fix new version of essquise introduced errors Fix a warning in vroom due to the column type problem systemPipeShiny 1.1.35 Major change Login feature added:\n Users can choose whether to enable the login or not in global.RSPS options.\n There are also the login loading screen feature which can be turned on and off.\n There are 3 different login loading screens right now and users can interact with them.\n Website updated. https://systempipe.org/sps\n Updates on the admin panel:\n App information: added live charts for CPU, temperature, and RAM\n User control: admins now can add/delete/change users directly from this tab, instead of only from command line.\n Minor change Addtarget=\"_blank\" to all external links in the app, so when they are clicked, it will open in a new tab. Bug fix FIx bugs due to login page caused server not loading\n Add 1s delay in javascript after login to resize the page so the dashboard can be displayed normal.\n Fix a table rendering bug in workflow cwl step markdown text.\n systemPipeShiny 1.1.30 Major change new spsAccount class. This class is associated with login management , which allows users to create/delete user/admin accounts, change password, change roles.\n Deprecated the spsPlotContainer class since we rewrite the Canvas feature and move to a separate package {drawer}.\n New spsCoreTabReplace, which allows users to overwrite the default core tabs.\n A lot more SPS options.\n Users can now choose whether to load or not load certain tabs on start, even for default core tabs. Combining the spsCoreTabReplace function, now users can customize everything of the original app.\n Users can change the app title, and logo image.\n Admin panel added to app. Users now can visit the admin panel by adding “?user_definded_string” to the end of the url. Default is “admin”. Login with an admin account is required. Users can use the spsAccount class to add/change an admin account before starting the app.\n App information: a tab displays current SPS app server information, like CPU, RAM, size, etc.\n User control: a tab to see account information of current SPS app.\n Changed the way to install modules. Default modules, workflow, RNAseq and quick ggplot dependency packages are not installed by default, unless you use dependency = TRUE in installation command. It means all these dependencies are moved from Imports to the Suggests class. This helps to save quite some time on SPS package installation. Users install these packages based on their needs. When users loads these modules but depend packages are not fully installed, app will not crash, instead, a warning message with install instructions will be displayed on both console and app UI.\n Based on the module installation change, module loading methods are also changed. Module server functions are only called if users set the option to load them. In previous versions, the server functions are still loaded, just hide the unloaded module UI. This saves a lot of time on app starting time, roughly from \u003e 10s to \u003c 3s if none of the default modules are loaded.\n Bug fix update all links to our new website: https://systempipe.org/sps\n Fix some bugs in the guide system\n systemPipeShiny 1.1.20 Major change 3 default modules complete: workflow, RNAseq,quick ggplot. Details of these modules updated in our website: \u003chttps://systempipe.org/sps\u003e{.uri}.\n Separation of SPS smaller functions into 3 different packages. We hope these packages can help people in their own Shiny app, or other R projects.\n {spsComps}: SPS components, all new Shiny custom components and utility functions that are used in Shiny server side.\n {drawer}: the redesign of Canvas, purely front-end image editing tool.\n {spsUtil}: SPS utilities, general useful utility functions that can be used with/without Shiny.\n Redesigned the new tab feature. Now users use spsNewTab function to create their new custom visualization tab. The old newSpsTab function is deprecated. Easier syntax and templates are used. By default it will use the “simple” template which wraps 90% of the shiny code from users so they can focus on the plotting code. There is also the “full” template which expose all the Shiny code to users.\n New spsEzUI and spsEzServer functions are used in the “simple” template to wrap complex Shiny code. New spsOptDefaults, which prints out all the default SPS options and current values of these options on console.\n New notification system. Developers can write some notifications which stores in a remote location and when app starts, it will try to download and parse this file to notifications messages to broadcast to users. This way, developers can send messages to users often without re-deploy the app. The notification will appear on the top right corner.\n The interactive guide is back. After a few versions of tests, we added the guide system back. This time, developers can customize their own guides. A guide_content.R file is created when a SPS project initialize. It is stored in R of folder relate to the project root. The guide will also be displayed on the app top right corner.\n Minor change updated all unit test to testthat v3 format. Bug fix fix bugs due to shiny updates to 1.6.0\n Fix all bugs caused by {shinydashboardPlus} v2.0 updates.\n systemPipeShiny 1.1.10 Changes made from 1.1.0 to 1.1.05 Workflow module R session Now workflow module R session uses a background child R process, which runs independently to the parent R session which runs shiny. So the shiny will be not blocked while code is running in the background (you can still click other buttons when the child session is busy) – synchronous and non-blocking. A child indicator is also placed in the UI, updates every second. The UI design of R session is similar to Rstudio. Four panels, source code, console, log (specific to SPR), and plots. Standard out/error and plots are captured in the workflow folder. Users can download them in the bundle on step 5 Workflow Run. Plots will be displayed on the plots panel. Now supports plots that opens R device (base and ggplot), html widget plots are not supported as this moment. A new shiny disconnection popup for SPS. Besides the gray layer on shiny disconnection, a panel will be displayed to users to indicate the problem. Similar to what shows on a shiny server, but more informative and also works locally. Results of this session can be downloaded by closing the session and go back to step 5 of workflow module and there is a button to download all in a zipped file. RNAseq module redesigned the UI and server logic. Plots for DEG analysis and Canvas connections. {SummarizedExperiment} supports. Now it returns SummarizedExperiment objects to global environment once the normalization or DEG calculation is done. General UI Added a “Go Top” button on the right bottom corner, clicking on this button will automatically scroll to the top of the page. This button only shows up when client has \u003e 50px scroll height. Workflow module CWL tab Now the CWL file and CWL input file can be be edited. The edits will be imported to CWL parser every one second. Now this is a very useful place to test or write new CWL scripts. Now this tab has a dynamically rendered dropdown panel which allows users to choose which column for the targets table to map to the variables in CWL input file. Workflow module fully functioning Now you can run a full example workflow in SPS by choosing the “Example” option on workflow setup step.\n Other systemPipeR preconfiged workflows will cause problems because formatting issues that will cause errors in systemPipeR::runWF function, not introduced by SPS. Please wait the updates on systemPipeR to fix this. You can still use SPS to prepare files for all workflows. That means, step 1-4 will work, step 5 will give you errors if you choose a workflow which is not “Example”.\n Rework on the workflow part All 3 tabs merged into the main tab\n changed config tab to CWL tab\n added support for the running wf as a sub tab\n Now the main tab has 5 subtabs, they are all connected.\n Better guidelines for users, step-like usage, can’t reach other steps if a previous step is not completed.\n Original snapshot management drop down page changed to running workflow session. This session will lock users to a unique page, they can’t interactive other app parts on the page(working directory changed), to prevent app crash due to wd change.\n Other changes A new UI component spsTimeline : horizontal timeline UI unit, has status, can be updated on server by updateSpsTimeline.\n A new UI bsHoverPopover: enhanced high level function of bsPlus::HoverPopover, additional JS used to make the popover work on buttons as well.\n Fixed some link problems in renderDesc. Better links in renderDesc, enlarged and spacing animation for links.\n Change on about page\n The news is now rendered on about tab in the app\n reduced developer content on about page.\n changed developer emails to github links.\n Change on visualization RNAseq part is now only in one tab as big module: users upload the targets file and a raw count table, and make different plots in subtabs.\n This introduced a lot of dependencies, will decide later if we keep as it is or separate it to spsBio. ","categories":"","description":"","excerpt":"systemPipeTools 1.0.0 is available systemPipeTools package extends the …","ref":"/news/release_3_13/","tags":"","title":"Bioconductor 3.13"},{"body":"systemPipeR 1.24 is available OVERVIEW The following enhancements have been added to systemPipeR.\n With the upgrades provided in this release, systemPipeR has become a much more generic data analysis workflow environment that is no longer limited to analyzing just NGS data. Now it can be efficiently used for data analysis tasks in many omics areas, including genomics, proteomics, metabolomics and drug discovery.\n A workflow control class (SYSargsList) has been added allowing users to manage multiple-step workflows from a single container. This way one can select and execute multiple workflow steps with standard R subsetting syntax, e.g. runWF[1:3].\n Various improvements have been added to systemPipeR’s new command-line interface including the recently introduced SYSargs2 class that supports the Common Workflow Language (CWL). Utilities have been added to visualize workflow designs and topologies with different graphical layouts.\n Improvements have been added to monitor the run status of workflows, as well as tracking of warning and error messages. This includes the generation of both scientific and technical status reports. \n ","categories":"","description":"","excerpt":"systemPipeR 1.24 is available OVERVIEW The following enhancements have …","ref":"/news/release_3_12/","tags":"","title":"Bioconductor 3.12"},{"body":" Title and logo The default for title is “systemPipeShiny” and default logo is the “img/sps_small.png” which is a relative path of the www folder in your SPS project. You can change them in SPS options. The affected places are:\n","categories":"","description":"","excerpt":" Title and logo The default for title is “systemPipeShiny” and default …","ref":"/sps/adv_features/other_customizations/","tags":"","title":"Other customizations"},{"body":" Some screenshots of SPS Full app Loading screens Workflow module Workflow Execution RNASeq module Canvas Admin Debugging ","categories":"","description":"","excerpt":" Some screenshots of SPS Full app Loading screens Workflow module …","ref":"/sps/screenshots/","tags":"","title":"Screenshots"},{"body":"This is a SPR workflow editor, which will allow you to edit the workflow plot before/after running a workflow in SPR.\n Create a SPR workflow with the sysArgsList (sal) object, or directly use the sal object after workflow running. make a workflow plot with plotWF(sal) to take a glimpse of the plot preview. Use plotWF(sal, out_format = \"dot_print\") to print out the plot in DOT language, copy the whole content to your clipboard. Use this link to open Workflow Plot Editor. Paste plot code in the editor to start editing. ","categories":"","description":"","excerpt":"This is a SPR workflow editor, which will allow you to edit the …","ref":"/sp/spr/editor/","tags":"","title":"Workflow Plot Editor"},{"body":"Hi there!\nThanks for submitting an issue to svg-pan-zoom.\nTo help us help you better, please do the following before submitting an issue:\n Review the available documentation and existing examples Check if the same bug/feature request wasn’t previously reported Make sure you are not asking a usage or debugging question. If you are, use StackOverflow. Fill in the information that corresponds to your type of issue below If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: http://jsfiddle.net/bumbu/167usffr/). Delete this intro and any unrelated text :smile: (if you do not we’ll assume you haven’t read these instructions and automatically close the issue) Bug report Expected behaviour your text here\nActual behaviour your text here\nSteps to reproduce the behaviour Configuration svg-pan-zoom version: `` Browser(s): `` Operating system(s): `` A relevant example URL: Feature Request Feature description Reasons for adopting new feature Is this a breaking change? (How will this affect existing functionality) ","categories":"","description":"","excerpt":"Hi there!\nThanks for submitting an issue to svg-pan-zoom.\nTo help us …","ref":"/sp/spr/viz_editor/bower_components/svg-pan-zoom/issue_template/","tags":"","title":""},{"body":"layout: true background-image: url(https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/app/www/img/sps_small.png) background-position: 100% 0% background-size: 10%\n","categories":"","description":"","excerpt":"layout: true background-image: …","ref":"/presentations/sps/sps_intro/","tags":"","title":"![](https://raw.githubusercontent.com/systemPipeR/systemPipeShiny/master/inst/app/www/img/sps_small.png){width=1in}\n\u003cbr/\u003e_systemPipeShiny_\n"},{"body":" layout: true background-image: url(https://raw.githubusercontent.com/tgirke/systemPipeR/gh-pages/images/systemPipeR.png) background-position: 99% 1% background-size: 10%\n class: middle\nOutline Introduction Design How to run a Workflow Workflows Tutorial Live Demo class: inverse, center, middle\n Introduction Introduction systemPipeR provides a suite of R/Bioconductor packages for designing, building and running end-to-end analysis workflows on local machines, HPC clusters and cloud systems, while generating at the same time publication quality analysis reports\n systemPipeR offers many utilities to build, control, and execute workflows entirely from R\n The environment takes advantage of central community S4 classes of the Bioconductor ecosystem\n Workflows are managed by generic workflow management containers supporting both analysis routines implemented in R code and/or command-line software\n Simple annotation system targets\n systemPipeR’s Core Functionalities .center[ ]\n Structural Features – .left-column[\nWF infrastructure ]\n.right-column[ systemPipeR offers many utilities to build, control, and execute workflows entirely from R. The environment takes advantage of central community S4 classes of the Bioconductor ecosystem. Workflows are managed by generic workflow management containers supporting both analysis routines implemented in R code and/or command-line software. A layered monitoring infrastructure is provided to design, control and debug each step in a workflow. The run environment allows to execute workflows entirely or with a intuitive to use step-wise execution syntax using R’s standard subsetting syntax (runWF(sys[1:3])) or pipes (%\u003e%). ]\n Structural Features .left-column[\nWF infrastructure Command-line support ]\n.right-column[ An important feature of systemPipeR is support for running command-line software by adopting the Common Workflow Language (CWL). The latter is a widely adopted community standard for describing analysis workflows. This design offers several advantages such as:\n seamless integration of most command-line software\n support to run systemPipeR workflows from R or many other popular computer languages\n efficient sharing of workflows across different workflow environments. ]\n Structural Features .left-column[\nWF infrastructure Command-line support Parallel evaluation ]\n.right-column[ The processing time of workflows can be greatly reduced by making use of parallel evaluations across several CPU cores on single machines, or multiple nodes of computer clusters and cloud-based systems. systemPipeR simplifies these parallelization tasks without creating any limitations for users who do not have access to high-performance computer resources ]\n Structural Features .left-column[\nWF infrastructure Command-line support Parallel evaluation Reports infrastructure ]\n.right-column[ systemPipeR’s reporting infrastructure includes three types of interconnected reports each serving a different purpose:\n a scientific report, based on R Markdown, contains all scientifically relevant results\n a technical report captures all technical information important for each workflow step, including parameter settings, software versions, and warning/error messages, etc.\n a visual report depicts the entire workflow topology including its run status in form of a workflow graph\n]\n Structural Features .left-column[\nWF infrastructure Command-line support Parallel evaluation Reports infrastructure Shiny Web Interface ]\n.right-column[ Recently, the systemPipeShiny package has been added that allows users to design workflows in an interactive graphical user interface (GUI). In addition to designing workflows, this new interface allows users to run and to monitor workflows in an intuitive manner without the need of knowing R. ]\n Structural Features .left-column[\nWF infrastructure Command-line support Parallel evaluation Reports infrastructure Shiny Web Interface Workflow Templates ]\n.right-column[ A rich set of end-to-end workflow templates is provided by this project for a wide range omics applications. In addition, users can contribute and share their workflows with the community by submitting them to a central GitHub repository ]\n Important Functions .small[\n Function Name Description Category genWorkenvir Generates workflow templates provided by systemPipeRdata helper package / or from the individuals’ pipelines packages Accessory loadWorkflow Constructs SYSargs2 object from CWL param and targets files SYSargs2 renderWF Populate all the command-line in an SYSargs2 object SYSargs2 subsetWF Subsetting SYSargs2 class slots SYSargs2 runCommandline Executes command-line software on samples and parameters specified in SYSargs2 object SYSargs2 clusterRun Runs command-line software in parallel mode on a computer cluster SYSargs2 writeTargetsout Write updated targets out to file/Generate targets file with reference SYSargs2 output_update Updates the output files paths in the SYSargs2 object SYSargs2 singleYML Create automatically the param.yml SYSargs2 createWF Create automatically param.cwl and the param.yml based on the command line SYSargs2 config.param Custom configuration of the CWL param files from R SYSargs2 ] Important Functions .small[\n Function Name Description Category initWF Constructs SYSargsList workflow control module (S4 object) from script file SYSargsList configWF Control of which step of the workflow will be run and the generation of the new RMarkdown SYSargsList runWF Runs all the R chunk define in the RMarkdown file or a subset, e.g. runWF[1:3] SYSargsList renderReport Render Scientific Report based on RMarkdown SYSargsList subsetRmd Write updated subset Rmarkdown of R chunk with text associate in the step selected SYSargsList plotWF Plot visual workflow designs and topologies with different graphical layouts SYSargsList statusWF Return the overview of the workflow steps computational status SYSargsList evalCode Turn eval option TRUE or FALSE on RMarkdown file Accessory tryCL Checks if third-party software or utility is installed and set in the PATH Accessory ] class: inverse, center, middle\n Design Workflow Management Solutions systemPipeR central concept for designing workflows is workflow management containers (S4 class)\n SYSargs2 controls workflow steps with input/output file operations\n SYSargs2 requires a targets and a set of workflow definition files (here param.cwl and param.yml)\n -- SYSargsList objects organize one or many SYSargs2 containers in a single compound object capturing all information required to run, control and monitor complex workflows from start to finish\n.center[ ]\n Directory Structure The workflow templates generated by genWorkenvir contain the following preconfigured directory structure:\n Workflows Collection Browse pipelines that are currently available as part of the systemPipeR toolkit\n.small[\n WorkFlow Description Version GitHub CI Testing systemPipeChIPseq ChIP-Seq Workflow Template v1.0 systemPipeRIBOseq RIBO-Seq Workflow Template v1.0 systemPipeRNAseq RNA-Seq Workflow Template v1.0 systemPipeVARseq VAR-Seq Workflow Template v1.0 systemPipeMethylseq Methyl-Seq Workflow Template devel systemPipeDeNovo De novo transcriptome assembly Workflow Template devel systemPipeCLIPseq CLIP-Seq Workflow Template devel systemPipeMetaTrans Metatranscriptomic Sequencing Workflow Template devel ] class: inverse, center, middle\nCWL CWL TODO: Add section with CWL details\n.center[ ]\n CWL and SPR TODO: How to use CWL definition with systemPipeR\n SYSargs2 instances are constructed from a targets file and two param file hisat2-mapping-se.cwl file contains the settings for running command-line software hisat2-mapping-se.yml file define all the variables to be input in the specific command-line step targets \u003c- system.file(\"extdata\", \"targets.txt\", package=\"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/hisat2/hisat2-se\", package=\"systemPipeR\") align \u003c- loadWF(targets=targets, wf_file=\"hisat2-mapping-se.cwl\", input_file=\"hisat2-mapping-se.yml\", dir_path=dir_path) align \u003c- renderWF(align, inputvars=c(FileName=\"_FASTQ_PATH_\", SampleName=\"_SampleName_\")) ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 18 (M1A...V12B), targetsheader: 4 (lines) ## modules: 2 ## wf: 0, clt: 1, yamlinput: 7 (components) ## input: 18, output: 18 ## cmdlist: 18 ## WF Steps: ## 1. hisat2-mapping-se.cwl (rendered: TRUE) CWL and SPR SYSargs2 instance Slots and accessor functions have the same names names(align) # [1] \"targets\" \"targetsheader\" \"modules\" \"wf\" \"clt\" # [6] \"yamlinput\" \"cmdlist\" \"input\" \"output\" \"cwlfiles\" # [11] \"inputvars\" cmdlist return command-line arguments for the specific software, here HISAT2 for the first sample cmdlist(align)[1] # $M1A # $M1A$`hisat2-mapping-se.cwl` # [1] \"hisat2 -S results/M1A.sam -x ./data/tair10.fasta -k 1 --min-intronlen 30 --max-intronlen 3000 -U ./data/SRR446027_1.fastq.gz --threads 4\" The output components of SYSargs2 define all the expected output files for each step in the workflow; some of which are the input for the next workflow step output(align)[1] # $M1A # $M1A$`hisat2-mapping-se.cwl` # [1] \"results/M1A.sam\" class: inverse, center, middle\n Metadata Targets file organizes samples Structure of targets file for single-end (SE) library targetspath \u003c- system.file(\"extdata\", \"targets.txt\", package=\"systemPipeR\") read.delim(targetspath, comment.char = \"#\")[1:3,1:4] ## FileName SampleName Factor SampleLong ## 1 ./data/SRR446027_1.fastq.gz M1A M1 Mock.1h.A ## 2 ./data/SRR446028_1.fastq.gz M1B M1 Mock.1h.B ## 3 ./data/SRR446029_1.fastq.gz A1A A1 Avr.1h.A Structure of targets file for paired-end (PE) library targetspath \u003c- system.file(\"extdata\", \"targetsPE.txt\", package=\"systemPipeR\") read.delim(targetspath, comment.char = \"#\")[1:3,1:5] ## FileName1 FileName2 SampleName Factor ## 1 ./data/SRR446027_1.fastq.gz ./data/SRR446027_2.fastq.gz M1A M1 ## 2 ./data/SRR446028_1.fastq.gz ./data/SRR446028_2.fastq.gz M1B M1 ## 3 ./data/SRR446029_1.fastq.gz ./data/SRR446029_2.fastq.gz A1A A1 ## SampleLong ## 1 Mock.1h.A ## 2 Mock.1h.B ## 3 Avr.1h.A Integration with SummarizedExperiment Integrates targets files and count table from systemPipeR to a SummarizedExperiment object ## Create an object with targets file and comparison and count table sprSE \u003c- SPRdata(targetspath = targetspath, cmp=TRUE) metadata(sprSE) # $version # [1] ‘1.23.9’ # # $comparison # $comparison$CMPset1 # [,1] [,2] # [1,] \"M1\" \"A1\" # [2,] \"M1\" \"V1\" # [3,] \"A1\" \"V1\" # [4,] \"M6\" \"A6\" colData(sprSE) # DataFrame with 18 rows and 6 columns # FileName SampleName Factor SampleLong # \u003ccharacter\u003e \u003ccharacter\u003e \u003ccharacter\u003e \u003ccharacter\u003e # M1A ./data/SRR446027_1.f.. M1A M1 Mock.1h.A # M1B ./data/SRR446028_1.f.. M1B M1 Mock.1h.B # ... ... ... ... ... # M12B ./data/SRR446040_1.f.. M12B M12 Mock.12h.B class: inverse, center, middle\n Live Demo Install Package Install the systemPipeRdata package from Bioconductor:\nif (!requireNamespace(\"BiocManager\", quietly=TRUE)) install.packages(\"BiocManager\") BiocManager::install(\"systemPipeR\") Load Package and Documentation Load package:\nlibrary(\"systemPipeR\") Access help:\nlibrary(help=\"systemPipeR\") vignette(\"systemPipeR\") Quick Start Load Sample Workflow systemPipeRdata\n Helper package to generate with a single command workflow templates for systemPipeR Includes sample data for testing User can create new workflows or change and extend existing ones Template Workflows: Sample workflows can be loaded with the genWorkenvir function from systemPipeRdata Generate workflow template:\nlibrary(systemPipeRdata) genWorkenvir(workflow=\"rnaseq\") setwd(\"rnaseq\") More details about systemPipeRdata package here\n Install Workflow Check the workflow template availability\navailableWF(github = TRUE) # $systemPipeRdata # [1] \"chipseq\" \"new\" \"riboseq\" \"rnaseq\" \"varseq\" # # $github # workflow branches version html description # 1 systemPipeR/systemPipeChIPseq master release https://github.com/systemPipeR/systemPipeChIPseq Workflow Template # 2 systemPipeR/systemPipeRIBOseq master release https://github.com/systemPipeR/systemPipeRIBOseq Workflow Template # 3 systemPipeR/systemPipeRNAseq cluster, master, singleMachine release https://github.com/systemPipeR/systemPipeRNAseq Workflow Template # 4 systemPipeR/systemPipeVARseq master release https://github.com/systemPipeR/systemPipeVARseq Workflow Template # 5 systemPipeR/systemPipeCLIPseq master devel https://github.com/systemPipeR/systemPipeCLIPseq Workflow Template # 6 systemPipeR/systemPipeDeNovo master devel https://github.com/systemPipeR/systemPipeDeNovo Workflow Template # 7 systemPipeR/systemPipeMetaTrans master devel https://github.com/systemPipeR/systemPipeMetaTrans Workflow Template # 8 systemPipeR/systemPipeMethylseq master devel https://github.com/systemPipeR/systemPipeMethylseq Workflow Template Dynamic Workflow Template Create dynamic Workflow Templates with RStudio\n File -\u003e New File -\u003e R Markdown -\u003e From Template .center[ ]\n Run a Workflow .left-column[\nSetup ]\n.right-column[\nlibrary(systemPipeR) targetspath \u003c- system.file(\"extdata\", \"targets.txt\", package=\"systemPipeR\") read.delim(targetspath, comment.char = \"#\")[1:4,1:4] ## FileName SampleName Factor SampleLong ## 1 ./data/SRR446027_1.fastq.gz M1A M1 Mock.1h.A ## 2 ./data/SRR446028_1.fastq.gz M1B M1 Mock.1h.B ## 3 ./data/SRR446029_1.fastq.gz A1A A1 Avr.1h.A ## 4 ./data/SRR446030_1.fastq.gz A1B A1 Avr.1h.B script \u003c- system.file(\"extdata/workflows/rnaseq\", \"systemPipeRNAseq.Rmd\", package=\"systemPipeRdata\") ]\n Run a Workflow .left-column[\nSetup initWF ]\n.right-column[\nsysargslist \u003c- initWF(script = script, targets = targetspath, overwrite = TRUE) # Project started with success: ./SYSproject and SYSconfig.yml were created. ]\n Run a Workflow .left-column[\nSetup initWF configWF ]\n.right-column[\nsysargslist \u003c- configWF(sysargslist, input_steps = \"1:3\") sysargslist # Instance of 'SYSargsList': # WF Steps: # 1. Rmarkdown/HTML setting # 2. Introduction # 3. Samples and environment settings # 3.1. Environment settings and input data # 3.2. Required packages and resources # 3.3. Experiment definition provided by `targets` file ]\n Run a Workflow .left-column[\nSetup initWF configWF runWF ]\n.right-column[\nsysargslist \u003c- runWF(sysargslist, steps = \"1:2\") # Step: 1: Introduction --\u003e DONE # Step: 2: Samples and environment settings --\u003e DONE # Step: 2.1: Environment settings and input data --\u003e DONE # Step: 2.2: Required packages and resources --\u003e DONE # Step: 2.3: Experiment definition provided by `targets` file --\u003e DONE sysargslist \u003c- runWF(sysargslist, steps = \"ALL\") ]\n Run a Workflow .left-column[\nSetup initWF configWF runWF renderReport ]\n.right-column[\nsysargslist \u003c- renderReport(sysargslist = sysargslist) ]\n How to Use Pipes %\u003e% Consider the following example, in which the steps are the initialization, configuration and running the entire workflow.\nlibrary(systemPipeR) sysargslist \u003c- initWF(script =\"systemPipeRNAseq.Rmd\", overwrite = TRUE) %\u003e% configWF(input_steps = \"1:6\") %\u003e% runWF(steps = \"1:2\") class: inverse, center, middle\n Project Updates targets x SummarizedExperiment Extension “SummarizedExperiment” methods:\nsprSE \u003c- addAssay(sprSE, assay(countMatrix), xName=\"countMatrix\") sprSE \u003c- addMetadata(sprSE, list(targets), xName=\"metadata\") New Function:\n## Create empty SummarizedExperiment sprSE \u003c- SPRdata() ## Create an object with targets file and comparison and count table sprSE \u003c- SPRdata(counts = countMatrix, cmp=TRUE, targetspath = targetspath) metadata(sprSE) colData(sprSE) assays(sprSE) SPR Paper Link to draft\n Added the main points to discuss in the draft\n Writing: Results and introduction\n Improve Graphical Abstract\n Show case?\n SYSargsList Explain how SYSargsList is implemented - Vignette\n.small[\n Function Name Description initWF Constructs SYSargsList workflow control module (S4 object) from script file configWF Control of which step of the workflow will be run and the generation of the new RMarkdown runWF Runs all the R chunk define in the RMarkdown file or a subset, e.g. runWF[1:3] renderReport Render Scientific Report based on RMarkdown renderLog Render logs Report based on RMarkdown updateWF Recover the SYSargsList workflow previous ran and restarts the WF plotWF Plot visual workflow designs and topologies with different graphical layouts statusWF Return the overview of the workflow steps computational status evalCode Turn eval option TRUE or FALSE on RMarkdown file tryCL Checks if third-party software or utility is installed and set in the PATH ] Improve statusWF()\n Visualization in systemPipeR Add to vignette (SPR or SPS)\n exploreDDS, exploreDDSplot, GLMplot, MAplot, MDSplot, PCAplot, hclustplot, heatMaplot, tSNEplot, volcanoplot Enrichment analysis and visualization tool for SPR\n Integration with FGSEA WebSite Updated the vignette\n Added systemPipeRdata vignette and presentation: link\n Redirect http://girke.bioinformatics.ucr.edu/systemPipeR/ to new page\n Add content to FAQ section\n Add tutorials videos\n class: middle\nThanks! Browse source code at \n Ask a question about systemPipeR at Bioconductor Support Page \n systemPipeRdata at Bioconductor\n https://systempipe.org/\n","categories":"","description":"","excerpt":" layout: true background-image: …","ref":"/presentations/spr/spr_project/","tags":"","title":"_systemPipeR_"},{"body":"systemPipeR (SPR) workflow environment containers multiple packages. Browse your interested chapters from below.\nChapters ","categories":"","description":"","excerpt":"systemPipeR (SPR) workflow environment containers multiple packages. …","ref":"/sp/","tags":"","title":"systemPipeR Documentation"},{"body":"Starting with pre-configured workflow templates To test workflows quickly or design new ones from existing templates, users can generate with a single command workflow instances fully populated with sample data and parameter files required for running a chosen workflow.\nLoad one of the available workflows into your current working directory. The following does this for the varseq workflow template. The name of the resulting workflow directory can be specified under the mydirname argument. The default NULL uses the name of the chosen workflow. An error is issued if a directory of the same name and path exists already.\nlibrary(\"systemPipeRdata\") genWorkenvir(workflow=\"systemPipeR/SPvarseq\", mydirname=NULL) setwd(\"varseq\") On Linux and OS X systems the same can be achieved from the command-line of a terminal with the following commands.\n$ Rscript -e \"systemPipeRdata::genWorkenvir(workflow='systemPipeR/SPvarseq', mydirname=NULL)\" Check availability of workflow templates A collection of workflow templates are available, and it is possible to browse the current availability, as follows:\navailableWF(github = TRUE) ## $systemPipeRdata ## [1] \"chipseq\" \"new\" \"riboseq\" \"rnaseq\" \"varseq\" ## ## $github ## workflow branches version ## 1 systemPipeR/SPchipseq master release ## 2 systemPipeR/SPriboseq master release ## 3 systemPipeR/SPrnaseq cluster, master, singleMachine release ## 4 systemPipeR/SPvarseq master release ## 5 systemPipeR/SPclipseq master devel ## 6 systemPipeR/SPdenovo master devel ## 7 systemPipeR/SPmetatrans master devel ## 8 systemPipeR/SPmethylseq master devel ## 9 systemPipeR/SPmirnaseq master devel ## html description ## 1 https://github.com/systemPipeR/SPchipseq Workflow Template ## 2 https://github.com/systemPipeR/SPriboseq Workflow Template ## 3 https://github.com/systemPipeR/SPrnaseq Workflow Template ## 4 https://github.com/systemPipeR/SPvarseq Workflow Template ## 5 https://github.com/systemPipeR/SPclipseq Workflow Template ## 6 https://github.com/systemPipeR/SPdenovo Workflow Template ## 7 https://github.com/systemPipeR/SPmetatrans Workflow Template ## 8 https://github.com/systemPipeR/SPmethylseq Workflow Template ## 9 https://github.com/systemPipeR/SPmirnaseq Workflow Template This function returns the list of workflow templates available within the package and systemPipeR Project Organization on GitHub. Each one listed template can be created as described above.\nThe workflow template choose from Github will be installed as an R package, and also it creates an environment with all the settings and files to run the demo analysis.\ngenWorkenvir(workflow=\"systemPipeR/SPrnaseq\", mydirname=\"NULL\") setwd(\"systemPipeVARseq\") Besides, it is possible to choose different versions of the workflow template, defined through other branches on the GitHub Repository. By default, the master branch is selected, however, it is possible to define a different branch with the ref argument.\ngenWorkenvir(workflow=\"systemPipeR/SPrnaseq\", ref = \"singleMachine\") setwd(\"systemPipeRNAseq\") ","categories":"","description":"","excerpt":"Starting with pre-configured workflow templates To test workflows …","ref":"/spr_wf/installwf/","tags":"","title":"How to install systemPipe Workflows"},{"body":" Stay tuned for all sytemPipe project news!\n ","categories":"","description":"","excerpt":" Stay tuned for all sytemPipe project news!\n ","ref":"/news/","tags":"","title":"News"},{"body":"","categories":"","description":"","excerpt":"","ref":"/presentations/","tags":"","title":"Presentations"},{"body":"How to create a new Workflow Template SPRthis package expand usethis package, providing automation to create systemPipeR workflows templates.\nInstallation To install SPRthis using from BiocManager the following code:\nif (!requireNamespace(\"BiocManager\", quietly = TRUE)) { install.packages(\"BiocManager\") BiocManager::install(\"dcassol/SPRthis\") Quick start to using to SPRthis ## Load the package library(SPRthis) ## create Package sprthis(wfName=\"SPRtest\", analysis=\"SPRtest\", path=tempdir()) ## ✓ Setting active project to '/tmp/RtmpWTh4tB' ## ✓ Creating 'R/' ## ✓ Writing 'DESCRIPTION' ## Package: SPRtest ## Title: SPRtest ## Version: 0.9.0 ## Authors@R (parsed): ## * First Last \u003cfirst.last@example.com\u003e [aut, cre] (YOUR-ORCID-ID) ## Description: This package provides a pre-configured workflow and reporting ## template for SPRtest. ## License: Artistic-2.0 ## URL: https://github.com/systemPipeR/SPRtest ## Imports: ## systemPipeR (\u003e= 1.25.0) ## Suggests: ## BiocStyle, ## knitr, ## rmarkdown ## VignetteBuilder: ## knitr ## biocViews: Infrastructure, ... ## Encoding: UTF-8 ## LazyData: true ## Roxygen: list(markdown = TRUE) ## RoxygenNote: 7.1.1 ## SystemRequirements: SPRtest can be used to run external command-line ## software, but the corresponding tool needs to be installed on a ## system. ## ✓ Writing 'NAMESPACE' ## ✓ Setting active project to '\u003cno active project\u003e' ## [1] \"/tmp/RtmpWTh4tB\" SPRtest/ ├── DESCRIPTION ├── NAMESPACE ├── README.md ├── SPRtest.Rproj ├── .gitignore ├── .Rbuildignore ├── .Rproj.user/ ├── R/ │ ├── functions.R ├── vignettes │ ├── bibtex.bib │ ├── SPRtest.Rmd └── inst ├── rmarkdown │ └── templates │ └── SPRtest │ ├── template.yml │ └── skeleton │ ├── batchtools.slurm.tmpl │ ├── .batchtools.conf.R │ ├── bibtex.bib │ ├── NEWS │ ├── SPRconfig.yml │ ├── skeleton.Rmd │ ├── targetsPE.txt │ ├── data/ │ ├── param/ │ └── results/ Help functions to create the package Create the webiste for the package with pkgdown Edit the _pkgdown.yml file and run:\npkgdown::build_site() Documentation with roxygen2 roxygen2::roxygenise() Testing the code with testthat To test the code, you can run\ndevtools::test() Package available to genWorkenvir Function After creating the new repository on GitHub systemPipeR Organization, please follow:\n Rules: The Workflow Template need to be available under systemPipeR Organization; The repository needs to be public; About setting: Description: keywords in the description are required: “Workflow Template”; Topics: we expected “systempiper” and “release” or “development” words on Topics section; Branch name: To make simple, please name the branch as “master”. Check availability of workflow templates A collection of workflow templates are available, and it is possible to browse the current availability, as follows:\nsystemPipeRdata::availableWF(github = TRUE) ## $systemPipeRdata ## [1] \"chipseq\" \"new\" \"riboseq\" \"rnaseq\" \"varseq\" ## ## $github ## workflow branches version ## 1 systemPipeR/SPchipseq master release ## 2 systemPipeR/SPriboseq master release ## 3 systemPipeR/SPrnaseq cluster, master, singleMachine release ## 4 systemPipeR/SPvarseq master release ## 5 systemPipeR/SPclipseq master devel ## 6 systemPipeR/SPdenovo master devel ## 7 systemPipeR/SPmetatrans master devel ## 8 systemPipeR/SPmethylseq master devel ## 9 systemPipeR/SPmirnaseq master devel ## html description ## 1 https://github.com/systemPipeR/SPchipseq Workflow Template ## 2 https://github.com/systemPipeR/SPriboseq Workflow Template ## 3 https://github.com/systemPipeR/SPrnaseq Workflow Template ## 4 https://github.com/systemPipeR/SPvarseq Workflow Template ## 5 https://github.com/systemPipeR/SPclipseq Workflow Template ## 6 https://github.com/systemPipeR/SPdenovo Workflow Template ## 7 https://github.com/systemPipeR/SPmetatrans Workflow Template ## 8 https://github.com/systemPipeR/SPmethylseq Workflow Template ## 9 https://github.com/systemPipeR/SPmirnaseq Workflow Template This function returns the list of workflow templates available within the package and systemPipeR Project Organization on GitHub. Each one listed template can be created as described above.\n","categories":"","description":"","excerpt":"How to create a new Workflow Template SPRthis package expand usethis …","ref":"/spr_wf/newwf/","tags":"","title":"Rules to create a new Workflow Template"},{"body":"","categories":"","description":"","excerpt":"","ref":"/search/","tags":"","title":"Search Results"},{"body":"Workflow Templates systemPipeR project provides pre-configured workflows and reporting templates for a wide range of NGS applications that are listed bellow. The systemPipeR project provides a suite of R/Bioconductor packages for designing, building and running end-to-end analysis workflows on local machines, HPC clusters and cloud systems, while generating at the same time publication quality analysis reports.\nsystemPipeRdata is a helper package to generate with a single command workflow templates that are intended to be used by its parent package systemPipeR (H Backman and Girke 2016).\n WorkFlow Description Version GitHub R-CMD-check SPchipseq ChIP-Seq Workflow Template SPriboseq RIBO-Seq Workflow Template SPrnaseq RNA-Seq Workflow Template SPvarseq VAR-Seq Workflow Template SPmethylseq Methyl-Seq Workflow Template SPdenovo De novo transcriptome assembly Workflow Template SPclipseq CLIP-Seq Workflow Template SPmetatrans Metatranscriptomic Sequencing Workflow Template SPatacseq ATAC-Seq Workflow Template SPpolyriboseq Polyribosomal RNA-Seq Workflow Template SPhic Hi-C Workflow Template SPmirnaseq MicroRNA-Seq Workflow Template SPblast BLAST Workflow Template SPscrnaseq Single-Cell RNA-Seq Workflow Template Reference H Backman, Tyler W, and Thomas Girke. 2016. “systemPipeR: NGS workflow and report generation environment.” BMC Bioinformatics 17 (1): 388. https://doi.org/10.1186/s12859-016-1241-0.\n ","categories":"","description":"","excerpt":"Workflow Templates systemPipeR project provides pre-configured …","ref":"/spr_wf/","tags":"","title":"SPR WorkFlow Collection"},{"body":" #td-cover-block-0 { background-image: url(\"background.jpg\") } systemPipe Workflow Environment loadLogo(\"images/sp_org_links.svg\") Learn More Bioconductor 3.15 New Features A workflow design, report generation, and visualization framework for data analysis\n systemPipe Project\nThe systemPipe project provides a suite of R/Bioconductor packages for designing, building and running end-to-end analysis workflows on local machines, HPC clusters and cloud systems, while generating at the same time publication quality analysis reports.\n Bioconductor Download a stable release from Bioconductor of\nsystemPipeR , systemPipeShiny , systemPipeTools , systemPipeRdata.\n Contributions welcome! Get the lastest version, submit issues and pull requests. Read more here.\n systemPipeShiny Demo Try an interactive demo and tutorial.\n ","categories":"","description":"","excerpt":" #td-cover-block-0 { background-image: url(\"background.jpg\") } …","ref":"/","tags":"","title":"systemPipe"},{"body":" loadLogo(\"/images/sps_logos.svg\") #svg-logo { background: radial-gradient(circle, transparent 0%, rgba(255,255,255,1) 30%), linear-gradient(to right, var(--color), var(--color)), var(--image2); background-repeat: no-repeat; background-size: auto 1200px; background-position: center center; background-blend-mode: var(--blend-top, normal), var(--blend-bottom, saturation), normal; --image2: url(\"/background.jpg\"); --color-v: rgba(76,169,237,1); --color: rgba(76,169,237,1); } #svg-logo svg { margin: 0 auto; display: block; padding: 50px; } systemPipeShiny (SPS) extends the widely used systemPipeR (SPR) workflow environment with a versatile graphical user interface provided by a Shiny App. This allows non-R users, such as experimentalists, to run many systemPipeR’s workflow designs, control, and visualization functionalities interactively without requiring knowledge of R. Most importantly, SPS has been designed as a general purpose framework for interacting with other R packages in an intuitive manner. Like most Shiny Apps, SPS can be used on both local computers as well as centralized server-based deployments that can be accessed remotely as a public web service for using SPR’s functionalities with community and/or private data. The framework can integrate many core packages from the R/Bioconductor ecosystem. Examples of SPS' current functionalities include:\n A default interactive workflow module to create experimental designs, visualize and customize workflow topologies with previews, and programming free workflow execution within the application. An interactive module with extensive plot options to visualize downstream analysis of a RNA-Seq workflow. A quick ggplot module to make all variety of scientific plots from any user defined tabular data. An extendable set of visualization functionalities makes it easy to design custom Shiny Apps under SPS framework without any knowledge of Shiny. A ‘Canvas Workbench’ to manage complex visual results. It allows users to organize and to compare plots in an efficient manner combined with a session screenshot feature to edit scientific and publishable figures. Three other supporting packages to help all users from beginners and advanced developers to extend under current SPS framework or on their own visualization apps. Demos Shinyapps.io demos View our online demo app:\n Type and link option changed notes Default full installation{blk} See installation full app Minimum installation{blk} See installation no modules installed Login enabled{blk} login_screen = TRUE; login_theme = \"empty\" no modules installed Login and login themes{blk} login_screen = TRUE; login_theme = \"random\" no modules installed App admin page{blk} admin_page = TRUE or simply add “?admin” to the end of URL of demos For the login required demos, the app account name is “user” password “user”.\nFor the admin panel login, account name “admin”, password “admin”.\nPlease DO NOT delete or change password when you are using the admin features. shinyapp.io will reset the app once a while, but this will affect other people who are trying the demo simultaneously.\nRstudio Cloud demo There is an Rstudio Cloud project instance that you can also play with. You need to create a free new account. Two Bioconductor related modules - workflow \u0026 RNAseq are not installed. They require more than 1GB RAM to install and to run which is beyond the limit of a free account.\nDocker Use systempipe_docker for instructions.\nOther packages in systemPipeShiny Package Description Documents Function reference Demo systemPipeShiny{blk} SPS main package website link demo{blk} spsComps{blk} SPS UI and server components website link demo{blk} drawer{blk} SPS interactive image editing tool website link demo{blk} spsUtil{blk} SPS utility functions website link NA ","categories":"","description":"","excerpt":" loadLogo(\"/images/sps_logos.svg\") #svg-logo { background: …","ref":"/sps/","tags":"","title":"systemPipeShiny Documentation"},{"body":"document.addEventListener(\"DOMContentLoaded\", function() { document.querySelector(\"h1\").className = \"title\"; }); document.addEventListener(\"DOMContentLoaded\", function() { var links = document.links; for (var i = 0, linksLength = links.length; i Define environment settings and samples A typical workflow starts with generating the expected working environment containing the proper directory structure, input files, and parameter settings. To simplify this task, one can load one of the existing NGS workflows templates provided by systemPipeRdata into the current working directory. The following does this for the rnaseq template. The name of the resulting workflow directory can be specified under the mydirname argument. The default NULL uses the name of the chosen workflow. An error is issued if a directory of the same name and path exists already. On Linux and OS X systems one can also create new workflow instances from the command-line of a terminal as shown here. To apply workflows to custom data, the user needs to modify the targets file and if necessary update the corresponding .cwl and .yml files. A collection of pre-generated .cwl and .yml files are provided in the param/cwl subdirectory of each workflow template. They are also viewable in the GitHub repository of systemPipeRdata (see here).\nlibrary(systemPipeR) library(systemPipeRdata) genWorkenvir(workflow = \"rnaseq\", mydirname = NULL) setwd(\"rnaseq\") Read Preprocessing Preprocessing with preprocessReads function The function preprocessReads allows to apply predefined or custom read preprocessing functions to all FASTQ files referenced in a SYSargs2 container, such as quality filtering or adaptor trimming routines. The paths to the resulting output FASTQ files are stored in the output slot of the SYSargs2 object. Internally, preprocessReads uses the FastqStreamer function from the ShortRead package to stream through large FASTQ files in a memory-efficient manner. The following example performs adaptor trimming with the trimLRPatterns function from the Biostrings package. After the trimming step a new targets file is generated (here targets_trimPE.txt) containing the paths to the trimmed FASTQ files. The new targets file can be used for the next workflow step with an updated SYSargs2 instance, e.g. running the NGS alignments with the trimmed FASTQ files.\nConstruct SYSargs2 object from cwl and yml param and targets files.\ntargetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/preprocessReads/trim-pe\", package = \"systemPipeR\") trim \u003c- loadWorkflow(targets = targetsPE, wf_file = \"trim-pe.cwl\", input_file = \"trim-pe.yml\", dir_path = dir_path) trim \u003c- renderWF(trim, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) trim output(trim)[1:2] preprocessReads(args = trim, Fct = \"trimLRPatterns(Rpattern='GCCCGGGTAA', subject=fq)\", batchsize = 1e+05, overwrite = TRUE, compress = TRUE) The following example shows how one can design a custom read preprocessing function using utilities provided by the ShortRead package, and then run it in batch mode with the ‘preprocessReads’ function (here on paired-end reads).\nfilterFct \u003c- function(fq, cutoff = 20, Nexceptions = 0) { qcount \u003c- rowSums(as(quality(fq), \"matrix\") \u003c= cutoff, na.rm = TRUE) # Retains reads where Phred scores are \u003e= cutoff with N exceptions fq[qcount \u003c= Nexceptions] } preprocessReads(args = trim, Fct = \"filterFct(fq, cutoff=20, Nexceptions=0)\", batchsize = 1e+05) Preprocessing with TrimGalore! TrimGalore! is a wrapper tool to consistently apply quality and adapter trimming to fastq files, with some extra functionality for removing Reduced Representation Bisulfite-Seq (RRBS) libraries.\ntargets \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/trim_galore/trim_galore-se\", package = \"systemPipeR\") trimG \u003c- loadWorkflow(targets = targets, wf_file = \"trim_galore-se.cwl\", input_file = \"trim_galore-se.yml\", dir_path = dir_path) trimG \u003c- renderWF(trimG, inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\")) trimG cmdlist(trimG)[1:2] output(trimG)[1:2] ## Run Single Machine Option trimG \u003c- runCommandline(trimG[1], make_bam = FALSE) Preprocessing with Trimmomatic targetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/trimmomatic/trimmomatic-pe\", package = \"systemPipeR\") trimM \u003c- loadWorkflow(targets = targetsPE, wf_file = \"trimmomatic-pe.cwl\", input_file = \"trimmomatic-pe.yml\", dir_path = dir_path) trimM \u003c- renderWF(trimM, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) trimM cmdlist(trimM)[1:2] output(trimM)[1:2] ## Run Single Machine Option trimM \u003c- runCommandline(trimM[1], make_bam = FALSE) FASTQ quality report The following seeFastq and seeFastqPlot functions generate and plot a series of useful quality statistics for a set of FASTQ files including per cycle quality box plots, base proportions, base-level quality trends, relative k-mer diversity, length and occurrence distribution of reads, number of reads above quality cutoffs and mean quality distribution.\nThe function seeFastq computes the quality statistics and stores the results in a relatively small list object that can be saved to disk with save() and reloaded with load() for later plotting. The argument klength specifies the k-mer length and batchsize the number of reads to a random sample from each FASTQ file.\nfqlist \u003c- seeFastq(fastq = infile1(trim), batchsize = 10000, klength = 8) pdf(\"./results/fastqReport.pdf\", height = 18, width = 4 * length(fqlist)) seeFastqPlot(fqlist) dev.off() Figure 1: FASTQ quality report\n Parallelization of FASTQ quality report on a single machine with multiple cores.\nf \u003c- function(x) seeFastq(fastq = infile1(trim)[x], batchsize = 1e+05, klength = 8) fqlist \u003c- bplapply(seq(along = trim), f, BPPARAM = MulticoreParam(workers = 4)) seeFastqPlot(unlist(fqlist, recursive = FALSE)) Parallelization of FASTQ quality report via scheduler (e.g. Slurm) across several compute nodes.\nlibrary(BiocParallel) library(batchtools) f \u003c- function(x) { library(systemPipeR) targetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/preprocessReads/trim-pe\", package = \"systemPipeR\") trim \u003c- loadWorkflow(targets = targetsPE, wf_file = \"trim-pe.cwl\", input_file = \"trim-pe.yml\", dir_path = dir_path) trim \u003c- renderWF(trim, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) seeFastq(fastq = infile1(trim)[x], batchsize = 1e+05, klength = 8) } resources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) param \u003c- BatchtoolsParam(workers = 4, cluster = \"slurm\", template = \"batchtools.slurm.tmpl\", resources = resources) fqlist \u003c- bplapply(seq(along = trim), f, BPPARAM = param) seeFastqPlot(unlist(fqlist, recursive = FALSE)) NGS Alignment software After quality control, the sequence reads can be aligned to a reference genome or transcriptome database. The following sessions present some NGS sequence alignment software. Select the most accurate aligner and determining the optimal parameter for your custom data set project.\nFor all the following examples, it is necessary to install the respective software and export the PATH accordingly. If it is available Environment Module in the system, you can load all the request software with moduleload(args) function.\nAlignment with HISAT2 using SYSargs2 The following steps will demonstrate how to use the short read aligner Hisat2 (Kim, Langmead, and Salzberg 2015) in both interactive job submissions and batch submissions to queuing systems of clusters using the systemPipeR's new CWL command-line interface.\nThe parameter settings of the aligner are defined in the hisat2-mapping-se.cwl and hisat2-mapping-se.yml files. The following shows how to construct the corresponding SYSargs2 object, here args.\ntargets \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/hisat2/hisat2-se\", package = \"systemPipeR\") args \u003c- loadWorkflow(targets = targets, wf_file = \"hisat2-mapping-se.cwl\", input_file = \"hisat2-mapping-se.yml\", dir_path = dir_path) args \u003c- renderWF(args, inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\")) args ## Instance of 'SYSargs2': ## Slot names/accessors: ## targets: 18 (M1A...V12B), targetsheader: 4 (lines) ## modules: 1 ## wf: 0, clt: 1, yamlinput: 7 (inputs) ## input: 18, output: 18 ## cmdlist: 18 ## Sub Steps: ## 1. hisat2-mapping-se (rendered: TRUE) cmdlist(args)[1:2] ## $M1A ## $M1A$`hisat2-mapping-se` ## [1] \"hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 --min-intronlen 30 --max-intronlen 3000 -U ./data/SRR446027_1.fastq.gz --threads 4\" ## ## ## $M1B ## $M1B$`hisat2-mapping-se` ## [1] \"hisat2 -S ./results/M1B.sam -x ./data/tair10.fasta -k 1 --min-intronlen 30 --max-intronlen 3000 -U ./data/SRR446028_1.fastq.gz --threads 4\" output(args)[1:2] ## $M1A ## $M1A$`hisat2-mapping-se` ## [1] \"./results/M1A.sam\" ## ## ## $M1B ## $M1B$`hisat2-mapping-se` ## [1] \"./results/M1B.sam\" Subsetting SYSargs2 class slots for each workflow step.\nsubsetWF(args, slot = \"input\", subset = \"FileName\")[1:2] ## Subsetting the input files for this particular workflow ## M1A M1B ## \"./data/SRR446027_1.fastq.gz\" \"./data/SRR446028_1.fastq.gz\" subsetWF(args, slot = \"output\", subset = 1, index = 1)[1:2] ## Subsetting the output files for one particular step in the workflow ## M1A M1B ## \"./results/M1A.sam\" \"./results/M1B.sam\" subsetWF(args, slot = \"step\", subset = 1)[1] ## Subsetting the command-lines for one particular step in the workflow ## M1A ## \"hisat2 -S ./results/M1A.sam -x ./data/tair10.fasta -k 1 --min-intronlen 30 --max-intronlen 3000 -U ./data/SRR446027_1.fastq.gz --threads 4\" subsetWF(args, slot = \"output\", subset = 1, index = 1, delete = TRUE)[1] ## DELETING specific output files ## The subset cannot be deleted: no such file ## M1A ## \"./results/M1A.sam\" Build Hisat2 index.\ndir_path \u003c- system.file(\"extdata/cwl/hisat2/hisat2-idx\", package = \"systemPipeR\") idx \u003c- loadWorkflow(targets = NULL, wf_file = \"hisat2-index.cwl\", input_file = \"hisat2-index.yml\", dir_path = dir_path) idx \u003c- renderWF(idx) idx cmdlist(idx) ## Run runCommandline(idx, make_bam = FALSE) Interactive job submissions in a single machine To simplify the short read alignment execution for the user, the command-line can be run with the runCommandline function. The execution will be on a single machine without submitting to a queuing system of a computer cluster. This way, the input FASTQ files will be processed sequentially. By default runCommandline auto detects SAM file outputs and converts them to sorted and indexed BAM files, using internally the Rsamtools package (Morgan et al. 2019). Besides, runCommandline allows the user to create a dedicated results folder for each workflow and a sub-folder for each sample defined in the targets file. This includes all the output and log files for each step. When these options are used, the output location will be updated by default and can be assigned to the same object.\nrunCommandline(args, make_bam = FALSE) ## generates alignments and writes *.sam files to ./results folder args \u003c- runCommandline(args, make_bam = TRUE) ## same as above but writes files and converts *.sam files to sorted and indexed BAM files. Assigning the new extention of the output files to the object args. If available, multiple CPU cores can be used for processing each file. The number of CPU cores (here 4) to use for each process is defined in the *.yml file. With yamlinput(args)['thread'] one can return this value from the SYSargs2 object.\nParallelization on clusters Alternatively, the computation can be greatly accelerated by processing many files in parallel using several compute nodes of a cluster, where a scheduling/queuing system is used for load balancing. For this the clusterRun function submits the computing requests to the scheduler using the run specifications defined by runCommandline.\nTo avoid over-subscription of CPU cores on the compute nodes, the value from yamlinput(args)['thread'] is passed on to the submission command, here ncpus in the resources list object. The number of independent parallel cluster processes is defined under the Njobs argument. The following example will run 18 processes in parallel using for each 4 CPU cores. If the resources available on a cluster allow running all 18 processes at the same time then the shown sample submission will utilize in total 72 CPU cores. Note, clusterRun can be used with most queueing systems as it is based on utilities from the batchtools package which supports the use of template files (*.tmpl) for defining the run parameters of different schedulers. To run the following code, one needs to have both a conf file (see .batchtools.conf.R samples here) and a template file (see *.tmpl samples here) for the queueing available on a system. The following example uses the sample conf and template files for the Slurm scheduler provided by this package.\nlibrary(batchtools) resources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) reg \u003c- clusterRun(args, FUN = runCommandline, more.args = list(args = args, make_bam = TRUE, dir = FALSE), conffile = \".batchtools.conf.R\", template = \"batchtools.slurm.tmpl\", Njobs = 18, runid = \"01\", resourceList = resources) getStatus(reg = reg) waitForJobs(reg = reg) Check and update the output location if necessary.\nargs \u003c- output_update(args, dir = FALSE, replace = TRUE, extension = c(\".sam\", \".bam\")) ## Updates the output(args) to the right location in the subfolders output(args) Create new targets file To establish the connectivity to the next workflow step, one can write a new targets file with the writeTargetsout function. The new targets file serves as input to the next loadWorkflow and renderWF call.\nnames(clt(args)) writeTargetsout(x = args, file = \"default\", step = 1, new_col = \"FileName\", new_col_output_index = 1, overwrite = TRUE) Alignment with HISAT2 and SAMtools Alternatively, it possible to build an workflow with HISAT2 and SAMtools.\ntargets \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/workflow-hisat2/workflow-hisat2-se\", package = \"systemPipeR\") WF \u003c- loadWorkflow(targets = targets, wf_file = \"workflow_hisat2-se.cwl\", input_file = \"workflow_hisat2-se.yml\", dir_path = dir_path) WF \u003c- renderWF(WF, inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\")) WF cmdlist(WF)[1:2] output(WF)[1:2] Alignment with Tophat2 The NGS reads of this project can also be aligned against the reference genome sequence using Bowtie2/TopHat2 (Kim et al. 2013; Langmead and Salzberg 2012).\nBuild Bowtie2 index.\ndir_path \u003c- system.file(\"extdata/cwl/bowtie2/bowtie2-idx\", package = \"systemPipeR\") idx \u003c- loadWorkflow(targets = NULL, wf_file = \"bowtie2-index.cwl\", input_file = \"bowtie2-index.yml\", dir_path = dir_path) idx \u003c- renderWF(idx) idx cmdlist(idx) ## Run in single machine runCommandline(idx, make_bam = FALSE) The parameter settings of the aligner are defined in the tophat2-mapping-pe.cwl and tophat2-mapping-pe.yml files. The following shows how to construct the corresponding SYSargs2 object, here tophat2PE.\ntargetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/tophat2/tophat2-pe\", package = \"systemPipeR\") tophat2PE \u003c- loadWorkflow(targets = targetsPE, wf_file = \"tophat2-mapping-pe.cwl\", input_file = \"tophat2-mapping-pe.yml\", dir_path = dir_path) tophat2PE \u003c- renderWF(tophat2PE, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) tophat2PE cmdlist(tophat2PE)[1:2] output(tophat2PE)[1:2] ## Run in single machine tophat2PE \u003c- runCommandline(tophat2PE[1], make_bam = TRUE) Parallelization on clusters.\nresources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) reg \u003c- clusterRun(tophat2PE, FUN = runCommandline, more.args = list(args = tophat2PE, make_bam = TRUE, dir = FALSE), conffile = \".batchtools.conf.R\", template = \"batchtools.slurm.tmpl\", Njobs = 18, runid = \"01\", resourceList = resources) waitForJobs(reg = reg) Create new targets file\nnames(clt(tophat2PE)) writeTargetsout(x = tophat2PE, file = \"default\", step = 1, new_col = \"tophat2PE\", new_col_output_index = 1, overwrite = TRUE) Alignment with Bowtie2 (e.g. for miRNA profiling) The following example runs Bowtie2 as a single process without submitting it to a cluster.\nBuilding the index:\ndir_path \u003c- system.file(\"extdata/cwl/bowtie2/bowtie2-idx\", package = \"systemPipeR\") idx \u003c- loadWorkflow(targets = NULL, wf_file = \"bowtie2-index.cwl\", input_file = \"bowtie2-index.yml\", dir_path = dir_path) idx \u003c- renderWF(idx) idx cmdlist(idx) ## Run in single machine runCommandline(idx, make_bam = FALSE) Building all the command-line:\ntargetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/bowtie2/bowtie2-pe\", package = \"systemPipeR\") bowtiePE \u003c- loadWorkflow(targets = targetsPE, wf_file = \"bowtie2-mapping-pe.cwl\", input_file = \"bowtie2-mapping-pe.yml\", dir_path = dir_path) bowtiePE \u003c- renderWF(bowtiePE, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) bowtiePE cmdlist(bowtiePE)[1:2] output(bowtiePE)[1:2] Running all the jobs to computing nodes.\nresources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) reg \u003c- clusterRun(bowtiePE, FUN = runCommandline, more.args = list(args = bowtiePE, dir = FALSE), conffile = \".batchtools.conf.R\", template = \"batchtools.slurm.tmpl\", Njobs = 18, runid = \"01\", resourceList = resources) getStatus(reg = reg) Alternatively, it possible to run all the jobs in a single machine.\nbowtiePE \u003c- runCommandline(bowtiePE) Create new targets file.\nnames(clt(bowtiePE)) writeTargetsout(x = bowtiePE, file = \"default\", step = 1, new_col = \"bowtiePE\", new_col_output_index = 1, overwrite = TRUE) Alignment with BWA-MEM (e.g. for VAR-Seq) The following example runs BWA-MEM as a single process without submitting it to a cluster. ##TODO: add reference\nBuild the index:\ndir_path \u003c- system.file(\"extdata/cwl/bwa/bwa-idx\", package = \"systemPipeR\") idx \u003c- loadWorkflow(targets = NULL, wf_file = \"bwa-index.cwl\", input_file = \"bwa-index.yml\", dir_path = dir_path) idx \u003c- renderWF(idx) idx cmdlist(idx) # Indexes reference genome ## Run runCommandline(idx, make_bam = FALSE) Running the alignment:\ntargetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/bwa/bwa-pe\", package = \"systemPipeR\") bwaPE \u003c- loadWorkflow(targets = targetsPE, wf_file = \"bwa-pe.cwl\", input_file = \"bwa-pe.yml\", dir_path = dir_path) bwaPE \u003c- renderWF(bwaPE, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) bwaPE cmdlist(bwaPE)[1:2] output(bwaPE)[1:2] ## Single Machine bwaPE \u003c- runCommandline(args = bwaPE, make_bam = FALSE) ## Cluster library(batchtools) resources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) reg \u003c- clusterRun(bwaPE, FUN = runCommandline, more.args = list(args = bwaPE, dir = FALSE), conffile = \".batchtools.conf.R\", template = \"batchtools.slurm.tmpl\", Njobs = 18, runid = \"01\", resourceList = resources) getStatus(reg = reg) Create new targets file.\nnames(clt(bwaPE)) writeTargetsout(x = bwaPE, file = \"default\", step = 1, new_col = \"bwaPE\", new_col_output_index = 1, overwrite = TRUE) Alignment with Rsubread (e.g. for RNA-Seq) The following example shows how one can use within the environment the R-based aligner , allowing running from R or command-line.\n## Build the index: dir_path \u003c- system.file(\"extdata/cwl/rsubread/rsubread-idx\", package = \"systemPipeR\") idx \u003c- loadWorkflow(targets = NULL, wf_file = \"rsubread-index.cwl\", input_file = \"rsubread-index.yml\", dir_path = dir_path) idx \u003c- renderWF(idx) idx cmdlist(idx) runCommandline(args = idx, make_bam = FALSE) ## Running the alignment: targets \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/rsubread/rsubread-se\", package = \"systemPipeR\") rsubread \u003c- loadWorkflow(targets = targets, wf_file = \"rsubread-mapping-se.cwl\", input_file = \"rsubread-mapping-se.yml\", dir_path = dir_path) rsubread \u003c- renderWF(rsubread, inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\")) rsubread cmdlist(rsubread)[1] ## Single Machine rsubread \u003c- runCommandline(args = rsubread[1]) Create new targets file.\nnames(clt(rsubread)) writeTargetsout(x = rsubread, file = \"default\", step = 1, new_col = \"rsubread\", new_col_output_index = 1, overwrite = TRUE) Alignment with gsnap (e.g. for VAR-Seq and RNA-Seq) Another R-based short read aligner is gsnap from the gmapR package (Wu and Nacu 2010). The code sample below introduces how to run this aligner on multiple nodes of a compute cluster.\n## Build the index: dir_path \u003c- system.file(\"extdata/cwl/gsnap/gsnap-idx\", package = \"systemPipeR\") idx \u003c- loadWorkflow(targets = NULL, wf_file = \"gsnap-index.cwl\", input_file = \"gsnap-index.yml\", dir_path = dir_path) idx \u003c- renderWF(idx) idx cmdlist(idx) runCommandline(args = idx, make_bam = FALSE) ## Running the alignment: targetsPE \u003c- system.file(\"extdata\", \"targetsPE.txt\", package = \"systemPipeR\") dir_path \u003c- system.file(\"extdata/cwl/gsnap/gsnap-pe\", package = \"systemPipeR\") gsnap \u003c- loadWorkflow(targets = targetsPE, wf_file = \"gsnap-mapping-pe.cwl\", input_file = \"gsnap-mapping-pe.yml\", dir_path = dir_path) gsnap \u003c- renderWF(gsnap, inputvars = c(FileName1 = \"_FASTQ_PATH1_\", FileName2 = \"_FASTQ_PATH2_\", SampleName = \"_SampleName_\")) gsnap cmdlist(gsnap)[1] output(gsnap)[1] ## Cluster library(batchtools) resources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) reg \u003c- clusterRun(gsnap, FUN = runCommandline, more.args = list(args = gsnap, make_bam = FALSE), conffile = \".batchtools.conf.R\", template = \"batchtools.slurm.tmpl\", Njobs = 18, runid = \"01\", resourceList = resources) getStatus(reg = reg) gsnap \u003c- output_update(gsnap, dir = FALSE, replace = TRUE, extension = c(\".sam\", \".bam\")) Create new targets file.\nnames(clt(gsnap)) writeTargetsout(x = gsnap, file = \"default\", step = 1, new_col = \"gsnap\", new_col_output_index = 1, overwrite = TRUE) Create symbolic links for viewing BAM files in IGV The genome browser IGV supports reading of indexed/sorted BAM files via web URLs. This way it can be avoided to create unnecessary copies of these large files. To enable this approach, an HTML directory with Http access needs to be available in the user account (e.g. home/publichtml) of a system. If this is not the case then the BAM files need to be moved or copied to the system where IGV runs. In the following, htmldir defines the path to the HTML directory with http access where the symbolic links to the BAM files will be stored. The corresponding URLs will be written to a text file specified under the _urlfile_ argument.\nsymLink2bam(sysargs = args, htmldir = c(\"~/.html/\", \"somedir/\"), urlbase = \"http://myserver.edu/~username/\", urlfile = \"IGVurl.txt\") Read counting for mRNA profiling experiments Create txdb (needs to be done only once).\nlibrary(GenomicFeatures) txdb \u003c- makeTxDbFromGFF(file = \"data/tair10.gff\", format = \"gff\", dataSource = \"TAIR\", organism = \"Arabidopsis thaliana\") saveDb(txdb, file = \"./data/tair10.sqlite\") The following performs read counting with summarizeOverlaps in parallel mode with multiple cores.\nlibrary(BiocParallel) txdb \u003c- loadDb(\"./data/tair10.sqlite\") eByg \u003c- exonsBy(txdb, by = \"gene\") outpaths \u003c- subsetWF(args, slot = \"output\", subset = 1, index = 1) bfl \u003c- BamFileList(outpaths, yieldSize = 50000, index = character()) multicoreParam \u003c- MulticoreParam(workers = 4) register(multicoreParam) registered() counteByg \u003c- bplapply(bfl, function(x) summarizeOverlaps(eByg, x, mode = \"Union\", ignore.strand = TRUE, inter.feature = TRUE, singleEnd = TRUE)) # Note: for strand-specific RNA-Seq set 'ignore.strand=FALSE' and for PE data # set 'singleEnd=FALSE' countDFeByg \u003c- sapply(seq(along = counteByg), function(x) assays(counteByg[[x]])$counts) rownames(countDFeByg) \u003c- names(rowRanges(counteByg[[1]])) colnames(countDFeByg) \u003c- names(bfl) rpkmDFeByg \u003c- apply(countDFeByg, 2, function(x) returnRPKM(counts = x, ranges = eByg)) write.table(countDFeByg, \"results/countDFeByg.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") write.table(rpkmDFeByg, \"results/rpkmDFeByg.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") Please note, in addition to read counts this step generates RPKM normalized expression values. For most statistical differential expression or abundance analysis methods, such as edgeR or DESeq2, the raw count values should be used as input. The usage of RPKM values should be restricted to specialty applications required by some users, e.g. manually comparing the expression levels of different genes or features.\nRead counting with summarizeOverlaps using multiple nodes of a cluster.\nlibrary(BiocParallel) f \u003c- function(x) { library(systemPipeR) library(BiocParallel) library(GenomicFeatures) txdb \u003c- loadDb(\"./data/tair10.sqlite\") eByg \u003c- exonsBy(txdb, by = \"gene\") args \u003c- systemArgs(sysma = \"param/tophat.param\", mytargets = \"targets.txt\") outpaths \u003c- subsetWF(args, slot = \"output\", subset = 1, index = 1) bfl \u003c- BamFileList(outpaths, yieldSize = 50000, index = character()) summarizeOverlaps(eByg, bfl[x], mode = \"Union\", ignore.strand = TRUE, inter.feature = TRUE, singleEnd = TRUE) } resources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) param \u003c- BatchtoolsParam(workers = 4, cluster = \"slurm\", template = \"batchtools.slurm.tmpl\", resources = resources) counteByg \u003c- bplapply(seq(along = args), f, BPPARAM = param) countDFeByg \u003c- sapply(seq(along = counteByg), function(x) assays(counteByg[[x]])$counts) rownames(countDFeByg) \u003c- names(rowRanges(counteByg[[1]])) colnames(countDFeByg) \u003c- names(outpaths) Useful commands for monitoring the progress of submitted jobs\ngetStatus(reg = reg) outpaths \u003c- subsetWF(args, slot = \"output\", subset = 1, index = 1) file.exists(outpaths) sapply(1:length(outpaths), function(x) loadResult(reg, id = x)) # Works after job completion Read and alignment count stats Generate a table of read and alignment counts for all samples.\nread_statsDF \u003c- alignStats(args) write.table(read_statsDF, \"results/alignStats.xls\", row.names = FALSE, quote = FALSE, sep = \"\\t\") The following shows the first four lines of the sample alignment stats file provided by the systemPipeR package. For simplicity the number of PE reads is multiplied here by 2 to approximate proper alignment frequencies where each read in a pair is counted.\nread.table(system.file(\"extdata\", \"alignStats.xls\", package = \"systemPipeR\"), header = TRUE)[1:4, ] ## FileName Nreads2x Nalign Perc_Aligned Nalign_Primary Perc_Aligned_Primary ## 1 M1A 192918 177961 92.24697 177961 92.24697 ## 2 M1B 197484 159378 80.70426 159378 80.70426 ## 3 A1A 189870 176055 92.72397 176055 92.72397 ## 4 A1B 188854 147768 78.24457 147768 78.24457 Parallelization of read/alignment stats on single machine with multiple cores.\nf \u003c- function(x) alignStats(args[x]) read_statsList \u003c- bplapply(seq(along = args), f, BPPARAM = MulticoreParam(workers = 8)) read_statsDF \u003c- do.call(\"rbind\", read_statsList) Parallelization of read/alignment stats via scheduler (e.g. Slurm) across several compute nodes.\nlibrary(BiocParallel) library(batchtools) f \u003c- function(x) { library(systemPipeR) targets \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") dir_path \u003c- \"param/cwl/hisat2/hisat2-se\" ## TODO: replace path to system.file args \u003c- loadWorkflow(targets = targets, wf_file = \"hisat2-mapping-se.cwl\", input_file = \"hisat2-mapping-se.yml\", dir_path = dir_path) args \u003c- renderWF(args, inputvars = c(FileName = \"_FASTQ_PATH1_\", SampleName = \"_SampleName_\")) args \u003c- output_update(args, dir = FALSE, replace = TRUE, extension = c(\".sam\", \".bam\")) alignStats(args[x]) } resources \u003c- list(walltime = 120, ntasks = 1, ncpus = 4, memory = 1024) param \u003c- BatchtoolsParam(workers = 4, cluster = \"slurm\", template = \"batchtools.slurm.tmpl\", resources = resources) read_statsList \u003c- bplapply(seq(along = args), f, BPPARAM = param) read_statsDF \u003c- do.call(\"rbind\", read_statsList) Read counting for miRNA profiling experiments Download miRNA genes from miRBase.\nsystem(\"wget ftp://mirbase.org/pub/mirbase/19/genomes/My_species.gff3 -P ./data/\") gff \u003c- import.gff(\"./data/My_species.gff3\") gff \u003c- split(gff, elementMetadata(gff)$ID) bams \u003c- names(bampaths) names(bams) \u003c- targets$SampleName bfl \u003c- BamFileList(bams, yieldSize = 50000, index = character()) countDFmiR \u003c- summarizeOverlaps(gff, bfl, mode = \"Union\", ignore.strand = FALSE, inter.feature = FALSE) # Note: inter.feature=FALSE important since pre and mature miRNA ranges overlap rpkmDFmiR \u003c- apply(countDFmiR, 2, function(x) returnRPKM(counts = x, gffsub = gff)) write.table(assays(countDFmiR)$counts, \"results/countDFmiR.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") write.table(rpkmDFmiR, \"results/rpkmDFmiR.xls\", col.names = NA, quote = FALSE, sep = \"\\t\") Correlation analysis of samples The following computes the sample-wise Spearman correlation coefficients from the rlog (regularized-logarithm) transformed expression values generated with the DESeq2 package. After transformation to a distance matrix, hierarchical clustering is performed with the hclust function and the result is plotted as a dendrogram (sample_tree.pdf).\nlibrary(DESeq2, warn.conflicts = FALSE, quietly = TRUE) library(ape, warn.conflicts = FALSE) countDFpath \u003c- system.file(\"extdata\", \"countDFeByg.xls\", package = \"systemPipeR\") countDF \u003c- as.matrix(read.table(countDFpath)) colData \u003c- data.frame(row.names = targets.as.df(targets(args))$SampleName, condition = targets.as.df(targets(args))$Factor) dds \u003c- DESeqDataSetFromMatrix(countData = countDF, colData = colData, design = ~condition) ## Warning in DESeqDataSet(se, design = design, ignoreRank): some variables in ## design formula are characters, converting to factors d \u003c- cor(assay(rlog(dds)), method = \"spearman\") hc \u003c- hclust(dist(1 - d)) plot.phylo(as.phylo(hc), type = \"p\", edge.col = 4, edge.width = 3, show.node.label = TRUE, no.margin = TRUE) Figure 2: Correlation dendrogram of samples for rlog values.\n Alternatively, the clustering can be performed with RPKM normalized expression values. In combination with Spearman correlation the results of the two clustering methods are often relatively similar.\nrpkmDFeBygpath \u003c- system.file(\"extdata\", \"rpkmDFeByg.xls\", package = \"systemPipeR\") rpkmDFeByg \u003c- read.table(rpkmDFeBygpath, check.names = FALSE) rpkmDFeByg \u003c- rpkmDFeByg[rowMeans(rpkmDFeByg) \u003e 50, ] d \u003c- cor(rpkmDFeByg, method = \"spearman\") hc \u003c- hclust(as.dist(1 - d)) plot.phylo(as.phylo(hc), type = \"p\", edge.col = \"blue\", edge.width = 2, show.node.label = TRUE, no.margin = TRUE) DEG analysis with edgeR The following *run_edgeR* function is a convenience wrapper for identifying differentially expressed genes (DEGs) in batch mode with *edgeR’s GML method (Robinson, McCarthy, and Smyth 2010) for any number of pairwise sample comparisons specified under the cmp* argument. Users are strongly encouraged to consult the edgeR vignette for more detailed information on this topic and how to properly run edgeR on data sets with more complex experimental designs.\ntargetspath \u003c- system.file(\"extdata\", \"targets.txt\", package = \"systemPipeR\") targets \u003c- read.delim(targetspath, comment = \"#\") cmp \u003c- readComp(file = targetspath, format = \"matrix\", delim = \"-\") cmp[[1]] ## [,1] [,2] ## [1,] \"M1\" \"A1\" ## [2,] \"M1\" \"V1\" ## [3,] \"A1\" \"V1\" ## [4,] \"M6\" \"A6\" ## [5,] \"M6\" \"V6\" ## [6,] \"A6\" \"V6\" ## [7,] \"M12\" \"A12\" ## [8,] \"M12\" \"V12\" ## [9,] \"A12\" \"V12\" countDFeBygpath \u003c- system.file(\"extdata\", \"countDFeByg.xls\", package = \"systemPipeR\") countDFeByg \u003c- read.delim(countDFeBygpath, row.names = 1) edgeDF \u003c- run_edgeR(countDF = countDFeByg, targets = targets, cmp = cmp[[1]], independent = FALSE, mdsplot = \"\") ## Loading required namespace: edgeR ## Disp = 0.21829 , BCV = 0.4672 Filter and plot DEG results for up and down-regulated genes. Because of the small size of the toy data set used by this vignette, the FDR value has been set to a relatively high threshold (here 10%). More commonly used FDR cutoffs are 1% or 5%. The definition of ‘up’ and ‘down’ is given in the corresponding help file. To open it, type ?filterDEGs in the R console.\nDEG_list \u003c- filterDEGs(degDF = edgeDF, filter = c(Fold = 2, FDR = 10)) Figure 3: Up and down regulated DEGs identified by edgeR.\n names(DEG_list) ## [1] \"UporDown\" \"Up\" \"Down\" \"Summary\" DEG_list$Summary[1:4, ] ## Comparisons Counts_Up_or_Down Counts_Up Counts_Down ## M1-A1 M1-A1 0 0 0 ## M1-V1 M1-V1 1 1 0 ## A1-V1 A1-V1 1 1 0 ## M6-A6 M6-A6 0 0 0 DEG analysis with DESeq2 The following *run_DESeq2* function is a convenience wrapper for identifying DEGs in batch mode with DESeq2* (Love, Huber, and Anders 2014) for any number of pairwise sample comparisons specified under the cmp* argument. Users are strongly encouraged to consult the DESeq2 vignette for more detailed information on this topic and how to properly run DESeq2 on data sets with more complex experimental designs.\ndegseqDF \u003c- run_DESeq2(countDF = countDFeByg, targets = targets, cmp = cmp[[1]], independent = FALSE) ## Warning in DESeqDataSet(se, design = design, ignoreRank): some variables in ## design formula are characters, converting to factors Filter and plot DEG results for up and down-regulated genes.\nDEG_list2 \u003c- filterDEGs(degDF = degseqDF, filter = c(Fold = 2, FDR = 10)) Figure 4: Up and down regulated DEGs identified by DESeq2.\n Venn Diagrams The function overLapper can compute Venn intersects for large numbers of sample sets (up to 20 or more) and vennPlot can plot 2-5 way Venn diagrams. A useful feature is the possibility to combine the counts from several Venn comparisons with the same number of sample sets in a single Venn diagram (here for 4 up and down DEG sets).\nvennsetup \u003c- overLapper(DEG_list$Up[6:9], type = \"vennsets\") vennsetdown \u003c- overLapper(DEG_list$Down[6:9], type = \"vennsets\") vennPlot(list(vennsetup, vennsetdown), mymain = \"\", mysub = \"\", colmode = 2, ccol = c(\"blue\", \"red\")) Figure 5: Venn Diagram for 4 Up and Down DEG Sets.\n GO term enrichment analysis of DEGs Obtain gene-to-GO mappings The following shows how to obtain gene-to-GO mappings from biomaRt (here for A. thaliana) and how to organize them for the downstream GO term enrichment analysis. Alternatively, the gene-to-GO mappings can be obtained for many organisms from Bioconductor’s *.db genome annotation packages or GO annotation files provided by various genome databases. For each annotation, this relatively slow preprocessing step needs to be performed only once. Subsequently, the preprocessed data can be loaded with the load function as shown in the next subsection.\nlibrary(\"biomaRt\") listMarts() # To choose BioMart database listMarts(host = \"plants.ensembl.org\") m \u003c- useMart(\"plants_mart\", host = \"plants.ensembl.org\") listDatasets(m) m \u003c- useMart(\"plants_mart\", dataset = \"athaliana_eg_gene\", host = \"plants.ensembl.org\") listAttributes(m) # Choose data types you want to download go \u003c- getBM(attributes = c(\"go_id\", \"tair_locus\", \"namespace_1003\"), mart = m) go \u003c- go[go[, 3] != \"\", ] go[, 3] \u003c- as.character(go[, 3]) go[go[, 3] == \"molecular_function\", 3] \u003c- \"F\" go[go[, 3] == \"biological_process\", 3] \u003c- \"P\" go[go[, 3] == \"cellular_component\", 3] \u003c- \"C\" go[1:4, ] dir.create(\"./data/GO\") write.table(go, \"data/GO/GOannotationsBiomart_mod.txt\", quote = FALSE, row.names = FALSE, col.names = FALSE, sep = \"\\t\") catdb \u003c- makeCATdb(myfile = \"data/GO/GOannotationsBiomart_mod.txt\", lib = NULL, org = \"\", colno = c(1, 2, 3), idconv = NULL) save(catdb, file = \"data/GO/catdb.RData\") Batch GO term enrichment analysis Apply the enrichment analysis to the DEG sets obtained in the above differential expression analysis. Note, in the following example the FDR filter is set here to an unreasonably high value, simply because of the small size of the toy data set used in this vignette. Batch enrichment analysis of many gene sets is performed with the GOCluster_Report function. When method=\"all\", it returns all GO terms passing the p-value cutoff specified under the cutoff arguments. When method=\"slim\", it returns only the GO terms specified under the myslimv argument. The given example shows how one can obtain such a GO slim vector from BioMart for a specific organism.\nload(\"data/GO/catdb.RData\") DEG_list \u003c- filterDEGs(degDF = edgeDF, filter = c(Fold = 2, FDR = 50), plot = FALSE) up_down \u003c- DEG_list$UporDown names(up_down) \u003c- paste(names(up_down), \"_up_down\", sep = \"\") up \u003c- DEG_list$Up names(up) \u003c- paste(names(up), \"_up\", sep = \"\") down \u003c- DEG_list$Down names(down) \u003c- paste(names(down), \"_down\", sep = \"\") DEGlist \u003c- c(up_down, up, down) DEGlist \u003c- DEGlist[sapply(DEGlist, length) \u003e 0] BatchResult \u003c- GOCluster_Report(catdb = catdb, setlist = DEGlist, method = \"all\", id_type = \"gene\", CLSZ = 2, cutoff = 0.9, gocats = c(\"MF\", \"BP\", \"CC\"), recordSpecGO = NULL) library(\"biomaRt\") m \u003c- useMart(\"plants_mart\", dataset = \"athaliana_eg_gene\", host = \"plants.ensembl.org\") goslimvec \u003c- as.character(getBM(attributes = c(\"goslim_goa_accession\"), mart = m)[, 1]) BatchResultslim \u003c- GOCluster_Report(catdb = catdb, setlist = DEGlist, method = \"slim\", id_type = \"gene\", myslimv = goslimvec, CLSZ = 10, cutoff = 0.01, gocats = c(\"MF\", \"BP\", \"CC\"), recordSpecGO = NULL) Plot batch GO term results The data.frame generated by GOCluster_Report can be plotted with the goBarplot function. Because of the variable size of the sample sets, it may not always be desirable to show the results from different DEG sets in the same bar plot. Plotting single sample sets is achieved by subsetting the input data frame as shown in the first line of the following example.\ngos \u003c- BatchResultslim[grep(\"M6-V6_up_down\", BatchResultslim$CLID), ] gos \u003c- BatchResultslim pdf(\"GOslimbarplotMF.pdf\", height = 8, width = 10) goBarplot(gos, gocat = \"MF\") dev.off() goBarplot(gos, gocat = \"BP\") goBarplot(gos, gocat = \"CC\") Figure 6: GO Slim Barplot for MF Ontology.\n Clustering and heat maps The following example performs hierarchical clustering on the rlog transformed expression matrix subsetted by the DEGs identified in the above differential expression analysis. It uses a Pearson correlation-based distance measure and complete linkage for cluster join.\nlibrary(pheatmap) geneids \u003c- unique(as.character(unlist(DEG_list[[1]]))) y \u003c- assay(rlog(dds))[geneids, ] pdf(\"heatmap1.pdf\") pheatmap(y, scale = \"row\", clustering_distance_rows = \"correlation\", clustering_distance_cols = \"correlation\") dev.off() Figure 7: Heat map with hierarchical clustering dendrograms of DEGs.\n References Kim, Daehwan, Ben Langmead, and Steven L Salzberg. 2015. “HISAT: A Fast Spliced Aligner with Low Memory Requirements.” Nat. Methods 12 (4): 357–60.\n Kim, Daehwan, Geo Pertea, Cole Trapnell, Harold Pimentel, Ryan Kelley, and Steven L Salzberg. 2013. “TopHat2: Accurate Alignment of Transcriptomes in the Presence of Insertions, Deletions and Gene Fusions.” Genome Biol. 14 (4): R36. https://doi.org/10.1186/gb-2013-14-4-r36.\n Langmead, Ben, and Steven L Salzberg. 2012. “Fast Gapped-Read Alignment with Bowtie 2.” Nat. Methods 9 (4): 357–59. https://doi.org/10.1038/nmeth.1923.\n Love, Michael, Wolfgang Huber, and Simon Anders. 2014. “Moderated Estimation of Fold Change and Dispersion for RNA-seq Data with DESeq2.” Genome Biol. 15 (12): 550. https://doi.org/10.1186/s13059-014-0550-8.\n Morgan, Martin, Hervé Pagès, Valerie Obenchain, and Nathaniel Hayden. 2019. Rsamtools: Binary Alignment (BAM), FASTA, Variant Call (BCF), and Tabix File Import. http://bioconductor.org/packages/Rsamtools.\n Robinson, M D, D J McCarthy, and G K Smyth. 2010. “edgeR: A Bioconductor Package for Differential Expression Analysis of Digital Gene Expression Data.” Bioinformatics 26 (1): 139–40. https://doi.org/10.1093/bioinformatics/btp616.\n Wu, T D, and S Nacu. 2010. “Fast and SNP-tolerant Detection of Complex Variants and Splicing in Short Reads.” Bioinformatics 26 (7): 873–81. https://doi.org/10.1093/bioinformatics/btq057.\n ","categories":"","description":"","excerpt":"document.addEventListener(\"DOMContentLoaded\", function() { …","ref":"/sp/spr/steps_oldversion/","tags":"","title":"Workflow steps overview"}]