---
# System prepended metadata

title: 'Getting started to use HPC (Hive) :bee:'

---

Getting started to use HPC (Hive) :bee:
===


```notes:

```

<div style="
  width: 100%;
  padding: 4rem 2rem;
  background: #f9fafb;
  text-align: center;
  font-family: 'Segoe UI', Arial, sans-serif;
  border-bottom: 4px solid #2563eb;
">
  <h1 style="
    margin: 0;
    font-size: 4rem;
    font-weight: 800;
    color: #111827;
    line-height: 1.1;
  ">
    Dennis Lab Meeting
  </h1>
  <p style="
    margin: 1rem 0 0;
    font-size: 2rem;
    font-weight: 500;
    color: #374151;
  ">
    Thu, Aug 14, 2025
  </p>
  <p style="
    margin: 0.5rem 0;
    font-size: 1.6rem;
    color: #4b5563;
  ">
    <strong>By:</strong> Mohamed Abuelanin
  </p>
  <p style="
    margin: 0.5rem 0;
    font-size: 1.4rem;
  ">
    <a href="mailto:mahussien@ucdavis.edu" style="
      color: #2563eb;
      text-decoration: none;
      border-bottom: 2px solid rgba(37, 99, 235, 0.3);
    " onmouseover="this.style.borderBottomColor='rgba(37,99,235,1)';" onmouseout="this.style.borderBottomColor='rgba(37,99,235,0.3)';">
      mahussien@ucdavis.edu
    </a>
  </p>
</div>


# 1. What is HPC?

## 1.1 Organization overview

