{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PICB Workflow - Jupyter Notebook"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Purpose:</b> Demonstration of the PICB workflow using a processed subset of small RNA data from Drosophila ovaries.<br>\n",
    "<b>Authors:</b> PICB Team of the Haase Lab<br>\n",
    "<b>Date:</b> 2024-12-04"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Description:</b> This script demonstrates analysis on a reduced dataset, \n",
    "Fly_Ov1_chr2L_20To21mb_filtered.bam, created from small RNA reads aligned to Drosophila melanogaster genome (Dm6). The data preparation includes trimming, filtering, mapping, and downsampling as detailed below.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Compatible Environments:</b> <br>\n",
    "✅ R versions 4.2 - 4.4 <br>\n",
    "✅ Jupyter Notebook on local machine <br>\n",
    "✅ Jupyter Notebook on an HPC <br>\n",
    "✅ IRkernel in Cursor AI (fork of VScode)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-------"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Data Preparation Context</b>\n",
    "- Processed data: Fly_Ov1_chr2L_20To21mb_filtered.bam\n",
    "- Details:\n",
    "    - Trimmed 3' adaptors, filtered reads ≥24 nt.\n",
    "    - Removed abundant cellular RNAs (rRNAs, tRNAs, snRNAs, snoRNAs).\n",
    "    - Mapped reads to Dm6 genome (chr2L:20000000-21000000) using STAR.\n",
    "    - Retained essential tags (NH, NM) and compressed BAM file.\n",
    "    - Downsampled to 22% of reads for a smaller, manageable dataset.\n",
    "    - Indexed and renamed the file.\n",
    "\n",
    "\n",
    "<b>Disclaimer:</b> The processed data is intended for demonstration purposes only and is not representative of biologically relevant samples due to extensive downsampling and regional restriction."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Additional Notes:</b>\n",
    "The R Script version of this script is available in the corresponding folder. Data preparation commands can be found on the [PICB GitHub page](https://github.com/HaaseLab/PICB)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-------"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Technical requirements "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Check R version compatibility\n",
    "message(\"Using R version: \", R.version.string)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Install required R packages from CRAN and Bioconductor\n",
    "# a. CRAN packages\n",
    "cran_packages <- c(\"data.table\", \"seqinr\", \"openxlsx\", \"dplyr\")\n",
    "if (length(setdiff(cran_packages, installed.packages()[,\"Package\"])) > 0) \n",
    "    install.packages(setdiff(cran_packages, installed.packages()[,\"Package\"])) else \n",
    "    message(\"All required CRAN packages are already installed.\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# b. Install BiocManager\n",
    "if (!require(\"BiocManager\", quietly = TRUE)) install.packages(\"BiocManager\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# c. Install Bioconductor packages\n",
    "bio_packages <- c(\"BiocManager\", \"IRanges\", \"GenomicRanges\", \"GenomicAlignments\", \"Rsamtools\", \"Biostrings\", \"Seqinfo\", \"BSgenome\", \"rtracklayer\")\n",
    "if (length(setdiff(bio_packages, installed.packages()[,\"Package\"])) > 0) \n",
    "    BiocManager::install(setdiff(bio_packages, installed.packages()[,\"Package\"]), ask = FALSE) else \n",
    "    message(\"All required Bioconductor packages are already installed.\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Install PICB "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Select one of the following installation methods for the PICB package:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Uncomment the preferred method.\n",
    "\n",
    "# devtools::install_github(\"HaaseLab/PICB\")\n",
    "# remotes::install_github(\"HaaseLab/PICB\")\n",
    "# install.packages(\"../PICB\", repos = NULL, type = \"source\")\n",
    "# Use terminal to clone and build if required:\n",
    "# git clone https://github.com/HaaseLab/PICB.git"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Load PICB package\n",
    "library(\"PICB\") "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Core-PICB"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load the reference genome"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Provide reference genome (just run 1 option)\n",
    "# a. Install and load a BSgenome\n",
    "# BiocManager::install(\"BSgenome.Dmelanogaster.UCSC.dm6\")\n",
    "library(\"BSgenome.Dmelanogaster.UCSC.dm6\")\n",
    "myGenome <- \"BSgenome.Dmelanogaster.UCSC.dm6\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Other options to load the reference genome"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "{     \"tags\": [         \"hide-cell\"     ] }"
    ],
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# b. Provide a Seqinfo object containing the chromosome names and lengths according to the BAM file.\n",
    "myGenome <- Seqinfo::Seqinfo(\n",
    "    seqnames = c(\"chr2L\", \"chr2R\", \"chr3L\", \"chr3R\", \"chr4\", \"chrX\", \"chrY\"),\n",
    "    seqlengths = c(23513712, 25286936, 28110227, 32079331, 1348131, 23542271, 3667352)\n",
    ")\n",
    "# c. Provide supported genome as Seqinfo object.\n",
    "myGenome <- Seqinfo::Seqinfo(genome = \"dm6\")\n",
    "# d. Provide a fasta file containing the reference genome sequence.\n",
    "myGenome <- PICBloadfasta(\"dm6.fa\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load mapped piRNA data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Load the demo BAM file and process it into GRanges format\n",
    "bam_file <- system.file(\"extdata\", \"Fly_Ov1_chr2L_20To21mb_filtered.bam\", package = \"PICB\")\n",
    "myAlignments <- PICBload(\n",
    "    BAMFILE = bam_file,\n",
    "    REFERENCE.GENOME = myGenome\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build piRNA clusters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Run PICBbuild to construct piRNA clusters.\n",
    "myClusters <- PICBbuild(\n",
    "    IN.ALIGNMENTS = myAlignments,\n",
    "    REFERENCE.GENOME = myGenome,\n",
    "    LIBRARY.SIZE = 12799826\n",
    ")$clusters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Note:</b> Library size usually doesn't need to be set, but we are dealing with a sample that does not contain all reads, so normalization is altered."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Optimize PICB parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "parameterExploration <- PICBoptimize(\n",
    "    IN.ALIGNMENTS = myAlignments,\n",
    "    REFERENCE.GENOME = myGenome,\n",
    "    MIN.UNIQUE.ALIGNMENTS.PER.WINDOW = c(1, 2, 3, 4, 5),\n",
    "    LIBRARY.SIZE = 12799826,\n",
    "    VERBOSITY = 2\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Note:</b> Expect a warning due to the modified LIBRARY.SIZE, which does not match the number of reads in IN.ALIGNMENTS."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "parameterExploration"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A thorough parameter exploration for a subset of alignments is not particularly useful here. Nevertheless, we provide the code below to visualize the exploration of different values for MIN.UNIQUE.ALIGNMENTS.PER.WINDOW for the reads (\"library\") and the genome space covered by piRNA clusters."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Visualize parameter optimization results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "library(ggplot2)\n",
    "#Specify parameter to optimize for.\n",
    "x_column <- \"MIN.UNIQUE.ALIGNMENTS.PER.WINDOW\" # change parameter to optimize, if applicable\n",
    "\n",
    "# Determine a scaling factor for the secondary axis\n",
    "scaling_factor <- max(parameterExploration$fraction.of.library.explained.by.clusters) / max(parameterExploration$fraction.of.genome.space.clusters)\n",
    "\n",
    "# plot graph\n",
    "ggplot(parameterExploration, aes(x = .data[[x_column]])) +\n",
    "    geom_line(aes(y = fraction.of.library.explained.by.clusters * 100, color = \"piRNAs Explained\"), linewidth = 1) +\n",
    "    geom_point(aes(y = fraction.of.library.explained.by.clusters * 100, color = \"piRNAs Explained\"), size = 3) +\n",
    "    geom_line(aes(y = fraction.of.genome.space.clusters * scaling_factor * 100, color = \"Genome Space\"), linewidth = 1) +\n",
    "    geom_point(aes(y = fraction.of.genome.space.clusters * scaling_factor * 100, color = \"Genome Space\"), size = 3) +\n",
    "    scale_y_continuous(name = \"piRNAs Explained by Clusters (%, piRNA sample)\", sec.axis = sec_axis(~ . / scaling_factor, name = \"Total piRNA cluster-length (Genome, %)\")) +\n",
    "    scale_x_reverse(name = paste0(\"Parameter chosen: \", x_column), breaks = parameterExploration[[x_column]], labels = parameterExploration[[x_column]]) +\n",
    "    scale_color_manual(name = \"Metrics\", values = c(\"piRNAs Explained\" = \"#00a100\", \"Genome Space\" = \"black\")) +\n",
    "    theme_classic() +\n",
    "    theme(axis.title.y.left = element_text(color = \"#00a100\"), axis.title.y.right = element_text(color = \"black\"), legend.position = \"top\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If needed modify paramater(s) in PICBbuild (not needed for the PICB-demonstration)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dealing with the results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Rank piRNA clusters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# one option is to rank by primary alignments FPM:\n",
    "library(GenomicRanges)\n",
    "myClusters <- myClusters[order(-mcols(myClusters)$all_reads_primary_alignments_FPM)]\n",
    "mcols(myClusters)$rank_all_reads_primary_alignments_FPM <- rank(-mcols(myClusters)$all_reads_primary_alignments_FPM)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Export results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# RDS format \n",
    "saveRDS(myClusters, file=\"clusters_PICB_demo.RDS\")\n",
    "# Microsoft Excel format\n",
    "PICBexporttoexcel(IN.RANGES = myClusters, EXCEL.FILE.NAME = \"clusters_PICB_demo.xlsx\")\n",
    "# GTF format \n",
    "myClusters$transcript_id <- paste0(\"PICB_ rank_\", myClusters$rank_all_reads_primary_alignments_FPM)\n",
    "rtracklayer::export(myClusters, \"clusters_PICB_demo.gtf\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "codemirror_mode": "r",
   "file_extension": ".r",
   "mimetype": "text/x-r-source",
   "name": "R",
   "pygments_lexer": "r",
   "version": "4.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
