Notebooks 2.0 is here.

Public
Edited
Jul 29
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof combineAssemblyScript2 = {
const inputPath = Inputs.text({
label: "📂 Path to folder containing barcode directories",
placeholder:
"C:\\Users\\yourname\\Desktop\\Nanopore_Results\\Run1\\Sample1\\assemblies",
style: "width: 600px"
});

const textarea = html`<textarea readonly rows="30" style="width: 100%; font-family: monospace; white-space: pre;"></textarea>`;
const copyButton = html`<button style="padding: 4px 8px; font-size: 0.85em;">📋 Copy</button>`;

copyButton.onclick = () => {
navigator.clipboard.writeText(textarea.value);
copyButton.textContent = "✅ Copied!";
setTimeout(() => (copyButton.textContent = "📋 Copy"), 1500);
};

function toWSLPath(path) {
return path
.replace(/^([A-Za-z]):/, (_, d) => `/mnt/${d.toLowerCase()}`)
.replace(/\\/g, "/");
}

function generateScript() {
const rawPath = inputPath.value.trim();
const path = toWSLPath(rawPath);

textarea.value = `#!/bin/bash

# 🧬 Activate reads-assembly-core environment
source ~/miniconda/etc/profile.d/conda.sh
conda activate reads-assembly-core

# 📁 Define the base directory
base_dir="${path}"

# 📄 Output file for selected data
output_file="\${base_dir}/assembly_summary.tsv"

# 🧾 Write header
echo -e "Barcode\\tseq_name\\tlength\\tcov." > "\${output_file}"

# 🔁 Loop through barcode folders
for dir in "\${base_dir}"/barcode*/; do
folder_name=$(basename "\${dir}")
info_file="\${dir}assembly_info.txt"

if [[ -f "\${info_file}" ]]; then
data_line=$(sed -n '2p' "\${info_file}")
if [[ -n "\${data_line}" ]]; then
seq_name=$(echo "\${data_line}" | cut -f1)
length=$(echo "\${data_line}" | cut -f2)
cov=\$(echo "\${data_line}" | cut -f3)
echo -e "\${folder_name}\\t\${seq_name}\\t\${length}\\t\${cov}" >> "\${output_file}"
fi
else
echo "Warning: Missing \${info_file}"
fi
done

# 📊 Convert to Excel
python3 - <<EOF
import pandas as pd
import os
tsv_path = os.path.join("${path}", "assembly_summary.tsv")
xlsx_path = os.path.join("${path}", "assembly_summary.xlsx")
df = pd.read_csv(tsv_path, sep="\\t")
df.to_excel(xlsx_path, index=False)
EOF

echo "✅ Done! TSV and Excel saved in: \${base_dir}"`;
}

inputPath.addEventListener("input", generateScript);
generateScript();

const controlsPanel = html`<div style="display: flex; flex-direction: column; gap: 1em; min-width: 320px;">
${inputPath}
</div>`;

const outputPanel = html`<div style="flex-grow: 1; display: flex; flex-direction: column; gap: 0.5em;">
${textarea}
${copyButton}
</div>`;

return html`<div style="display: flex; flex-direction: row; gap: 2em; align-items: flex-start;">
${controlsPanel}
${outputPanel}
</div>`;
}
Insert cell
Insert cell
Insert cell
viewof doradoBasecallScript2 = {
const kitInput = Inputs.select(
[
"SQK-RPB114-24",
"EXP-NBD114",
"SQK-PCB109",
"SQK-RAB201",
"Custom-Barcodes"
],
{ label: "🧬 Kit name", value: "SQK-RPB114-24", style: "width: 250px" }
);

const modelInput = Inputs.text({
label: "📈 Model",
value: "sup@v5.2",
style: "width: 250px"
});

const qscoreInput = Inputs.range([0, 30], {
label: "🎯 Minimum Q-score",
value: 10,
step: 1
});

const pod5FolderInput = Inputs.text({
label: "📁 Folder of Pod5 files (Windows path)",
placeholder: "C:\\Users\\YourName\\Desktop\\Nanopore_Data\\Pod5_Files",
style: "width: 600px"
});

const outputPathInput = Inputs.text({
label: "📄 Output BAM file name",
placeholder: "Dorado_Output.bam",
value: "Dorado_Output.bam",
style: "width: 600px"
});

const barcodeArrangementInput = Inputs.text({
label: "🧬 Barcode arrangement TOML (Windows path, optional)",
placeholder: "C:\\Path\\To\\Your\\M13-arrangement.toml",
style: "width: 600px"
});

const barcodeSequencesInput = Inputs.text({
label: "🧬 Barcode sequences FASTA (Windows path, optional)",
placeholder: "C:\\Path\\To\\Your\\barcodes.fasta",
style: "width: 600px"
});

const textarea = html`<textarea readonly rows="10" style="width: 100%; font-family: monospace; white-space: pre;"></textarea>`;
const copyButton = html`<button style="padding: 4px 8px; font-size: 0.9em;">📋 Copy Command</button>`;

function toWSLPath(winPath) {
return winPath
.replace(/^([A-Za-z]):/, (_, d) => `/mnt/${d.toLowerCase()}`)
.replace(/\\/g, "/");
}

function updateScript() {
const pod5WinPath = pod5FolderInput.value.trim();
const outputBam = outputPathInput.value.trim() || "Dorado_Output.bam";
const barcodeToml = barcodeArrangementInput.value.trim();
const barcodeFasta = barcodeSequencesInput.value.trim();

if (!pod5WinPath) {
textarea.value = "";
copyButton.disabled = true;
return;
}

const pod5LinuxPath = toWSLPath(pod5WinPath);
const outputLinuxPath = `${pod5LinuxPath}/${outputBam}`;
const args = [
"dorado basecaller -rv",
` --kit-name ${kitInput.value}`,
` --min-qscore ${qscoreInput.value}`
];

// Add custom barcode flags only if both paths are provided
if (barcodeToml && barcodeFasta) {
args.push(` --barcode-arrangement ${toWSLPath(barcodeToml)}`);
args.push(` --barcode-sequences ${toWSLPath(barcodeFasta)}`);
}

args.push(` ${modelInput.value}`);
args.push(` "${pod5LinuxPath}" > "${outputLinuxPath}"`);

textarea.value = `# 🧬 Run Dorado Basecalling\n${args.join(" \\\n")}`;
copyButton.disabled = false;
}

copyButton.onclick = () => {
navigator.clipboard.writeText(textarea.value);
copyButton.textContent = "✅ Copied!";
setTimeout(() => (copyButton.textContent = "📋 Copy Command"), 1500);
};

[
pod5FolderInput,
outputPathInput,
modelInput,
kitInput,
qscoreInput,
barcodeArrangementInput,
barcodeSequencesInput
].forEach((input) => input.addEventListener("input", updateScript));

updateScript();

const controls = html`<div style="display: flex; flex-direction: column; gap: 1em; min-width: 360px;">
${kitInput}
${modelInput}
${qscoreInput}
${pod5FolderInput}
${outputPathInput}
${barcodeArrangementInput}
${barcodeSequencesInput}
</div>`;

const output = html`<div style="flex-grow: 1; display: flex; flex-direction: column; gap: 0.5em;">
${textarea}
${copyButton}
</div>`;

return html`<div style="display: flex; gap: 2em; align-items: flex-start;">
${controls}
${output}
</div>`;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more