![image](https://hackmd.io/_uploads/r1lYZUKuxx.png)

## 1.2 How storage actually works? (Quobyte)

**- NFS, parallel IO**

![image](https://hackmd.io/_uploads/H1h1U9tule.png)


## 1.3 Slurm

![image](https://hackmd.io/_uploads/B1yc2cFOgl.png)


## 1.4 SSH
![image](https://hackmd.io/_uploads/HklUljK_lg.png)


## 1.5 HIPPO

![image](https://hackmd.io/_uploads/B1CZJUtuee.png)


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 2. Understanding the Shell Environment


## 2.1 What is a Shell? 🐚

A **shell** is a program that takes your commands and gives them to the operating system to perform. It's the primary way you interact with a command-line interface.

**Analogy:** Think of the shell as a translator between you and the computer's core (the kernel).

* **You type:** `ls -l` (a command to list files).
* **The Shell interprets** this and asks the kernel for the file list.
* **The Kernel provides** the list, and the shell displays it for you.

The most common shell is **bash**.

```mermaid
graph TD
    subgraph "How a Command Works"
        User -- "Types 'ls -l'" --> Shell;
        Shell -- "Asks for file list" --> Kernel;
        Kernel -- "Returns file list" --> Shell;
        Shell -- "Displays output" --> User;
    end
````

## 2.2 What are Shell Configuration Files?

When a shell starts, it runs special scripts to set up your environment. These are called configuration files (or "dotfiles" because their names start with a dot, like `.bashrc`).

You use them to customize your command-line world:

  * **Aliases:** Create shortcuts for long commands (e.g., `alias ll='ls -alF'`).
  * **Environment Variables:** Set important variables like `$PATH`, which tells the shell where to find programs.


## 2.3 Login vs. Interactive Shells

To understand which file gets used, you need to know the difference between two types of shells:

1.  **Login Shell:** This is the *first* shell session that starts after you authenticate.
      * **Example:** When you log in to a server with **SSH**.
2.  **Interactive Non-Login Shell:** This is any *new* shell you start from an existing session.
      * **Example:** Opening a new terminal window on your desktop, or typing `bash` inside your SSH session.

This distinction is the key to why we have different configuration files.

```mermaid
graph TD
    subgraph "Which Shell Am I?"
        A(User Action) --> B{Is this the initial login?};
        B -- "Yes (e.g., SSH)" --> C[Starts a LOGIN shell];
        B -- "No (e.g., new terminal tab)" --> D[Starts an INTERACTIVE NON-LOGIN shell];
    end
```


## 2.4 `.bash_profile` vs. `.bashrc`

Bash uses two main files for interactive shells:

### `~/.bash_profile`

  * **When it runs:** **Only once**, when you start a **login shell** (e.g., `ssh`).
  * **Purpose:** For things that only need to be set up once per session. The most important is the `PATH` environment variable.

### `~/.bashrc`

  * **When it runs:** For **every new interactive non-login shell**.
  * **Purpose:** For things you want in every terminal, like aliases and prompt settings.

**The Common Trick:** To make sure your aliases are available everywhere, most `.bash_profile` files are set up to automatically run `.bashrc`.

```bash
# Inside ~/.bash_profile
if [ -f ~/.bashrc ]; then
   source ~/.bashrc
fi
```



## 2.5 The HPC Login Process

Here’s what happens step-by-step when you connect to an HPC cluster using Bash.

```mermaid
%%{init: { "theme": "base", "themeVariables": { "lineColor": "#26A69A" }}}%%
flowchart TB
    A["You — local terminal"]:::you --> B["ssh your_user\@hive.hpc.ucdavis.edu"]:::action
    B --> C["Login node<br>hive.hpc.ucdavis.edu"]:::login
    C --> D{"Authenticate<br>(key or password)"}:::decision
    D -->|ok| E["Bash starts<br>login shell"]:::bash
    E --> F["Run ~/.bash_profile"]:::file
    F --> G["Source ~/.bashrc<br>(from .bash_profile)"]:::file
    G --> H["Prompt ready"]:::done

    %% Alternative path (non-login shell)
    subgraph ALT["Non-login shell"]
      I["srun --pty bash<br>(or new terminal tab)"]:::action --> J["Bash starts<br>non-login shell"]:::bash
      J --> K["Run ~/.bashrc only"]:::file
    end
    K --> H

    %% Styles
    classDef you fill:#D1F2EB,stroke:#48C9B0,color:#0E6251,stroke-width:2px;
    classDef login fill:#E3F2FD,stroke:#42A5F5,color:#0D47A1,stroke-width:2px;
    classDef action fill:#FFF3E0,stroke:#FB8C00,color:#7D6608,stroke-width:2px;
    classDef decision fill:#FDEDEC,stroke:#E57373,color:#B71C1C,stroke-width:2px;
    classDef bash fill:#E8EAF6,stroke:#5C6BC0,color:#283593,stroke-width:2px;
    classDef file fill:#F3E5F5,stroke:#AB47BC,color:#4A148C,stroke-width:2px;
    classDef done fill:#E8F5E9,stroke:#66BB6A,color:#1B5E20,stroke-width:2px;
```

1) **Connect**
   ```bash
   ssh your_user@hive.hpc.ucdavis.edu
   ```
2) **Authenticate** on the **login node**.
3) **Login shell starts** (Bash is a *login* shell).
4) **`~/.bash_profile` runs.**
5) **`~/.bashrc` is sourced** (your `~/.bash_profile` should call it).
6) **Prompt ready** — you’re in a configured environment.

----


## 2.6 Use Case: Relocating Your Home Environment

**Problem:**  
Our default home directory (for example, my home directory is `/home/mabuelanin`) is on a small 20GB drive. Programs like Conda, VS Code Server, and package managers install lots of data there, causing it to fill up. You need these programs to use your group's large 400TB drive (`/quobyte/mydennisgrp/mabuelanin`) as their "home".

**Solution:**  
Change the `$HOME` environment variable. This tells all programs where your home is. This requires careful setup to avoid breaking your login process.

---

### Step 1: Prepare Your New Home

:::info
**IMPORTANT – DO THIS ONCE:**  
Before changing your `.bash_profile`, you must copy your existing configuration files to the new location. This ensures your shell and other programs can find them after `$HOME` is changed.
:::

Run this command directly in your terminal **once**:

```bash
# Copies all dotfiles (like .bashrc, .vimrc, etc.) to your new home.
# The -a flag preserves permissions and timestamps.
cp -a /home/mabuelanin/.[a-zA-Z0-9]* /quobyte/mydennisgrp/mabuelanin/
```

---

### Step 2: Modify `.bash_profile`

Open your **original** profile at `/home/mabuelanin/.bash_profile` and add/change the following lines:

```bash
# Relocate HOME to the large project directory
export HOME=/quobyte/mydennisgrp/mabuelanin

# Source the .bashrc from the NEW home directory
# "$HOME/.bashrc" now points to the new location
if [ -f "$HOME/.bashrc" ]; then
    source "$HOME/.bashrc"
fi

# Change directory to the new home
cd "$HOME"
```

---

### Result

- When you log in, your shell will set `$HOME` to the new, larger directory.  
- The `~` shortcut will now point to `/quobyte/mydennisgrp/mabuelanin`.  
- Programs like Conda and VS Code will install their files and caches in this new location, solving your storage problem.  
- You will start your session inside the new home directory.  

<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 3. Slurm Overview

Slurm is the job scheduler used on the cluster. You interact with it to submit jobs, request resources, and monitor their progress. Jobs can be run **interactively** (directly from the terminal) or as **batch jobs** (submitted scripts).

---

## 3.1 Interactive Jobs

Interactive jobs are useful for debugging, testing small workloads, or running interactive programs like Jupyter Notebook.

Example:  
```bash
srun --account=mydennisgrp --partition=high \
     --cpus-per-task=4 --mem=16G --time=01:00:00 \
     --pty bash
```

**Key points:**  
- `--pty bash` starts an interactive shell on the allocated node.  
- Release the node when done by typing `exit`.  

---

## 3.2 Batch Jobs with `sbatch`

Batch jobs run in the background without an active terminal connection. They are ideal for long or unattended jobs.

**Example template:**

```bash
#!/bin/bash
#SBATCH --job-name=myjob
#SBATCH --account=mydennisgrp
#SBATCH --partition=high
#SBATCH --cpus-per-task=4
#SBATCH --mem=16G
#SBATCH --time=02:00:00
#SBATCH --output=logs/%x_%j.out    # STDOUT
#SBATCH --error=logs/%x_%j.err     # STDERR
#SBATCH --mail-type=END,FAIL       # Email notifications
#SBATCH --mail-user=youremail@ucdavis.edu

# Optional: create logs directory if it doesn't exist
mkdir -p logs

# Load Conda properly inside Slurm
# Auto-detect the base conda path for the current user
CONDA_BASE=$(conda info --base)
. "$CONDA_BASE/etc/profile.d/conda.sh"

# Activate a specific environment (change 'myenv' as needed)
conda activate myenv

# Your command(s) here
python myscript.py --input data.txt

```

**How to submit:**
```bash
sbatch myjob.sh
```

---

## 3.3 Background Terminals with `screen`

Sometimes you need to keep a session alive after disconnecting (e.g., to monitor logs or run an interactive session).  

`screen` is a terminal multiplexer that lets you detach and reattach to sessions.

**Basic commands:**

```bash
# Start a new screen session
screen -S mysession

# Detach from the session (keep it running)
Ctrl + A, then D

# List existing sessions
screen -ls

# Reattach to a session
screen -r mysession

# Kill a session
screen -X -S mysession quit
```

<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">



# 4. Different Types of Accounts and Partitions

Below is an overview of the accounts and partitions available for **our lab**.

```mermaid
flowchart TD
    %% ========= NODES =========
    A["Accounts"] --> B["mydennisgrp"]
    A --> C["publicgrp"]
    A --> D["genome-center-grp"]

    %% mydennisgrp (Dedicated)
    B --> B_high["high"]
    B_high --> B_cpu["128 CPUs<br>1000 GB RAM<br>Dedicated Tecate node"]

    %% publicgrp (Shared)
    C --> C_high["high"]
    C --> C_low["low"]

    %% (UPDATED) publicgrp: no GPU block under 'high'
    C_high --> C_cpu["128 CPUs<br>2000 GB RAM"]

    %% publicgrp: low still shows CPU + GPU (scavenged resources)
    C_low --> C_cpu_low["Unused cluster CPUs & RAM<br>(3 days max / 1 node)"]
    C_low --> C_gpu_low["Unused cluster GPUs"]

    %% genome-center-grp (Shared)
    D --> D_high["high"]
    D --> D_gpu_a100["gpu-a100"]

    D_high --> D_cpu["616 CPUs<br>9856 GB RAM"]
    D_gpu_a100 --> D_gpu_a100_cpu["128 CPUs<br>2000 GB RAM"]
    D_gpu_a100 --> D_gpu_a100_gpu["8 GPUs (A100)"]

    %% ========= STYLES =========
    %% Accounts
    classDef acctPrivate fill:#E8F5E9,stroke:#66BB6A,stroke-width:2px,color:#1B5E20;
    classDef acctShared  fill:#E3F2FD,stroke:#42A5F5,stroke-width:2px,color:#0D47A1;

    %% Partitions
    classDef part fill:#FFF3E0,stroke:#FB8C00,stroke-width:1.5px,color:#E65100;

    %% Resource nodes
    classDef cpu fill:#F3E5F5,stroke:#AB47BC,stroke-width:1.5px,color:#4A148C;
    classDef gpu fill:#FCE4EC,stroke:#EC407A,stroke-width:1.5px,color:#880E4F;

    %% Apply classes
    class B acctPrivate;
    class C,D acctShared;

    class B_high,C_high,C_low,D_high,D_gpu_a100 part;

    class B_cpu,C_cpu,C_cpu_low,D_cpu,D_gpu_a100_cpu cpu;
    class C_gpu_low,D_gpu_a100_gpu gpu;
```


## Example `srun` Commands

The following are interactive job examples for each **account → partition → resource** combination.  
Each example includes the **maximum per-job limits** allowed by Slurm for that combination.  
Default runtime here is short (`--time=00:05:00`) for quick testing.

---

### mydennisgrp → high
<div style="display:flex; gap:8px; margin:6px 0;">
  <div style="background-color:#D1F2EB; color:#0E6251; padding:8px 10px; border:1px solid #48C9B0; border-radius:8px; flex:1;">
    <b>mydennisgrp (Dedicated)</b>
  </div>
  <div style="background-color:#FCF3CF; color:#7D6608; padding:8px 10px; border:1px solid #F7DC6F; border-radius:8px; flex:1;">
    <b>Partition: high</b>
  </div>
  <div style="background-color:#E8DAEF; color:#4A235A; padding:8px 10px; border:1px solid #BB8FCE; border-radius:8px; flex:2;">
    128 CPUs · 1000 GB RAM · Dedicated Tecate node
  </div>
</div>

**Max per job:** 128 CPUs · 1000 GB RAM · No GPU  
```bash
srun --account=mydennisgrp --partition=high \
     --cpus-per-task=4 --mem=16G --time=00:05:00 \
     --pty bash
```

---

### publicgrp → high
<div style="display:flex; gap:8px; margin:6px 0;">
  <div style="background-color:#D6EAF8; color:#154360; padding:8px 10px; border:1px solid #5DADE2; border-radius:8px; flex:1;">
    <b>publicgrp (Shared)</b>
  </div>
  <div style="background-color:#FCF3CF; color:#7D6608; padding:8px 10px; border:1px solid #F7DC6F; border-radius:8px; flex:1;">
    <b>Partition: high</b>
  </div>
  <div style="background-color:#E8DAEF; color:#4A235A; padding:8px 10px; border:1px solid #BB8FCE; border-radius:8px; flex:2;">
    128 CPUs · 2000 GB RAM
  </div>
</div>

**Max per job:** 8 CPUs · 128 GB RAM · No GPU  
```bash
srun --account=publicgrp --partition=high \
     --cpus-per-task=8 --mem=128G --time=00:05:00 \
     --pty bash
```

---

### publicgrp → low
<div style="display:flex; gap:8px; margin:6px 0;">
  <div style="background-color:#D6EAF8; color:#154360; padding:8px 10px; border:1px solid #5DADE2; border-radius:8px; flex:1;">
    <b>publicgrp (Shared)</b>
  </div>
  <div style="background-color:#FDEDEC; color:#641E16; padding:8px 10px; border:1px solid #F1948A; border-radius:8px; flex:1;">
    <b>Partition: low</b>
  </div>
  <div style="background-color:#E8DAEF; color:#4A235A; padding:8px 10px; border:1px solid #BB8FCE; border-radius:8px; flex:2;">
    Scavenged CPUs · Runtime max: 3 days · 1 node
  </div>
</div>

**Max per job:** 1 node · 3 days runtime · No guaranteed resources  
```bash
srun --account=publicgrp --partition=low \
     --cpus-per-task=4 --mem=16G --time=01:00:00 \
     --pty bash
```

---

### genome-center-grp → high
<div style="display:flex; gap:8px; margin:6px 0;">
  <div style="background-color:#D6EAF8; color:#154360; padding:8px 10px; border:1px solid #5DADE2; border-radius:8px; flex:1;">
    <b>genome-center-grp (Shared)</b>
  </div>
  <div style="background-color:#FCF3CF; color:#7D6608; padding:8px 10px; border:1px solid #F7DC6F; border-radius:8px; flex:1;">
    <b>Partition: high</b>
  </div>
  <div style="background-color:#E8DAEF; color:#4A235A; padding:8px 10px; border:1px solid #BB8FCE; border-radius:8px; flex:2;">
    616 CPUs · 9856 GB RAM
  </div>
</div>

**Max per job:** (Check with `sacctmgr show qos format=name,grace,maxtres`)  
```bash
srun --account=genome-center-grp --partition=high \
     --cpus-per-task=16 --mem=256G --time=00:30:00 \
     --pty bash
```

---

## GPU-Capable Partitions

:::danger
**Warning:**  
Running on a GPU partition **without** `--gres=gpu:<type>:<count>` will still use a GPU node but leave the GPUs idle, wasting resources.
:::

---

### genome-center-grp → gpu-a100
<div style="display:flex; gap:8px; margin:6px 0;">
  <div style="background-color:#D6EAF8; color:#154360; padding:8px 10px; border:1px solid #5DADE2; border-radius:8px; flex:1;">
    <b>genome-center-grp (Shared)</b>
  </div>
  <div style="background-color:#EBDEF0; color:#512E5F; padding:8px 10px; border:1px solid #AF7AC5; border-radius:8px; flex:1;">
    <b>Partition: gpu-a100</b>
  </div>
  <div style="background-color:#FDEDEC; color:#641E16; padding:8px 10px; border:1px solid #F1948A; border-radius:8px; flex:2;">
    8 GPUs (A100)
  </div>
</div>

**CPU-only example:**
```bash
srun --account=genome-center-grp --partition=gpu-a100 \
     --cpus-per-task=4 --mem=16G --time=00:30:00 \
     --pty bash
```

**GPU example:**
```bash
srun --account=genome-center-grp --partition=gpu-a100 \
     --gres=gpu:a100:1 \
     --cpus-per-task=4 --mem=16G --time=00:30:00 \
     --pty bash
```


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">



# 5. OnDemand (web access)

https://ondemand.hive.hpc.ucdavis.edu/

## What OnDemand Provides
- File browser and editor
- Interactive applications (Jupyter, RStudio, desktop environments)
- Job submission and monitoring interfaces
- No SSH knowledge required

![image](https://hackmd.io/_uploads/rkSIs9cOxx.png)


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">



# 6. Preinstalled HPC Modules

Most software on the cluster is provided through the **Environment Modules** system (`module` command).  
These modules let you load, unload, and switch between different versions of installed software without changing your shell configuration.

---

**Listing available modules**
```bash
module avail
```
This will print all available modules. You can narrow the search:
```bash
module avail python
module avail gcc
```



**Loading a module**
```bash
module load python/3.11.4
```
Once loaded, the software is available in your `$PATH`.  
To verify:
```bash
which python
python --version
```



**Unloading a module**
```bash
module unload python/3.11.4
```



**Switching versions**
```bash
module swap python/3.9.16 python/3.11.4
```



**Viewing loaded modules**
```bash
module list
```

---

:::info
**Tip:**  
Some core tools (e.g., `gcc`, `openmpi`, `cuda`) are only available after loading the corresponding module.  
If a command is “not found,” try searching with `module avail`.
:::

<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 7. Utilizing the Scratch Directory

Heavy I/O (lots of small writes / temporary files) can overwhelm shared filesystems and slow everyone down.  
Use each compute node’s **local NVMe scratch** for temporary data during jobs, then copy results back to shared storage when done.

---

**Why scratch?**
- **NVMe local disks** → very high IOPS & throughput (perfect for many small temporary files or random access patterns).
- **Reduces contention** on shared storage (your `$HOME`, group drives).
- **Ephemeral**: you clean up at the end; nothing is backed up.

---

## 7.1 Architecture at a glance

```mermaid
flowchart LR
    %% --- Nodes ---
    L["Login Node<br>Interactive prep"]:::login

    subgraph CA["Compute Node A"]
      SA["Local NVMe Scratch<br>/scratch/$USER or $TMPDIR"]:::scratch
    end

    subgraph CB["Compute Node B"]
      SB["Local NVMe Scratch<br>/scratch/$USER or $TMPDIR"]:::scratch
    end

    H["Shared Storage<br>$HOME / group shares"]:::shared

    %% --- Edges (minimal, non-overlapping) ---
    L --> CA
    L --> CB
    L --> H
    CA --> H
    CB --> H

    %% --- Styles ---
    classDef login fill:#D6EAF8,stroke:#5DADE2,stroke-width:2px,color:#154360;
    classDef shared fill:#E8EAF6,stroke:#5C6BC0,stroke-width:2px,color:#283593;
    classDef scratch fill:#FDEDEC,stroke:#E57373,stroke-width:2px,color:#B71C1C;
```


**Explanation**
- Use **shared storage** to **stage inputs** and **save final outputs**.
- During the job, write temp files to the **node-local NVMe scratch** (fast, isolated).
- Each node has its **own** scratch; data on `Compute Node A` isn’t visible on `Compute Node B`.

---

## 7.2 Practical usage patterns

**Check what scratch env var you have**
```bash
echo "TMPDIR=${TMPDIR:-unset}"
echo "NODE scratch exists?"; ls -ld /scratch/$USER 2>/dev/null || echo "no /scratch/$USER"
```

**Create a per-job scratch directory and auto-cleanup**
```bash
# Inside your job script or interactive srun session
SCRATCH_BASE="${TMPDIR:-/scratch/$USER}"
JOB_SCRATCH="$(mktemp -d "${SCRATCH_BASE}/job_${SLURM_JOB_ID:-manual}_XXXX")"
echo "Using scratch: $JOB_SCRATCH"

# Cleanup on exit (even if job fails)
cleanup() { rm -rf "$JOB_SCRATCH"; }
trap cleanup EXIT
```

**Stage inputs → run → stage outputs**
```bash
# 1) Copy inputs from shared storage to scratch
cp /path/to/shared/input.dat "$JOB_SCRATCH/"

# 2) Run the workload from scratch
cd "$JOB_SCRATCH"
mytool --in input.dat --out result.bin

# 3) Copy outputs back to shared storage
mkdir -p /path/to/shared/results/${SLURM_JOB_ID:-manual}
rsync -a result.bin /path/to/shared/results/${SLURM_JOB_ID:-manual}/
```

**Monitor space / speed**
```bash
df -h "$JOB_SCRATCH"
```

---

## 7.3 Slurm examples that favor scratch


**SBATCH template using node-local NVMe scratch**
```bash
#!/bin/bash
#SBATCH --job-name=scratch_demo
#SBATCH --account=mydennisgrp
#SBATCH --partition=high
#SBATCH --cpus-per-task=8
#SBATCH --mem=32G
#SBATCH --time=02:00:00
#SBATCH --output=logs/%x_%j.out
#SBATCH --error=logs/%x_%j.err


# Setup job scratch
SCRATCH_BASE="${TMPDIR:-/scratch/$USER}"
JOB_SCRATCH="$(mktemp -d "${SCRATCH_BASE}/job_${SLURM_JOB_ID}_XXXX")"
cleanup(){ rm -rf "$JOB_SCRATCH"; }
trap cleanup EXIT

echo "Job scratch: $JOB_SCRATCH"
cp /shared/inputs/data.tar "$JOB_SCRATCH/"
cd "$JOB_SCRATCH"
tar xf data.tar

# Run your I/O-heavy workload here
my_pipeline.sh > pipeline.log 2>&1

# Save results back to shared storage
mkdir -p /shared/outputs/${SLURM_JOB_ID}
rsync -a . /shared/outputs/${SLURM_JOB_ID}/ --include='*.out' --include='*.log' --exclude='*'

# Cleanup happens via trap
```

---

## 7.4 Best practices

- **Write temp files to scratch**, not `$HOME` or group shares.
- **One job → one scratch dir**; clean it up with `trap` to avoid leftovers.
- **Copy back only what you need** (logs, final artifacts).
- **Assume scratch is not backed up** and may be purged after the job or after inactivity.
- **Scratch is per node**: multi-node jobs should **not** assume a single shared scratch unless the site provides one (e.g., parallel scratch/burst buffer).


## 7.5. Symbolic linking (symlink, or soft link)

A symbolic link (symlink) is like a shortcut — it lets you access a file or folder from another location without copying it.  
This is handy on the HPC when you want to point software to a bigger storage location or organize files without moving them.

**Example:**  
```bash
ln -s /quobyte/mydennisgrp/datasets/bigdata ~/bigdata
```
Now `~/bigdata` will open the data stored on the large drive.

:::info
Always use **absolute paths** (`/something/...`) when making symlinks.  
Relative paths can break if you run commands from a different directory.
:::

To see where a symlink points:
```bash
ls -l ~/bigdata
```

To remove a symlink (this won’t delete the real data):
```bash
rm ~/bigdata
```


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 8 Miniconda (Miniforge)

https://conda-forge.org/

Install a lightweight Conda (from **conda-forge**) in your home directory, hook it into Bash, then use **mamba** for fast solves. Keep `base` clean.

---

## 8.1 Install Miniforge

```bash
# Download the right installer for your OS/arch
curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"

# Make it executable and install (batch mode to $HOME/miniforge3)
chmod +x Miniforge3-$(uname)-$(uname -m).sh
./Miniforge3-$(uname)-$(uname -m).sh -b
```

**Add Conda to Bash (`~/.bashrc`)**

Option A — let Conda handle it:
```bash
$HOME/miniforge3/bin/conda init bash
# reload your shell so changes take effect
source ~/.bashrc
```


**Verify**
```bash
conda --version
which conda
```



## 8.2 Create and use environments

```bash
# create a fresh env with Python 3.11
conda create -n py311 python=3.11 -y

# activate / deactivate
conda activate py311
conda deactivate
```

:::danger
**Best practice:** keep **base** clean — **don’t install project packages** into `base`.  
Create project-specific envs (`conda create -n <name> ...`) and install packages there.
:::

---

**Use `mamba` for speed**
```bash
# install mamba into base (tooling-only is OK)
conda install -n base -c conda-forge mamba -y

# faster env & package operations
mamba create -n py311 python=3.11 -y
conda activate py311
mamba install numpy pandas -y
```


**Using Conda/Mamba inside Slurm (`sbatch`)**
```bash
#!/bin/bash
#SBATCH --job-name=conda_demo
#SBATCH --account=mydennisgrp
#SBATCH --partition=high
#SBATCH --cpus-per-task=2
#SBATCH --mem=8G
#SBATCH --time=00:30:00
#SBATCH --output=logs/%x_%j.out
#SBATCH --error=logs/%x_%j.err

# Load Conda correctly in non-interactive shells
. "$HOME/miniforge3/etc/profile.d/conda.sh"   # or: CONDA_BASE=$(conda info --base); . "$CONDA_BASE/etc/profile.d/conda.sh"
conda activate py311

python -c "import sys,platform; print(sys.executable, platform.python_version())"
```

---

:::danger
**Don’t mix Miniforge with `module load conda`.**  
If your `~/.bashrc` sources Miniforge, it will **shadow** the site Conda module. In that shell, **do not** run `module load conda/anaconda`. Use **one** Conda per session.
:::


## 8.3 Conda channels (add **bioconda** by default)

**What are channels?**  
Conda installs packages from *channels* (package repositories).  
- **conda-forge**: community-maintained, huge catalog, up-to-date.  
- **bioconda**: bioinformatics packages (built on top of conda-forge).  
**Order matters** and using **strict priority** avoids mixing builds.

**Option A — configure via commands (keeps existing settings)**
```bash
# Make sure conda-forge is present (Miniforge already has it)
conda config --add channels conda-forge

# Append bioconda after conda-forge
conda config --add channels bioconda

# Prefer higher-priority channels strictly
conda config --set channel_priority strict
```


**Example:**
```bash
mamba create -n bio python fastqc samtools bedtools bwa bowtie2 -y
mamba activate bio

# after creation, we can install more tools
mamba install bioconda::bcftools
```

:::info
With this setup you no longer need `-c bioconda -c conda-forge` on each install—the defaults cover it. Keep **base** clean; install tools into named envs.
:::


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 9 Port Forwarding

Port forwarding lets you open services (JupyterLab, VS Code Server, custom web apps) running on a **compute node** in your local browser.  
On Hive, connections **must go through the login node**: `hive.hpc.ucdavis.edu`.



## 9.1 How it works

```mermaid
flowchart LR
    A["Local Machine<br>Browser / VS Code"]:::local -- "ssh -L tunnel" --> B["Login Node<br>hive.hpc.ucdavis.edu"]:::login
    B -- "ssh" --> C["Compute Node<br>hive-dc-7-9-48"]:::compute

    classDef local fill:#d0e8ff,stroke:#4a90e2,stroke-width:2px,color:#0f3a66
    classDef login fill:#ffe7c2,stroke:#e69b1c,stroke-width:2px,color:#7a4b00
    classDef compute fill:#d5f5e3,stroke:#25a25a,stroke-width:2px,color:#0e5a2e
```


Flow: your browser → `localhost:LOCAL_PORT` → SSH tunnel → **login node** → **compute node:REMOTE_PORT**.

---

## 9.2 Quick template (recommended)

> Replace the vars, then run the single SSH command **from your laptop**.

```bash
# --- set these on your LOCAL machine ---
LOCAL_PORT=8888                 # any unused port on your laptop (e.g., 8888, 9000, 9999)
REMOTE_NODE=hive-dc-7-9-48      # copy verbatim from the compute-node prompt (see below)
REMOTE_PORT=3000                # the port your app uses on the compute node (e.g., 3000, 8888)

ssh -N -L ${LOCAL_PORT}:${REMOTE_NODE}:${REMOTE_PORT} mhussien@hive.hpc.ucdavis.edu
```

- Open your browser at: `http://localhost:${LOCAL_PORT}`  
- The `-N` flag keeps the tunnel open without starting a remote shell.
- To run it in the background, add `-f` (optional): `ssh -f -N -L ...`

**How to get `REMOTE_NODE`:**
- When you start an interactive job (e.g., with `srun --pty bash`), your prompt usually shows the node.
- Or run `hostname` on the compute node; use that string as `REMOTE_NODE`.

---

## 9.3 Example: Simple HTTP file browser on a compute node (Python only)

**1) Start an interactive job (on Hive)**
```bash
srun --account=mydennisgrp --partition=high \
     --cpus-per-task=4 --mem=16G --time=02:00:00 \
     --pty bash
```
You’ll land on a node like `hive-dc-7-9-48`.

**2) Launch a file-listing HTTP server on that node (Python only)**
```bash
module load python              # only load Python
cd ~
python -m http.server 8000 --bind 0.0.0.0
```
Leave this running; it serves a **directory listing** on port `8000`.

**3) From your laptop, forward the port through the login node**
```bash
LOCAL_PORT=8000
REMOTE_NODE=hive-dc-7-9-48
REMOTE_PORT=8000
ssh -N -L ${LOCAL_PORT}:${REMOTE_NODE}:${REMOTE_PORT} username@hive.hpc.ucdavis.edu
```

Open in your browser:
```
http://localhost:8000
```

:::info
- Change `LOCAL_PORT` if 8000 is busy on your laptop (e.g., 9000).  
- The `--bind 127.0.0.1` option keeps the server accessible **only** via your SSH tunnel (safer).
:::

---

## 9.4 Example: JBrowse use case (CHM13 + BAM on a compute node)


---

**1) Start an interactive job (on Hive)**

```bash
srun --account=mydennisgrp --partition=high \
     --cpus-per-task=4 --mem=16G --time=02:00:00 \
     --pty bash
# Note the node name (e.g., hive-dc-7-9-48)
```

**2) Create a Conda env and install JBrowse CLI**

