
## Installation and setup

If you want to quickly get started reading an existing Zarr array with the
package, this section should have the essentials covered.  First, we need to
install **Rarr**^[you only need to do the installation step once] with the
commands below.

```{r, installation, eval = FALSE}
## we need BiocManager to perform the installation
if (!require("BiocManager", quietly = TRUE)) {
  install.packages("BiocManager")
}
## install Rarr
BiocManager::install("Rarr")
```

Once **Rarr** is installed, we have to load it into our R session:

```{r message=FALSE}
library(Rarr)
```

**Rarr** can be used to read files either on local disk or on remote S3 storage
systems.  First lets take a look at reading from a local file.

## Reading a from a local Zarr array
To demonstrate reading a local file, we'll pick the example file containing
32-bit integers arranged in the "column first" ordering.

```{r, use-example}
zarr_example <- system.file(
  "extdata",
  "zarr_examples",
  "column-first",
  "int32.zarr",
  package = "Rarr"
)
```

### Exploring the data

We can get an summary of the array properties, such as its shape and datatype, or group properties,
using the function `zarr_overview()`^[This is essentially reading and formatting
the array metadata that accompanies any Zarr array, or the consolidated metadata if present in the case of a Zarr group.].

```{r, overview-1}
zarr_overview(zarr_example)
```

You can use this to check that the location is a valid Zarr array, and that the
shape and datatype of the array content are what you are expecting.  For
example, we can see in the output above that the data type (`int32`) corresponds
to what we expect.

### Reading the Zarr array
The summary information retrieved above is required, as to read the array with
**Rarr** you need to know the shape and size of the array (unless you want to
read the entire array).  From the previous output we can see our example array
has three dimensions of size 30 x 20 x 10.  We can select the subset we want to
extract using a `list`. The list must have the same length as the number of
dimensions in our array, with each element of the list corresponding to the
indices you want to extract in that dimension.

```{r}
index <- list(1:4, 1:2, 1)
```

We then extract the subset using `read_zarr_array()`:

```{r, extract-subset}
read_zarr_array(zarr_example, index = index)
```

## Reading from S3 storage {#read-s3}

Reading files in S3 storage works in a very similar fashion to local disk.  This
time the path needs to be a URL to the Zarr array.
We can again use `zarr_overview()` to quickly retrieve the array metadata.

```{r, read-from-s3-shown, echo = TRUE, eval = FALSE}
s3_address <- "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0076A/10501752.zarr/0"
zarr_overview(s3_address)
```

```{r, read-from-s3, echo = FALSE, eval = TRUE}
s3_address <- "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0076A/10501752.zarr/0"
s3_client <- paws.storage::s3(
  config = list(
    credentials = list(anonymous = TRUE),
    region = "auto",
    endpoint = "https://uk1s3.embassy.ebi.ac.uk"
  )
)
zarr_overview(s3_address, s3_client = s3_client)
```

The output above indicates that the array is stored in 50 chunks, each
containing a slice of the overall data. In the example below we use the `index`
argument to extract the first and tenth slices from the array. Choosing to read only
2 of the 50 slices is much faster than if we opted to download the entire array
before accessing the data.

```{r, get-slices-not-run, echo = TRUE, eval = FALSE }
z2 <- read_zarr_array(s3_address, index = list(c(1, 10), NULL, NULL))
```

```{r, get-slices, echo = FALSE, eval = TRUE }
z2 <- read_zarr_array(
  s3_address,
  index = list(c(1, 10), NULL, NULL),
  s3_client = s3_client
)
```

We then plot our two slices on top of one another using the `image()` function.

```{r, plot-raster, echo = 2:9, cache = TRUE, out.width="30%", eval = TRUE}
par(mar = c(0, 0, 0, 0))
## plot the first slice in blue
image(
  log2(z2[1, , ]),
  col = hsv(h = 0.6, v = 1, s = 1, alpha = 0:100 / 100),
  asp = dim(z2)[2] / dim(z2)[3],
  axes = FALSE
)
## overlay the tenth slice in green
image(
  log2(z2[2, , ]),
  col = hsv(h = 0.3, v = 1, s = 1, alpha = 0:100 / 100),
  asp = dim(z2)[2] / dim(z2)[3],
  axes = FALSE,
  add = TRUE
)
```

**Note:** if you receive the error message
`"Error in stop(aws_error(request$error)) : bad error message"` it is likely you
have some AWS credentials available in to your R session, which are being
inappropriately used to access this public bucket.  Please see the section
\@ref(s3-client) for details on how to set credentials for a specific
request.

## Writing to a Zarr array

Up until now we've only covered reading existing Zarr array into R.  However,
**Rarr** can also be used to write R data to disk following the Zarr
specification.  To explore this, lets create an example array we want to save as
a Zarr.  In this case it's going to be a three dimensional array and store the
values 1 to 600.

```{r, example-array}
x <- array(1:600, dim = c(10, 10, 6))
```

```{r}
path_to_new_zarr <- file.path(tempdir(), "new.zarr")
write_zarr_array(
  x = x,
  zarr_array_path = path_to_new_zarr,
  chunk_dim = c(10, 5, 1)
)
```

We can check that the contents of the Zarr array is what we're expecting.  Since
the contents of the whole array will be too large to display here, we use the
`index` argument to extract rows 6 to 10, from the 10th column and 1st slice.
That should be the values `r x[6:10, 10, 1]`, but retaining the 3-dimensional
array structure of the original array.  The second line below uses `identical()`
to confirm that reading the whole Zarr returns something equivalent to our
original input `x`.

```{r, check-written-array}
read_zarr_array(zarr_array_path = path_to_new_zarr, index = list(6:10, 10, 1))
identical(read_zarr_array(zarr_array_path = path_to_new_zarr), x)
```

