Identify relevant workspaces
This notebook is intended to illustrate combining data from multiple
PRIMED workspaces for an analysis. We will take the example of a
researcher studying colorectal cancer who wants to use summary
statistics from two studies: the UKBB and published results from a GWAS.
Both studies are available in PRIMED open access workspaces.
To fetch data from a workspace, we need two pieces of information:
the workspace name and the namespace, also known as the billing project.
The URL for every AnVIL workspace takes the form
<https://anvil.terra.bio/#workspaces/namespace/workspace_name>
.
Therefore, we can always find this information for a workspace by
navigating to it in the Workspaces menu on the AnVIL platform. Based on
the URLs listed above, we can identify the workspace names and
namespaces to be:
ukbb_workspace <- "PRIMED_PAN_UKBB_GSR_CANCER"
ukbb_namespace <- "primed-data-cc-open"
crc_workspace <- "PRIMED_CRC_PMID36539618"
crc_namespace <- "primed-data-primed-cancer-open"
Retrieve data from UKBB workspace
We start with the UKBB Cancer workspace. Using the
avtable()
function from the AnVIL package, we can read in
the analysis
table to identify relevant analyses for our
project. Each row of the analysis
table corresponds to a
different analysis with summary statistics in the workspace. See the
PRIMED Data Model for details on all of the columns in this table. The
trait
column gives the name of the trait variable for that
analysis.
library(AnVIL)
Loading required package: dplyr
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
There are four analyses of colorectal cancer, in different
populations. Each row in the analysis
table is assigned an
analysis_id
when it is imported to AnVIL, which is the
primary key for this table.
ukbb_crc <- ukbb_analysis %>%
filter(trait == "Colorectal cancer")
select(ukbb_crc, analysis_id, trait, population_descriptor, population_labels)
The gsr_file
table contains bucket paths to the data
from these analyses, one file per row. See the PRIMED Data Model for
details on all of the columns in this table. The
analysis_id
links the analysis to files in the
gsr_file
table, so we use it to identify the files in the
gsr_file
table corresponding to the analysis we want (in
this case, the files from the multi-population analysis).
ukbb_gsr_file <- avtable("gsr_file",
name = ukbb_workspace,
namespace = ukbb_namespace) %>%
filter(analysis_id == "93f9b24b")
select(ukbb_gsr_file, analysis_id, chromosome, file_path) %>%
head(n=2)
count(ukbb_gsr_file, analysis_id)
This analysis has 23 files, one file per chromosome. We use the
gsutil_cp()
function to copy the files to our current cloud
environment.
dir.create("UKBB_CRC")
gsutil_cp(ukbb_gsr_file$file_path, "UKBB_CRC")
Retrieve data from GWAS workspace
The CRC GWAS workspace contains only a single analysis.
crc_analysis <- avtable("analysis",
name = crc_workspace,
namespace = crc_namespace)
select(crc_analysis, analysis_id, trait, population_descriptor, population_labels)
The gsr_file
table contains bucket paths to the data for
this analysis.
crc_gsr_file <- avtable("gsr_file",
name = crc_workspace,
namespace = crc_namespace)
This analysis has only one associated file, with the results for all
chromosomes. We use the gsutil_cp()
function to copy the
files to our current cloud environment.
dir.create("GWAS_CRC")
gsutil_cp(crc_gsr_file$file_path, "GWAS_CRC")
Write data tables to the workspace
To more easily keep track of the data we’re working with, we can
create analysis
and gsr_file
tables in this
workspace. Since all data is in the PRIMED data model, it is
straightforward to concatenate tables. The AnVIL package has a function
to import data tables to a workspace. The entity
argument
should contain the primary key for the table.
bind_rows(crc_analysis, ukbb_analysis) %>%
avtable_import()
pageSize = 27 rows (1 pages)
Read in summary statistics
Since we have already copied the GSR files to our compute
environment, we can read a file into R.
library(readr)
ukbb_chr22_file <- ukbb_gsr_file %>%
filter(chromosome == 22) %>%
select(file_path) %>%
unlist() %>%
basename()
ukbb_chr22 <- read_tsv(file.path("UKBB_CRC", ukbb_chr22_file))
Rows: 260586 Columns: 24── Column specification ──────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (8): SNPID, rsID, strand, effect_allele, other_allele, ref_allele, alt_allele, direction_of_effect
dbl (16): chromosome, position, effect_allele_freq, eaf_case, eaf_ctrl, p_value, p_value_log10, beta, se, ...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(ukbb_chr22)
We read GSR files for chromosome 22 from both analyses and match
variants. One of the analyses has all chromosomes in a single file, so
we filter to the desired set of variants.
crc_file <- crc_gsr_file %>%
select(file_path) %>%
unlist() %>%
basename()
crc_chr22 <- read_tsv(file.path("GWAS_CRC", crc_file)) %>%
filter(chromosome == 22)
We need to know if the files are both in the same genome build to
decide if they can be merged as-is or if liftover is required. This
information is in the analysis table.
select(ukbb_analysis, analysis_id, reference_assembly) %>%
filter(analysis_id %in% ukbb_gsr_file$analysis_id)
select(crc_analysis, analysis_id, reference_assembly)
Both analyses are in reference assembly GRCh37. This means we can
join the GSR tables on overlapping variants.
nrow(ukbb_chr22)
[1] 260586
nrow(crc_chr22)
[1] 295329
merged <- inner_join(ukbb_chr22, crc_chr22,
by=c("chromosome", "position", "effect_allele", "other_allele"),
suffix=c("_ukbb", "_crc"))
nrow(merged)
[1] 170229
head(merged)
library(ggplot2)
ggplot(merged, aes(beta_ukbb, beta_crc)) + geom_point() + xlim(-1,1) + ylim(-1,1)