```bash
mamba create -n jbrowse nodejs -y
mamba activate jbrowse

# install JBrowse CLI globally inside this env
npm install -g @jbrowse/cli
```

**3) Download JBrowse Web and register the assembly + track**

```bash
# Create a working directory and fetch the JBrowse Web build
JBROOT=$HOME/jbrowse_web2
jbrowse create $JBROOT
cd $JBROOT

# Add CHM13 assembly (FASTA + index in the same directory)
jbrowse add-assembly \
  /quobyte/mydennisgrp/mabuelanin/ref/chm13v2.0.fa \
  --alias chm13 \
  --name "T2T-CHM13v2.0" \
  --load symlink \
  --out .

# Add a BAM track (expects .bai next to the .bam)
jbrowse add-track \
  "/quobyte/mydennisgrp/mabuelanin/projects/simon/2025-simon-autism/all_simon_bams/STOPPED_ADDING_chm13_SD_bams/SS0013029_proband_11144.sorted.bam" \
  --name "SS0013029 proband (BAM)" \
  --trackId ss0013029_bam \
  --assemblyNames T2T-CHM13v2.0 \
  --load symlink \
  --out .

# Serve the downloaded web app from the current directory
npx serve -S . # leave this running
```





**4) From your laptop, forward a local port through the Hive login node**

