---
title: "Getting Started with the Epoch Package"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{vignette}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
    collapse = TRUE,
    comment = "#>",
    eval = TRUE,
    fig.align = "center",
    fig.width = 6,
    fig.height = 4
)
library(Epoch)
```

# Introduction

The Epoch package provides tools for downloading, manipulating, and analyzing intracranial EEG (iEEG) epoch data. This vignette will guide you through the main features of the package, from downloading data using `EpochDownloader` to manipulating and visualizing `Epoch` objects.

# Using the EpochDownloader

The `EpochDownloader` class is your gateway to accessing iEEG data. You can create a downloader using either a project name or a direct OSF project ID. We provide `fragility` and `kData` projects from UTMB as predefined projects for seizure onset prediction analysis. You can list all available projects via `EpochRepos()`.
```{r list_projects}
EpochRepos()
```

The `EpochRepos()` function returns a list of available projects, with name as the project name and value as the OSF project ID. `id` argument in `EpochDownloader()` accept either the project name or the OSF project ID. The default is `fragility` project if `id` is not specified.

```{r downloader_predefined}
downloader <- EpochDownloader(progress=FALSE)
downloader
```


## Exploring Available Data Files
The downloader works like a list object in R. Once you have a downloader, you can explore what data files are available using `names()`
```{r explore_data}
names(downloader)
```

## Loading Data into Epoch Objects

Now you can load specific datasets into `Epoch` objects using `$`, `[[]]`, or `[]` operators. The downloader will automatically handle the download and conversion of raw data files into `Epoch` objects. `$` and `[[]]` will return a single `Epoch` object, while `[]` will return a list of `Epoch` objects.

## Loading a Single Dataset

```{r load_single}
# Load the first available dataset
epoch_data <- downloader$FragilityData_subpt01_1

epoch_data
```

## Loading Multiple Datasets

```{r load_multiple}
# Load two datasets
selected_data <- c("FragilityData_subpt01_1", "FragilityData_subpt01_2")
epoch_list <- downloader[selected_data]

epoch_list
```


## Data Dictionary
To understand the definition of each variable in the metadata, you can call `wiki()` on the EpochDownloader object. This will bring you to the OSF wiki page associated with the project
```{r, eval=FALSE}
wiki(downloader)
```


# Working with Epoch Objects

Once you have loaded data into `Epoch` objects, you can manipulate and analyze them.

## Understanding Epoch Structure
The `Epoch` object is a matrix-like structure where rows represent electrodes and columns represent time points. The main advantage of using `Epoch` objects is that they encapsulate both the data and row, column, and table metadata, making it easier to work with iEEG data in R.

```{r epoch_structure}
# Assuming we have an epoch object from previous steps
epoch <- epoch_data  # or epoch_list[[1]] if you loaded multiple

print(epoch) 
```

## Plotting Epoch Data
You can directly visualize the `Epoch` object using the `plot()` function. This will create a time series plot for each electrode.
```{r}
plot(epoch)
```

## Basic Information
The `Epoch` object behaves like a matrix, so you can access its dimensions and data structure easily.
```{r}
# Basic information
dim(epoch)  # dimensions: electrodes x time points
nrow(epoch)  # number of electrodes
ncol(epoch)  # number of time points
rownames(epoch)  # electrode names
range(coltimes(epoch))  # time points range (colnames work but will return character vector)

# Access the underlying data
data_matrix <- tblData(epoch)
data_matrix[1:5, 1:5]
```

## Accessing metadata
`Epoch` objects contain metadata that provides context for the data. You can access this metadata using `rowData()`, `colData()`, and `metaData()` functions. 
```{r metadata}
# Access row metadata (electrode information)
electrode_info <- rowData(epoch)
print(electrode_info)

# Access column metadata (there is no column metadata in this example)
time_info <- colData(epoch)
print(time_info)

# Access general metadata
meta_info <- metaData(epoch)
str(meta_info)
```

## Subsetting Epoch Data
You can subset `Epoch` objects to focus on specific electrodes or time points. 

### Select specific electrodes

You can use the electrode indices to select the first 3 electrodes
```{r}
epoch[1:3, ]
```

Alternatively, you can select by names

```{r}
electrode_names <- rownames(epoch)[1:3]
epoch[electrode_names, ]
```

You can also select electrode using a list-like syntax
```{r}
epoch[electrode_names]
```

### Select specific time points

You can directly subset the `Epoch` object by time indices
```{r}
epoch[, 1:100]
```

However, it makes more sense to use the time range to subset the data. The `crop()` function allows you to specify a time range (in seconds) for subsetting.
```{r}
crop(epoch, start = -0.5, end = 1.5)
```

## Resampling Epoch Data
You can resample the `Epoch` data to a different sampling rate using the `resample()` function. This is useful for aligning data from different sources or for reducing the data size.
```{r resample_epoch}
# Resample to 250 Hz
resampled_epoch <- resample(epoch, samplingRate = 250)
resampled_epoch
```




# Creating Custom Epoch Objects

You can also create your own `Epoch` objects from scratch. We first define the table data.
```{r create_epoch}
# Create sample iEEG-like data
n_electrodes <- 10
n_timepoints <- 1000
sampling_rate <- 500  # Hz
start_time <- -0.5    # seconds

# Generate synthetic data
synthetic_data <- matrix(
  rnorm(n_electrodes * n_timepoints), 
  nrow = n_electrodes, 
  ncol = n_timepoints
)

# Create electrode names
electrode_names <- paste0("Electrode_", sprintf("%02d", 1:n_electrodes))
```

To give more context to the data, we can define its row, column, and general metadata. 
```{r add_metadata}
# Create electrode metadata
electrode_metadata <- data.frame(
  electrode_id = electrode_names,
  brain_region = rep(c("Frontal", "Temporal", "Parietal"), length.out = n_electrodes),
  hemisphere = rep(c("Left", "Right"), length.out = n_electrodes),
  depth = runif(n_electrodes, 10, 50),  # depth in mm
  stringsAsFactors = FALSE
)

# Create time metadata
time_points <- seq(start_time, by = 1/sampling_rate, length.out = n_timepoints)
time_metadata <- data.frame(
  epoch_phase = ifelse(time_points < 0, "pre_stimulus", "post_stimulus"),
  stringsAsFactors = FALSE
)

# Create general metadata
general_metadata <- list(
  subject_id = "SUB001",
  session = "Session1",
  task = "Memory Task",
  sampling_rate = sampling_rate,
  recording_date = Sys.Date()
)

```

Lastly, we can create the `Epoch` object using the `Epoch()` constructor. 
```{r}
comprehensive_epoch <- Epoch(
  table = synthetic_data,
  electrodes = electrode_names,
  startTime = start_time,
  samplingRate = sampling_rate,
  rowData = electrode_metadata,
  colData = time_metadata,
  metaData = general_metadata
)

comprehensive_epoch
```
