Skip to content

Commit 72b64ca

Browse files
authored
Merge pull request #4 from ShawnPatrick-Barhorst/main
Jetstream2 Deployment
2 parents 16e352c + 98b85a8 commit 72b64ca

File tree

5 files changed

+267
-3
lines changed

5 files changed

+267
-3
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# ----------------------------------------
5+
# Pretty printing helpers (same style)
6+
# ----------------------------------------
7+
8+
function generate_separator {
9+
local max_len=0
10+
for arg in "$@"; do
11+
((${#arg} > max_len)) && max_len=${#arg}
12+
done
13+
14+
local spaces
15+
printf -v spaces "%${max_len}s" ""
16+
echo "${spaces// /=}"
17+
}
18+
19+
function print_separated_message {
20+
local sep
21+
sep=$(generate_separator "$@")
22+
23+
echo "$sep"
24+
for line in "$@"; do
25+
echo "$line"
26+
done
27+
echo "$sep"
28+
}
29+
30+
function die {
31+
echo "ERROR: $*" >&2
32+
exit 1
33+
}
34+
35+
function step {
36+
# Usage: step "1/7" "Message"
37+
print_separated_message "[${1}] ${2}"
38+
}
39+
40+
# ----------------------------------------
41+
# Static settings (change only if needed)
42+
# ----------------------------------------
43+
44+
ENV_NAME="NSDF-Tutorial"
45+
KERNEL_NAME="nsdf-tutorial"
46+
KERNEL_DISPLAY='Python (NSDF-Tutorial)'
47+
48+
# ----------------------------------------
49+
# Derived paths
50+
# ----------------------------------------
51+
52+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
53+
cd "$SCRIPT_DIR"
54+
55+
# ----------------------------------------
56+
# 0) Ensure conda is available
57+
# ----------------------------------------
58+
59+
step "0/7" "Checking conda availability"
60+
61+
if command -v module >/dev/null 2>&1; then
62+
# Jetstream module environment
63+
module purge >/dev/null 2>&1 || true
64+
module load miniforge >/dev/null 2>&1 || true
65+
fi
66+
67+
command -v conda >/dev/null 2>&1 || die "conda not found. Did you 'module load miniforge'?"
68+
69+
# Make conda activate work in scripts
70+
# shellcheck disable=SC1090
71+
source "$(conda info --base)/etc/profile.d/conda.sh"
72+
73+
# ----------------------------------------
74+
# 1) Create env from environment.yml (replace if exists)
75+
# ----------------------------------------
76+
77+
step "1/7" "Create env from environment.yml (name: ${ENV_NAME})"
78+
79+
if conda env list | awk '{print $1}' | grep -qx "$ENV_NAME"; then
80+
echo "Removing existing env: ${ENV_NAME}"
81+
conda env remove -n "$ENV_NAME" -y >/dev/null
82+
fi
83+
84+
conda env create -f environment.yml >/dev/null
85+
86+
# ----------------------------------------
87+
# 2) Activate environment
88+
# ----------------------------------------
89+
90+
step "2/7" "Activate env: ${ENV_NAME}"
91+
92+
conda activate "$ENV_NAME"
93+
hash -r
94+
95+
# ----------------------------------------
96+
# 3) Verify activation (hard fail if wrong)
97+
# ----------------------------------------
98+
99+
step "3/7" "Verify activation"
100+
101+
python - <<PY
102+
import os, sys
103+
env = os.environ.get("CONDA_DEFAULT_ENV")
104+
prefix = os.environ.get("CONDA_PREFIX")
105+
print("CONDA_DEFAULT_ENV:", env)
106+
print("CONDA_PREFIX:", prefix)
107+
print("sys.executable:", sys.executable)
108+
if env != "$ENV_NAME":
109+
raise SystemExit(f"ERROR: expected CONDA_DEFAULT_ENV=$ENV_NAME but got {env}")
110+
PY
111+
112+
# ----------------------------------------
113+
# 4) Install GEOtiled/geotiled editable
114+
# ----------------------------------------
115+
116+
step "4/7" "Install GEOtiled/geotiled editable"
117+
118+
GEOTILED_DIR="$SCRIPT_DIR/GEOtiled/geotiled"
119+
[[ -d "$GEOTILED_DIR" ]] || die "GEOtiled/geotiled dir not found: $GEOTILED_DIR"
120+
121+
python -m pip install -e "$GEOTILED_DIR" >/dev/null
122+
123+
# ----------------------------------------
124+
# 5) Configure Openvisuspy environment variables
125+
# ----------------------------------------
126+
127+
step "5/7" "Configure Openvisuspy env vars (~/.bashrc)"
128+
129+
OPENVISUSPY_SRC="$SCRIPT_DIR/openvisuspy/src"
130+
[[ -d "$OPENVISUSPY_SRC" ]] || die "openvisuspy/src not found: $OPENVISUSPY_SRC"
131+
132+
# Append only if not already present (idempotent-ish)
133+
append_if_missing () {
134+
local line="$1"
135+
local file="$2"
136+
grep -Fqx "$line" "$file" 2>/dev/null || echo "$line" >> "$file"
137+
}
138+
139+
BASHRC="$HOME/.bashrc"
140+
141+
append_if_missing "export PATH=\"\$PATH:${OPENVISUSPY_SRC}\"" "$BASHRC"
142+
append_if_missing "export PYTHONPATH=\"\$PYTHONPATH:${OPENVISUSPY_SRC}\"" "$BASHRC"
143+
append_if_missing "export BOKEH_ALLOW_WS_ORIGIN='*'" "$BASHRC"
144+
append_if_missing "export BOKEH_RESOURCES='cdn'" "$BASHRC"
145+
append_if_missing "export VISUS_CACHE=/tmp/visus-cache/nsdf-services/somospie" "$BASHRC"
146+
append_if_missing "export VISUS_CPP_VERBOSE=1" "$BASHRC"
147+
append_if_missing "export VISUS_NETSERVICE_VERBOSE=1" "$BASHRC"
148+
append_if_missing "export VISUS_VERBOSE_DISKACCESS=1" "$BASHRC"
149+
150+
# Load into current shell too
151+
# shellcheck disable=SC1090
152+
source "$BASHRC"
153+
154+
# ----------------------------------------
155+
# 6) Install openvisuspy editable
156+
# ----------------------------------------
157+
158+
step "6/7" "Install openvisuspy editable"
159+
160+
OPENVISUSPY_DIR="$SCRIPT_DIR/openvisuspy"
161+
[[ -d "$OPENVISUSPY_DIR" ]] || die "openvisuspy dir not found: $OPENVISUSPY_DIR"
162+
163+
python -m pip install -e "$OPENVISUSPY_DIR" >/dev/null
164+
165+
# ----------------------------------------
166+
# 7) Install ipykernel + register kernel
167+
# ----------------------------------------
168+
169+
step "7/7" "Install Jupyter kernel + extras"
170+
171+
# keep these visible enough to diagnose, but not too noisy
172+
ENV_BIN_DIR="$CONDA_PREFIX/bin"
173+
174+
python -m ipykernel install --user \
175+
--name "$KERNEL_NAME" \
176+
--display-name "$KERNEL_DISPLAY" \
177+
--env PATH "$ENV_BIN_DIR:$OPENVISUSPY_SRC:$PATH" \
178+
--env LD_LIBRARY_PATH "$CONDA_PREFIX/lib:$CONDA_PREFIX/lib/gdalplugins" \
179+
--env PROJ_LIB "$CONDA_PREFIX/share/proj" \
180+
--env GDAL_DATA "$CONDA_PREFIX/share/gdal" \
181+
--env PROJ_NETWORK "ON"
182+
183+
print_separated_message \
184+
"DONE" \
185+
"" \
186+
"Environment:" \
187+
" conda activate ${ENV_NAME}" \
188+
"" \
189+
"Kernel:" \
190+
" jupyter kernelspec list" \
191+
" (look for '${KERNEL_DISPLAY}')"

hands-on/session II/Materials/environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ dependencies:
2121
- pip
2222
- pip:
2323
- panel==1.3.8
24-
- OpenVisusNoGui==2.2.128
24+
- OpenVisusNoGui==2.2.149
2.25 MB
Binary file not shown.

hands-on/session II/README.md

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ You can download the introductory slides [here](https://drive.google.com/file/d/
4949
1. [Running the Tutorial](#running-the-tutorial)
5050
2. [Option 1: GitHub Codespaces (Recommended)](#option-1-GitHub-codespaces-recommended)
5151
3. [Option 2: Docker](#0ption-2-docker)
52-
4. [APPENDIX: Prerequities for Docker](#appendix-prerequities-for-docker)
53-
5. [Community and Resources](#community-and-resources)
52+
4. [Option 3: Jetstream2](#option-3-jetstream2)
53+
5. [APPENDIX: Prerequities for Docker](#appendix-prerequities-for-docker)
54+
6. [Community and Resources](#community-and-resources)
5455
7. [Publications](#publications)
5556
8. [Copyright and License](#copyright-and-license)
5657
9. [Authors](#authors)
@@ -118,6 +119,77 @@ docker-compose up -d</code></pre>
118119
</li>
119120
</ol>
120121

122+
## Option 3: Jetstream2
123+
<p><strong>Requirements:</strong> Access to a Jetstream2 instance via SSH.</p>
124+
125+
<h4>Initial Setup (First Time Only)</h4>
126+
<ol>
127+
<li>
128+
If you do not already have a Jetstream2 instance, follow the
129+
<a href="Materials/jetstream2_manual.pdf" target="_blank">
130+
Jetstream2 Setup Manual
131+
</a>
132+
to create and connect to one.
133+
</li>
134+
135+
<li>Connect to your Jetstream2 instance via SSH.</li>
136+
137+
<li>
138+
Clone the tutorial repository:
139+
<pre><code>git clone https://github.com/TauferLab/NSDF-Tutorial-2025.git</code></pre>
140+
</li>
141+
142+
<li>
143+
Navigate to the session materials directory and build the environment:
144+
<pre><code>cd NSDF-Tutorial-2025/hands-on/session\ II/Materials/
145+
module load miniforge
146+
./build_jetstream_environment.sh</code></pre>
147+
</li>
148+
149+
<li>
150+
Start Jupyter Lab:
151+
<pre><code>cd ..
152+
jupyter-ip.sh</code></pre>
153+
</li>
154+
155+
<li>Open the Jupyter Lab URL printed in the terminal in your web browser.</li>
156+
157+
<li>
158+
In Jupyter Lab, select the kernel named
159+
<strong>NSDF-Tutorial</strong>.
160+
</li>
161+
</ol>
162+
163+
<h4>Starting the Environment (After Installation)</h4>
164+
<ol>
165+
<li>
166+
Load Conda:
167+
<pre><code>module load miniforge
168+
</code></pre>
169+
</li>
170+
171+
<li>
172+
Navigate to the tutorial directory and start Jupyter:
173+
<pre><code>cd hands-on/session\ II
174+
jupyter-ip.sh</code></pre>
175+
</li>
176+
177+
<li>Open the Jupyter Lab URL printed in the terminal in your browser.</li>
178+
</ol>
179+
180+
<h4>Accessing OpenVisuspy Dashboards</h4>
181+
<ol>
182+
<li>
183+
From your local machine, create an SSH tunnel to forward the dashboard port:
184+
<pre><code>ssh -L 8989:127.0.0.1:8989 &lt;Jetstream Native SSH&gt;</code></pre>
185+
</li>
186+
187+
<li>
188+
After executing the corresponding dashboard cell in Jupyter, open your browser and navigate to:
189+
<pre><code>http://localhost:8989</code></pre>
190+
</li>
191+
</ol>
192+
121193

122194
## APPENDIX: Prerequisites
123195

hands-on/session III/environment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ channels:
44
- defaults
55
dependencies:
66
- python=3.10
7+
- ipykernel==6.29.2
78
- pip
89
- pip:
910
- numpy

0 commit comments

Comments
 (0)