```bash
LOCAL_PORT=9000
REMOTE_NODE=hive-dc-7-9-48
REMOTE_PORT=3000
ssh -N -L ${LOCAL_PORT}:${REMOTE_NODE}:${REMOTE_PORT} YOUR_USERNAME@hive.hpc.ucdavis.edu
```

Open in your browser:

```
http://localhost:9000
```


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 10. Containers: Apptainer and DeepVariant

Apptainer (formerly Singularity) is preinstalled on Hive for running containerized applications without root access. The following example runs DeepVariant for variant calling.

---

## Example: DeepVariant with CHM13 Reference


Create `run_deepvariant.sbatch`:

```bash
#!/bin/bash
#SBATCH --job-name=deepvariant_chr13
#SBATCH --account=mydennisgrp
#SBATCH --partition=high
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=32
#SBATCH --mem=100G
#SBATCH --time=00-10:00:00

# Set up paths
BASE_DIR="/quobyte/mydennisgrp/mabuelanin"
REF="${BASE_DIR}/ref/chm13v2.0.fa"
BAM="${BASE_DIR}/projects/simon/2025-simon-autism/all_simon_bams/STOPPED_ADDING_chm13_SD_bams/SS0013029_proband_11144.sorted.bam"
PROBAND_ID="SS0013029_proband_11144"
SIF_PATH="/quobyte/mydennisgrp/mabuelanin/apps/sifs/deepvariant_1.9.0.sif"

# Create output directory in your scratch space
SCRATCH_DIR="/scratch/${USER}/deepvariant_chr13_${SLURM_JOB_ID}"
mkdir -p "${SCRATCH_DIR}"

# Create tmp directory in scratch space
mkdir -p "${SCRATCH_DIR}/tmp"

# Define the target region
REGION="chr13:56356433-56364371"

echo "Working directory: ${SCRATCH_DIR}"
echo "Reference: ${REF}"
echo "Analyzing region: ${REGION}"
echo "Starting DeepVariant analysis..."

# Run DeepVariant on specific region (high-performance)
apptainer run \
  --bind "${BASE_DIR}:/mnt" \
  --bind "${SCRATCH_DIR}:/output" \
  --env TMPDIR="/output/tmp" \
  "${SIF_PATH}" \
  /opt/deepvariant/bin/run_deepvariant \
  --model_type=WGS \
  --ref="/mnt/ref/chm13v2.0.fa" \
  --reads="/mnt/projects/simon/2025-simon-autism/all_simon_bams/STOPPED_ADDING_chm13_SD_bams/${PROBAND_ID}.sorted.bam" \
  --regions="${REGION}" \
  --sample_name="${PROBAND_ID}" \
  --output_vcf="/output/${PROBAND_ID}_chr13.vcf.gz" \
  --output_gvcf="/output/${PROBAND_ID}_chr13.g.vcf.gz" \
  --intermediate_results_dir="/output/intermediate" \
  --num_shards=8

echo "DeepVariant completed. Results in: ${SCRATCH_DIR}"
ls -lh "${SCRATCH_DIR}"

# Show any variants found
echo "Variants found in region:"
zcat "${SCRATCH_DIR}/${PROBAND_ID}_chr13.vcf.gz" | grep -v "^#" | head -10

# Create permanent output directory and copy results
PERMANENT_DIR="/quobyte/mydennisgrp/mabuelanin/tmp"
mkdir -p "${PERMANENT_DIR}"

echo "Copying results to: ${PERMANENT_DIR}"
rsync -av "${SCRATCH_DIR}/" "${PERMANENT_DIR}/"

# Verify copy was successful
echo "Results copied successfully:"
ls -lh "${PERMANENT_DIR}"

# Clean up scratch directory
echo "Cleaning up scratch directory: ${SCRATCH_DIR}"
rm -rf "${SCRATCH_DIR}"

echo "Job completed! Results available at: ${PERMANENT_DIR}"
```