LS0tCnRpdGxlOiAiQ1JDIHN1bW1hcnkgc3RhdGlzdGljcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBJZGVudGlmeSByZWxldmFudCB3b3Jrc3BhY2VzCgpUaGlzIG5vdGVib29rIGlzIGludGVuZGVkIHRvIGlsbHVzdHJhdGUgY29tYmluaW5nIGRhdGEgZnJvbSBtdWx0aXBsZSBQUklNRUQgCndvcmtzcGFjZXMgZm9yIGFuIGFuYWx5c2lzLiBXZSB3aWxsIHRha2UgdGhlIGV4YW1wbGUgb2YgYSByZXNlYXJjaGVyIHN0dWR5aW5nCmNvbG9yZWN0YWwgY2FuY2VyIHdobyB3YW50cyB0byB1c2Ugc3VtbWFyeSBzdGF0aXN0aWNzIGZyb20gdHdvIHN0dWRpZXM6IHRoZQpVS0JCIGFuZCBwdWJsaXNoZWQgcmVzdWx0cyBmcm9tIGEgR1dBUy4gQm90aCBzdHVkaWVzIGFyZSBhdmFpbGFibGUgaW4gUFJJTUVECm9wZW4gYWNjZXNzIHdvcmtzcGFjZXMuCgotIGh0dHBzOi8vYW52aWwudGVycmEuYmlvLyN3b3Jrc3BhY2VzL3ByaW1lZC1kYXRhLWNjLW9wZW4vUFJJTUVEX1BBTl9VS0JCX0dTUl9DQU5DRVIKLSBodHRwczovL2FudmlsLnRlcnJhLmJpby8jd29ya3NwYWNlcy9wcmltZWQtZGF0YS1wcmltZWQtY2FuY2VyLW9wZW4vUFJJTUVEX0NSQ19QTUlEMzY1Mzk2MTgKClRvIGZldGNoIGRhdGEgZnJvbSBhIHdvcmtzcGFjZSwgd2UgbmVlZCB0d28gcGllY2VzIG9mIGluZm9ybWF0aW9uOiB0aGUgd29ya3NwYWNlIG5hbWUgYW5kIHRoZSBuYW1lc3BhY2UsIGFsc28ga25vd24gYXMgdGhlIGJpbGxpbmcgcHJvamVjdC4gVGhlIFVSTCBmb3IgZXZlcnkgQW5WSUwgd29ya3NwYWNlIHRha2VzIHRoZSBmb3JtIGA8aHR0cHM6Ly9hbnZpbC50ZXJyYS5iaW8vI3dvcmtzcGFjZXMvbmFtZXNwYWNlL3dvcmtzcGFjZV9uYW1lPmAuIFRoZXJlZm9yZSwgd2UgY2FuIGFsd2F5cyBmaW5kIHRoaXMgaW5mb3JtYXRpb24gZm9yIGEgd29ya3NwYWNlIGJ5IG5hdmlnYXRpbmcgdG8gaXQgaW4gdGhlIFdvcmtzcGFjZXMgbWVudSBvbiB0aGUgQW5WSUwgcGxhdGZvcm0uIEJhc2VkIG9uIHRoZSBVUkxzIGxpc3RlZCBhYm92ZSwgd2UgY2FuIGlkZW50aWZ5IHRoZSB3b3Jrc3BhY2UgbmFtZXMgYW5kIG5hbWVzcGFjZXMgdG8gYmU6IAoKYGBge3J9CnVrYmJfd29ya3NwYWNlIDwtICJQUklNRURfUEFOX1VLQkJfR1NSX0NBTkNFUiIKdWtiYl9uYW1lc3BhY2UgPC0gInByaW1lZC1kYXRhLWNjLW9wZW4iCmNyY193b3Jrc3BhY2UgPC0gIlBSSU1FRF9DUkNfUE1JRDM2NTM5NjE4IgpjcmNfbmFtZXNwYWNlIDwtICJwcmltZWQtZGF0YS1wcmltZWQtY2FuY2VyLW9wZW4iCmBgYAoKIyBSZXRyaWV2ZSBkYXRhIGZyb20gVUtCQiB3b3Jrc3BhY2UKCldlIHN0YXJ0IHdpdGggdGhlIFVLQkIgQ2FuY2VyIHdvcmtzcGFjZS4gVXNpbmcgdGhlIGBhdnRhYmxlKClgIGZ1bmN0aW9uIGZyb20gdGhlIEFuVklMIHBhY2thZ2UsIHdlIGNhbiByZWFkIGluIHRoZSBgYW5hbHlzaXNgIHRhYmxlIHRvIGlkZW50aWZ5IHJlbGV2YW50IGFuYWx5c2VzIGZvciBvdXIgcHJvamVjdC4gRWFjaCByb3cgb2YgdGhlIGBhbmFseXNpc2AgdGFibGUgY29ycmVzcG9uZHMgdG8gYSBkaWZmZXJlbnQgYW5hbHlzaXMgd2l0aCBzdW1tYXJ5IHN0YXRpc3RpY3MgaW4gdGhlIHdvcmtzcGFjZS4gU2VlIHRoZSBQUklNRUQgRGF0YSBNb2RlbCBmb3IgZGV0YWlscyBvbiBhbGwgb2YgdGhlIGNvbHVtbnMgaW4gdGhpcyB0YWJsZS4gVGhlIGB0cmFpdGAgY29sdW1uIGdpdmVzIHRoZSBuYW1lIG9mIHRoZSB0cmFpdCB2YXJpYWJsZSBmb3IgdGhhdCBhbmFseXNpcy4gCgpgYGB7cn0KbGlicmFyeShBblZJTCkKbGlicmFyeShkcGx5cikKCnVrYmJfYW5hbHlzaXMgPC0gYXZ0YWJsZSgiYW5hbHlzaXMiLCAKICAgICAgICAgICAgICAgICAgICBuYW1lID0gdWtiYl93b3Jrc3BhY2UsCiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gdWtiYl9uYW1lc3BhY2UpCgpjb3VudCh1a2JiX2FuYWx5c2lzLCB0cmFpdCkKYGBgCgpUaGVyZSBhcmUgZm91ciBhbmFseXNlcyBvZiBjb2xvcmVjdGFsIGNhbmNlciwgaW4gZGlmZmVyZW50IHBvcHVsYXRpb25zLiBFYWNoIHJvdyBpbiB0aGUgYGFuYWx5c2lzYCB0YWJsZSBpcyBhc3NpZ25lZCBhbiBgYW5hbHlzaXNfaWRgIHdoZW4gaXQgaXMgaW1wb3J0ZWQgdG8gQW5WSUwsIHdoaWNoIGlzIHRoZSBwcmltYXJ5IGtleSBmb3IgdGhpcyB0YWJsZS4gCgpgYGB7cn0KdWtiYl9jcmMgPC0gdWtiYl9hbmFseXNpcyAlPiUKICBmaWx0ZXIodHJhaXQgPT0gIkNvbG9yZWN0YWwgY2FuY2VyIikKCnNlbGVjdCh1a2JiX2NyYywgYW5hbHlzaXNfaWQsIHRyYWl0LCBwb3B1bGF0aW9uX2Rlc2NyaXB0b3IsIHBvcHVsYXRpb25fbGFiZWxzKQpgYGAKClRoZSBgZ3NyX2ZpbGVgIHRhYmxlIGNvbnRhaW5zIGJ1Y2tldCBwYXRocyB0byB0aGUgZGF0YSBmcm9tIHRoZXNlIGFuYWx5c2VzLCBvbmUgZmlsZSBwZXIgcm93LiBTZWUgdGhlIFBSSU1FRCBEYXRhIE1vZGVsIGZvciBkZXRhaWxzIG9uIGFsbCBvZiB0aGUgY29sdW1ucyBpbiB0aGlzIHRhYmxlLiBUaGUgYGFuYWx5c2lzX2lkYCBsaW5rcyB0aGUgYW5hbHlzaXMgdG8gZmlsZXMgaW4gdGhlIGBnc3JfZmlsZWAgdGFibGUsIHNvIHdlIHVzZSBpdCB0byBpZGVudGlmeSB0aGUgZmlsZXMgaW4gdGhlIGBnc3JfZmlsZWAgdGFibGUgY29ycmVzcG9uZGluZyB0byB0aGUgYW5hbHlzaXMgd2Ugd2FudCAoaW4gdGhpcyBjYXNlLCB0aGUgZmlsZXMgZnJvbSB0aGUgbXVsdGktcG9wdWxhdGlvbiBhbmFseXNpcykuCgpgYGB7cn0KdWtiYl9nc3JfZmlsZSA8LSBhdnRhYmxlKCJnc3JfZmlsZSIsIAogICAgICAgICAgICAgICAgICAgIG5hbWUgPSB1a2JiX3dvcmtzcGFjZSwKICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSB1a2JiX25hbWVzcGFjZSkgJT4lCiAgZmlsdGVyKGFuYWx5c2lzX2lkID09ICI5M2Y5YjI0YiIpCgpzZWxlY3QodWtiYl9nc3JfZmlsZSwgYW5hbHlzaXNfaWQsIGNocm9tb3NvbWUsIGZpbGVfcGF0aCkgJT4lCiAgaGVhZChuPTIpCgpjb3VudCh1a2JiX2dzcl9maWxlLCBhbmFseXNpc19pZCkKYGBgCgpUaGlzIGFuYWx5c2lzIGhhcyAyMyBmaWxlcywgb25lIGZpbGUgcGVyIGNocm9tb3NvbWUuIFdlIHVzZSB0aGUgYGdzdXRpbF9jcCgpYCBmdW5jdGlvbiB0byBjb3B5IHRoZSBmaWxlcyB0byBvdXIgY3VycmVudCBjbG91ZCBlbnZpcm9ubWVudC4KCmBgYHtyfQpkaXIuY3JlYXRlKCJVS0JCX0NSQyIpCmdzdXRpbF9jcCh1a2JiX2dzcl9maWxlJGZpbGVfcGF0aCwgIlVLQkJfQ1JDIikKYGBgCgoKIyBSZXRyaWV2ZSBkYXRhIGZyb20gR1dBUyB3b3Jrc3BhY2UKClRoZSBDUkMgR1dBUyB3b3Jrc3BhY2UgY29udGFpbnMgb25seSBhIHNpbmdsZSBhbmFseXNpcy4KCmBgYHtyfQpjcmNfYW5hbHlzaXMgPC0gYXZ0YWJsZSgiYW5hbHlzaXMiLCAKICAgICAgICAgICAgICAgICAgICBuYW1lID0gY3JjX3dvcmtzcGFjZSwKICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBjcmNfbmFtZXNwYWNlKQoKc2VsZWN0KGNyY19hbmFseXNpcywgYW5hbHlzaXNfaWQsIHRyYWl0LCBwb3B1bGF0aW9uX2Rlc2NyaXB0b3IsIHBvcHVsYXRpb25fbGFiZWxzKQpgYGAKClRoZSBgZ3NyX2ZpbGVgIHRhYmxlIGNvbnRhaW5zIGJ1Y2tldCBwYXRocyB0byB0aGUgZGF0YSBmb3IgdGhpcyBhbmFseXNpcy4KCmBgYHtyfQpjcmNfZ3NyX2ZpbGUgPC0gYXZ0YWJsZSgiZ3NyX2ZpbGUiLCAKICAgICAgICAgICAgICAgICAgICBuYW1lID0gY3JjX3dvcmtzcGFjZSwKICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBjcmNfbmFtZXNwYWNlKQoKc2VsZWN0KGNyY19nc3JfZmlsZSwgYW5hbHlzaXNfaWQsIGNocm9tb3NvbWUsIGZpbGVfcGF0aCkKYGBgCgpUaGlzIGFuYWx5c2lzIGhhcyBvbmx5IG9uZSBhc3NvY2lhdGVkIGZpbGUsIHdpdGggdGhlIHJlc3VsdHMgZm9yIGFsbCBjaHJvbW9zb21lcy4gV2UgdXNlIHRoZSBgZ3N1dGlsX2NwKClgIGZ1bmN0aW9uIHRvIGNvcHkgdGhlIGZpbGVzIHRvIG91ciBjdXJyZW50IGNsb3VkIGVudmlyb25tZW50LgoKYGBge3J9CmRpci5jcmVhdGUoIkdXQVNfQ1JDIikKZ3N1dGlsX2NwKGNyY19nc3JfZmlsZSRmaWxlX3BhdGgsICJHV0FTX0NSQyIpCmBgYAoKCiMgV3JpdGUgZGF0YSB0YWJsZXMgdG8gdGhlIHdvcmtzcGFjZQoKVG8gbW9yZSBlYXNpbHkga2VlcCB0cmFjayBvZiB0aGUgZGF0YSB3ZSdyZSB3b3JraW5nIHdpdGgsIHdlIGNhbiBjcmVhdGUgCmBhbmFseXNpc2AgYW5kIGBnc3JfZmlsZWAgdGFibGVzIGluIHRoaXMgd29ya3NwYWNlLiBTaW5jZSBhbGwgZGF0YSBpcyBpbiB0aGUKUFJJTUVEIGRhdGEgbW9kZWwsIGl0IGlzIHN0cmFpZ2h0Zm9yd2FyZCB0byBjb25jYXRlbmF0ZSB0YWJsZXMuIFRoZSBBblZJTCAKcGFja2FnZSBoYXMgYSBmdW5jdGlvbiB0byBpbXBvcnQgZGF0YSB0YWJsZXMgdG8gYSB3b3Jrc3BhY2UuIFRoZSBgZW50aXR5YAphcmd1bWVudCBzaG91bGQgY29udGFpbiB0aGUgcHJpbWFyeSBrZXkgZm9yIHRoZSB0YWJsZS4KCmBgYHtyfQpiaW5kX3Jvd3MoY3JjX2FuYWx5c2lzLCB1a2JiX2FuYWx5c2lzKSAlPiUKICBhdnRhYmxlX2ltcG9ydChlbnRpdHkgPSAiYW5hbHlzaXNfaWQiKQpiaW5kX3Jvd3MoY3JjX2dzcl9maWxlLCB1a2JiX2dzcl9maWxlKSAlPiUKICBhdnRhYmxlX2ltcG9ydChlbnRpdHkgPSAiZ3NyX2ZpbGVfaWQiKQpgYGAKCgojIFJlYWQgaW4gc3VtbWFyeSBzdGF0aXN0aWNzCgpTaW5jZSB3ZSBoYXZlIGFscmVhZHkgY29waWVkIHRoZSBHU1IgZmlsZXMgdG8gb3VyIGNvbXB1dGUgZW52aXJvbm1lbnQsIHdlIGNhbiByZWFkIGEgZmlsZSBpbnRvIFIuCgpgYGB7cn0KbGlicmFyeShyZWFkcikKCnVrYmJfY2hyMjJfZmlsZSA8LSB1a2JiX2dzcl9maWxlICU+JQogIGZpbHRlcihjaHJvbW9zb21lID09IDIyKSAlPiUKICBzZWxlY3QoZmlsZV9wYXRoKSAlPiUKICB1bmxpc3QoKSAlPiUKICBiYXNlbmFtZSgpCgp1a2JiX2NocjIyIDwtIHJlYWRfdHN2KGZpbGUucGF0aCgiVUtCQl9DUkMiLCB1a2JiX2NocjIyX2ZpbGUpKQpoZWFkKHVrYmJfY2hyMjIpCmBgYAoKV2UgcmVhZCBHU1IgZmlsZXMgZm9yIGNocm9tb3NvbWUgMjIgZnJvbSBib3RoIGFuYWx5c2VzIGFuZCBtYXRjaCB2YXJpYW50cy4gT25lIG9mIHRoZSBhbmFseXNlcyBoYXMgCmFsbCBjaHJvbW9zb21lcyBpbiBhIHNpbmdsZSBmaWxlLCBzbyB3ZSBmaWx0ZXIgdG8gdGhlIGRlc2lyZWQgc2V0IG9mIHZhcmlhbnRzLgoKYGBge3J9CmNyY19maWxlIDwtIGNyY19nc3JfZmlsZSAlPiUKICBzZWxlY3QoZmlsZV9wYXRoKSAlPiUKICB1bmxpc3QoKSAlPiUKICBiYXNlbmFtZSgpCgpjcmNfY2hyMjIgPC0gcmVhZF90c3YoZmlsZS5wYXRoKCJHV0FTX0NSQyIsIGNyY19maWxlKSkgJT4lCiAgZmlsdGVyKGNocm9tb3NvbWUgPT0gMjIpCmBgYAoKV2UgbmVlZCB0byBrbm93IGlmIHRoZSBmaWxlcyBhcmUgYm90aCBpbiB0aGUgc2FtZSBnZW5vbWUgYnVpbGQgdG8gZGVjaWRlIGlmIHRoZXkgY2FuCmJlIG1lcmdlZCBhcy1pcyBvciBpZiBsaWZ0b3ZlciBpcyByZXF1aXJlZC4gVGhpcyBpbmZvcm1hdGlvbiBpcyBpbiB0aGUgYW5hbHlzaXMgdGFibGUuCgpgYGB7cn0Kc2VsZWN0KHVrYmJfYW5hbHlzaXMsIGFuYWx5c2lzX2lkLCByZWZlcmVuY2VfYXNzZW1ibHkpICU+JQogIGZpbHRlcihhbmFseXNpc19pZCAlaW4lIHVrYmJfZ3NyX2ZpbGUkYW5hbHlzaXNfaWQpCnNlbGVjdChjcmNfYW5hbHlzaXMsIGFuYWx5c2lzX2lkLCByZWZlcmVuY2VfYXNzZW1ibHkpCmBgYAoKQm90aCBhbmFseXNlcyBhcmUgaW4gcmVmZXJlbmNlIGFzc2VtYmx5IEdSQ2gzNy4gVGhpcyBtZWFucyB3ZSBjYW4gam9pbiB0aGUgR1NSIAp0YWJsZXMgb24gb3ZlcmxhcHBpbmcgdmFyaWFudHMuCgpgYGB7cn0KbnJvdyh1a2JiX2NocjIyKQpucm93KGNyY19jaHIyMikKYGBgCgpgYGB7cn0KbWVyZ2VkIDwtIGlubmVyX2pvaW4odWtiYl9jaHIyMiwgY3JjX2NocjIyLCAKICAgICAgICAgICAgICAgICAgICAgYnk9YygiY2hyb21vc29tZSIsICJwb3NpdGlvbiIsICJlZmZlY3RfYWxsZWxlIiwgIm90aGVyX2FsbGVsZSIpLCAKICAgICAgICAgICAgICAgICAgICAgc3VmZml4PWMoIl91a2JiIiwgIl9jcmMiKSkKbnJvdyhtZXJnZWQpCmhlYWQobWVyZ2VkKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmdncGxvdChtZXJnZWQsIGFlcyhiZXRhX3VrYmIsIGJldGFfY3JjKSkgKyBnZW9tX3BvaW50KCkgKyB4bGltKC0xLDEpICsgeWxpbSgtMSwxKQpgYGAKCg==