### Submit the job

```bash
sbatch run_deepvariant.sbatch
```

### Copy results when finished

```bash
# Check job completion first
squeue -u $USER
```

<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 11. Snakemake with SLURM Integration



## 11.1 Environment Setup

```bash
# Create conda environment for Snakemake
mamba create -n snakemake snakemake -y
mamba activate snakemake
pip install snakemake-executor-plugin-slurm
```

## 11.2 Multi-Sample DeepVariant Workflow

Create `Snakefile`:

```python
# Configuration for multiple samples
SAMPLES = [
    "SSC00003_proband_11006",
    "SSC00004_father_11006"
]

BASE_DIR = "/quobyte/mydennisgrp/mabuelanin"
REFERENCE = "/quobyte/mydennisgrp/mabuelanin/ref/chm13v2.0.fa"
BAM_DIR = "/quobyte/mydennisgrp/mabuelanin/projects/simon/2025-simon-autism/all_simon_bams/STOPPED_ADDING_chm13_SD_bams"
SIF_PATH = "/quobyte/mydennisgrp/mabuelanin/apps/sifs/deepvariant_1.9.0.sif"
REGION = "chr13:56356433-56364371"
OUTPUT_DIR = "/quobyte/mydennisgrp/mabuelanin/tmp"
USER = "mhussien"

rule all:
    input:
        expand(OUTPUT_DIR + "/{sample}_chr13.vcf.gz", sample=SAMPLES)

rule deepvariant:
    input:
        ref = REFERENCE,
        bam = BAM_DIR + "/{sample}.sorted.bam"
    output:
        vcf = OUTPUT_DIR + "/{sample}_chr13.vcf.gz",
        gvcf = OUTPUT_DIR + "/{sample}_chr13.g.vcf.gz"
    log:
        OUTPUT_DIR + "/logs/{sample}_deepvariant.log"
    resources:
        mem_mb = 100000,
        runtime = 600,  # 10 hours in minutes
        cpus = 32,
        slurm_account = "mydennisgrp",
        slurm_partition = "high",
        slurm_job_name = "deepvariant_{sample}"
    shell:
        """
        set -euo pipefail  # Exit on any error
        
        # Create scratch directory
        SCRATCH_DIR="/scratch/{USER}/deepvariant_{wildcards.sample}_${{SLURM_JOB_ID}}"
        mkdir -p "${{SCRATCH_DIR}}"
        mkdir -p "${{SCRATCH_DIR}}/tmp"
        
        echo "Processing sample: {wildcards.sample}"
        echo "Working directory: ${{SCRATCH_DIR}}"
        echo "Analyzing region: {REGION}"
        echo "Starting DeepVariant analysis..."
        
        # Run DeepVariant
        apptainer run \
          --bind "{BASE_DIR}:/mnt" \
          --bind "${{SCRATCH_DIR}}:/output" \
          --env TMPDIR="/output/tmp" \
          "{SIF_PATH}" \
          /opt/deepvariant/bin/run_deepvariant \
          --model_type=WGS \
          --ref="/mnt/ref/chm13v2.0.fa" \
          --reads="/mnt/projects/simon/2025-simon-autism/all_simon_bams/STOPPED_ADDING_chm13_SD_bams/{wildcards.sample}.sorted.bam" \
          --regions="{REGION}" \
          --sample_name="{wildcards.sample}" \
          --output_vcf="/output/{wildcards.sample}_chr13.vcf.gz" \
          --output_gvcf="/output/{wildcards.sample}_chr13.g.vcf.gz" \
          --intermediate_results_dir="/output/intermediate" \
          --num_shards=8
        
        echo "DeepVariant completed for {wildcards.sample}. Results in: ${{SCRATCH_DIR}}"
        
        # Check if output files exist before proceeding
        if [[ -f "${{SCRATCH_DIR}}/{wildcards.sample}_chr13.vcf.gz" ]]; then
            echo "VCF file created successfully"
            
            # Show any variants found (with error handling)
            echo "Variants found in region for {wildcards.sample}:"
            zcat "${{SCRATCH_DIR}}/{wildcards.sample}_chr13.vcf.gz" | grep -v "^#" | head -5 || echo "No variants found or error reading file"
            
            # Copy results to permanent storage
            mkdir -p "{OUTPUT_DIR}"
            echo "Copying results for {wildcards.sample} to: {OUTPUT_DIR}"
            rsync -av "${{SCRATCH_DIR}}/" "{OUTPUT_DIR}/"
            
            # Verify copy was successful
            if [[ -f "{OUTPUT_DIR}/{wildcards.sample}_chr13.vcf.gz" ]]; then
                echo "Results copied successfully for {wildcards.sample}:"
                ls -lh "{OUTPUT_DIR}/{wildcards.sample}_chr13"*
            else
                echo "ERROR: Copy failed for {wildcards.sample}"
                exit 1
            fi
        else
            echo "ERROR: DeepVariant failed to create output files"
            exit 1
        fi
        
        # Clean up (with error handling)
        echo "Cleaning up scratch directory: ${{SCRATCH_DIR}}"
        if [[ -d "${{SCRATCH_DIR}}" ]]; then
            rm -rf "${{SCRATCH_DIR}}" || echo "Warning: Could not fully clean scratch directory"
        fi
        
        echo "Job completed successfully for {wildcards.sample}! Results available at: {OUTPUT_DIR}"
        """
```

## Execution Commands

```bash
# Activate environment
conda activate snakemake

# Dry run to preview all jobs
snakemake -n

# Run all samples in parallel (max 2 jobs simultaneously)
snakemake --executor slurm --jobs 2

```


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 12. Monitoring Disk Usage with Duc

> *Dude, where are my bytes?*
> [Official Documentation](https://duc.zevv.nl/)

**Duc** is a blazing-fast disk usage analyzer that works by first **indexing** the directories you want to inspect, and then letting you **browse** the index interactively. It’s an excellent way to explore large file systems without repeatedly scanning everything.

![Duc interface example](https://hackmd.io/_uploads/SylbraK3gx.png)

---

## Installation

You can install Duc easily via **conda**:

```bash
conda create -n duc duc -y
```

Then activate the environment as usual:

```bash
conda activate duc
```

---

## Indexing Large Directories

When dealing with very large directories, it’s often useful to exclude unnecessary paths — such as hidden files, Conda environments, and working directories from Snakemake or Nextflow.

Here’s an example of how to create an index efficiently:

```bash
duc index -p \
  --exclude=".*" \
  --exclude=miniconda \
  --exclude="*conda*" \
  --exclude="from-lssc0/programs" \
  --exclude=".nextflow" \
  --exclude=".snakemake" \
  --max-depth=10 \
  /quobyte/mydennisgrp/from-lssc0/users \
  /quobyte/mydennisgrp/from-lssc0/projects
```

> *The index is stored in your local `~/.cache/duc/` directory.*

To view any indexed directory, run for example:

```bash
duc ui /quobyte/mydennisgrp/from-lssc0/projects
```

---

## Sharing the Index with Other Users

If you want others to be able to view the existing index **without installing Duc** or re-indexing the data, simply link the shared database file to their local cache:

```bash
mkdir -p $HOME/.cache/duc/
ln -s /quobyte/mydennisgrp/from-lssc0/duc.db $HOME/.cache/duc/
```

Then they can launch the Duc UI directly:

```bash
# View users directory
/quobyte/mydennisgrp/mabuelanin/miniforge3/envs/duc/bin/duc ui /quobyte/mydennisgrp/from-lssc0/users

# View projects directory
/quobyte/mydennisgrp/mabuelanin/miniforge3/envs/duc/bin/duc ui /quobyte/mydennisgrp/from-lssc0/projects
```


<hr style="border: 0; border-top: 6px solid currentColor; border-bottom: 2px solid currentColor; height: 0; margin: 1.25rem 0;">


# 13. Dennislab Hive documentation and management

https://github.com/mydennislab/hive

# Other Topics

- Termius
- Vscode
- Github

