3 Commits

Author SHA1 Message Date
Eric Coissac
2417959fbd Add options to startup script 2025-11-26 09:47:20 +01:00
Eric Coissac
4e338bc1d4 Complete the documentation Readme file 2025-11-25 13:05:27 +01:00
Eric Coissac
053d2e28cb A pretty jupyter login 2025-11-25 13:00:02 +01:00
364 changed files with 460578 additions and 170869 deletions

6
.gitignore vendored
View File

@@ -3,6 +3,8 @@
/jupyterhub_volumes/shared
/jupyterhub_volumes/jupyterhub
/jupyterhub_volumes/caddy
/jupyterhub_volumes/course/data/Genbank
/jupyterhub_volumes/web/
/**/.DS_Store
/web_src/**/*.RData
/web_src/**/*.pdf
@@ -11,3 +13,7 @@
/.luarc.json
/sandbox
*.log
ncbitaxo_*
Readme_files
Readme.html
tmp.*

709
Readme.html Normal file
View File

@@ -0,0 +1,709 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
<meta charset="utf-8">
<meta name="generator" content="quarto-1.8.26">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>readme</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
vertical-align: middle;
}
/* CSS for syntax highlighting */
html { -webkit-text-size-adjust: 100%; }
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
}
pre.numberSource { margin-left: 3em; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
</style>
<script src="Readme_files/libs/clipboard/clipboard.min.js"></script>
<script src="Readme_files/libs/quarto-html/quarto.js" type="module"></script>
<script src="Readme_files/libs/quarto-html/tabsets/tabsets.js" type="module"></script>
<script src="Readme_files/libs/quarto-html/axe/axe-check.js" type="module"></script>
<script src="Readme_files/libs/quarto-html/popper.min.js"></script>
<script src="Readme_files/libs/quarto-html/tippy.umd.min.js"></script>
<script src="Readme_files/libs/quarto-html/anchor.min.js"></script>
<link href="Readme_files/libs/quarto-html/tippy.css" rel="stylesheet">
<link href="Readme_files/libs/quarto-html/quarto-syntax-highlighting-587c61ba64f3a5504c4d52d930310e48.css" rel="stylesheet" id="quarto-text-highlighting-styles">
<script src="Readme_files/libs/bootstrap/bootstrap.min.js"></script>
<link href="Readme_files/libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="Readme_files/libs/bootstrap/bootstrap-d6a003b94517c951b2d65075d42fb01b.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
</head>
<body class="fullcontent quarto-light">
<div id="quarto-content" class="page-columns page-rows-contents page-layout-article">
<main class="content" id="quarto-document-content">
<section id="obijupyterhub---the-dna-metabarcoding-learning-server" class="level1">
<h1>OBIJupyterHub - the DNA Metabarcoding Learning Server</h1>
<section id="intended-use" class="level2">
<h2 class="anchored" data-anchor-id="intended-use">Intended use</h2>
<p>This project packages the MetabarcodingSchool training lab into one reproducible bundle. You get Python, R, and Bash kernels, a Quarto-built course website, and preconfigured admin/student accounts, so onboarding a class is a single command instead of a day of setup. Everything runs locally on a single machine, student work persists between sessions, and <code>./start-jupyterhub.sh</code> takes care of building images, rendering the site, preparing volumes, and bringing JupyterHub up at <code>http://localhost:8888</code>. Defaults (accounts, passwords, volumes) live in the repo so instructors can tweak them quickly.</p>
</section>
<section id="prerequisites-with-quick-checks" class="level2">
<h2 class="anchored" data-anchor-id="prerequisites-with-quick-checks">Prerequisites (with quick checks)</h2>
<p>You need Docker, Docker Compose, Quarto, and Python 3 available on the machine that will host the lab.</p>
<ul>
<li>macOS: install <a href="https://orbstack.dev/">OrbStack</a> (recommended) or Docker Desktop; both ship Docker Engine and Compose.</li>
<li>Linux: install Docker Engine and the Compose plugin from your distribution (e.g., <code>sudo apt install docker.io docker-compose-plugin</code>) or from Dockers official packages.</li>
<li>Windows: install Docker Desktop with the WSL2 backend enabled.</li>
<li>Quarto CLI: get installers from <a href="https://quarto.org/docs/get-started/" class="uri">https://quarto.org/docs/get-started/</a>.</li>
<li>Python 3: any recent version is fine (only the standard library is used).</li>
</ul>
<p>Verify from a terminal; if a command is missing, install it before moving on:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">docker</span> <span class="at">--version</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">docker</span> compose version <span class="co"># or: docker-compose --version</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ex">quarto</span> <span class="at">--version</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">--version</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
</section>
<section id="how-the-startup-script-works" class="level2">
<h2 class="anchored" data-anchor-id="how-the-startup-script-works">How the startup script works</h2>
<p><code>./start-jupyterhub.sh</code> is the single entry point. It builds the Docker images, renders the course website, prepares the volume folders, and starts the stack. Internally it:</p>
<ul>
<li>creates the <code>jupyterhub_volumes/</code> tree (caddy, course, shared, users, web…)</li>
<li>builds <code>jupyterhub-student</code> and <code>jupyterhub-hub</code> images</li>
<li>renders the Quarto site from <code>web_src/</code>, generates PDF galleries and <code>pages.json</code>, and copies everything into <code>jupyterhub_volumes/web/</code></li>
<li>runs <code>docker-compose up -d --remove-orphans</code></li>
</ul>
<p>You can tailor what it does with a few flags:</p>
<ul>
<li><code>--no-build</code> (or <code>--offline</code>): skip Docker image builds and reuse existing images (useful when offline).</li>
<li><code>--force-rebuild</code>: rebuild images without cache.</li>
<li><code>--stop-server</code>: stop the stack and remove student containers, then exit.</li>
<li><code>--update-lectures</code>: rebuild the course website only (no Docker stop/start).</li>
</ul>
</section>
<section id="installation-and-first-run" class="level2">
<h2 class="anchored" data-anchor-id="installation-and-first-run">Installation and first run</h2>
<ol type="1">
<li>Clone the project:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> clone https://forge.metabarcoding.org/MetabarcodingSchool/OBIJupyterHub.git</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> OBIJupyterHub</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<ol start="2" type="1">
<li>(Optional) glance at the structure youll populate:</li>
</ol>
<pre><code>OBIJupyterHub
├── start-jupyterhub.sh - single entry point (build + render + start)
├── obijupyterhub - Docker images and stack definitions
&nbsp;&nbsp; ├── docker-compose.yml
&nbsp;&nbsp; ├── Dockerfile
&nbsp;&nbsp; ├── Dockerfile.hub
&nbsp;&nbsp; └── jupyterhub_config.py
├── jupyterhub_volumes - data persisted on the host
&nbsp;&nbsp; ├── course - read-only for students (notebooks, data, bin, R packages)
&nbsp;&nbsp; ├── shared - shared read/write space for everyone
&nbsp;&nbsp; ├── users - per-user persistent data
&nbsp;&nbsp; └── web - rendered course website
└── web_src - Quarto sources for the course website</code></pre>
<ol start="3" type="1">
<li>Prepare course materials (optional before first run):</li>
</ol>
<ul>
<li>Put notebooks, datasets, scripts, binaries, or PDFs for students under <code>jupyterhub_volumes/course/</code>. They will appear read-only at <code>/home/jovyan/work/course/</code>.</li>
<li>For collaborative work, drop files in <code>jupyterhub_volumes/shared/</code> (read/write for all at <code>/home/jovyan/work/shared/</code>).</li>
<li>Edit or add Quarto sources in <code>web_src/</code> to update the course website; the script will render them.</li>
</ul>
<ol start="4" type="1">
<li>Start everything (build + render + launch):</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./start-jupyterhub.sh</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<ol start="5" type="1">
<li><p>Access JupyterHub in a browser at <code>http://localhost:8888</code>.</p></li>
<li><p>Stop the stack when youre done (run from <code>obijupyterhub/</code>):</p></li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">docker-compose</span> down</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<section id="operating-the-stack-one-command-a-few-options" class="level3">
<h3 class="anchored" data-anchor-id="operating-the-stack-one-command-a-few-options">Operating the stack (one command, a few options)</h3>
<ul>
<li>Start or rebuild: <code>./start-jupyterhub.sh</code> (rebuilds images, regenerates the website, starts the stack).</li>
<li>Start without rebuilding images (offline): <code>./start-jupyterhub.sh --no-build</code></li>
<li>Force rebuild without cache: <code>./start-jupyterhub.sh --force-rebuild</code></li>
<li>Stop only: <code>./start-jupyterhub.sh --stop-server</code></li>
<li>Rebuild website only (no Docker stop/start): <code>./start-jupyterhub.sh --update-lectures</code></li>
<li>Access at <code>http://localhost:8888</code> (students: any username / password <code>metabar2025</code>; admin: <code>admin</code> / <code>admin2025</code>).</li>
<li>Check logs from <code>obijupyterhub/</code> with <code>docker-compose logs -f jupyterhub</code>.</li>
<li>Stop with <code>docker-compose down</code> (from <code>obijupyterhub/</code>). Rerun <code>./start-jupyterhub.sh</code> to start again or after config changes.</li>
</ul>
</section>
</section>
<section id="managing-shared-data" class="level2">
<h2 class="anchored" data-anchor-id="managing-shared-data">Managing shared data</h2>
<p>Each student lands in <code>/home/jovyan/work/</code> with three key areas: their own files, a shared space, and a read-only course space. Everything under <code>work/</code> is persisted on the host in <code>jupyterhub_volumes</code>.</p>
<pre><code>work/ # Personal workspace root (persistent)
├── [student files] # Their own files and notebooks
├── R_packages/ # Personal R packages (writable by student)
├── shared/ # Shared workspace (read/write, shared with all)
└── course/ # Course files (read-only, managed by admin)
├── R_packages/ # Shared R packages (read-only, installed by prof)
├── bin/ # Shared executables (in PATH)
└── [course materials] # Your course files</code></pre>
<p>R looks for packages in this order: personal <code>work/R_packages/</code>, then shared <code>work/course/R_packages/</code>, then system libraries. Because everything lives under <code>work/</code>, student files survive restarts.</p>
<section id="user-accounts" class="level3">
<h3 class="anchored" data-anchor-id="user-accounts">User Accounts</h3>
<p>Defaults are defined in <code>obijupyterhub/docker-compose.yml</code>: admin (<code>admin</code> / <code>admin2025</code>) with write access to <code>course/</code>, and students (any username, password <code>metabar2025</code>) with read-only access to <code>course/</code>. Adjust <code>JUPYTERHUB_ADMIN_PASSWORD</code> and <code>JUPYTERHUB_PASSWORD</code> there, then rerun <code>./start-jupyterhub.sh</code>.</p>
</section>
<section id="installing-r-packages-admin-only" class="level3">
<h3 class="anchored" data-anchor-id="installing-r-packages-admin-only">Installing R Packages (Admin Only)</h3>
<p>From the host, install shared R packages into <code>course/R_packages/</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Install packages</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ex">tools/install_packages.sh</span> reshape2 plotly knitr</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<p>Students can install their own packages into their personal <code>work/R_packages/</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Install in personal library (each student has their own)</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="fu">install.packages</span>(<span class="st">'mypackage'</span>) <span class="co"># Will install in work/R_packages/</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
</section>
<section id="using-r-packages-students" class="level3">
<h3 class="anchored" data-anchor-id="using-r-packages-students">Using R Packages (Students)</h3>
<p>Students simply load packages normally:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(reshape2) <span class="co"># R checks: 1) work/R_packages/ 2) work/course/R_packages/ 3) system</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(plotly)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<p>R automatically searches in this order:</p>
<ol type="1">
<li>Personal packages: <code>/home/jovyan/work/R_packages/</code> (R_LIBS_USER)</li>
<li>Prof packages: <code>/home/jovyan/work/course/R_packages/</code> (R_LIBS_SITE)</li>
<li>System packages</li>
</ol>
</section>
<section id="list-available-packages" class="level3">
<h3 class="anchored" data-anchor-id="list-available-packages">List Available Packages</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co"># List all available packages (personal + course + system)</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="fu">installed.packages</span>()[,<span class="st">"Package"</span>]</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Check personal packages</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="fu">list.files</span>(<span class="st">"/home/jovyan/work/R_packages"</span>)</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Check course packages (installed by prof)</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="fu">list.files</span>(<span class="st">"/home/jovyan/work/course/R_packages"</span>)</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
</section>
<section id="deposit-or-retrieve-course-and-student-files" class="level3">
<h3 class="anchored" data-anchor-id="deposit-or-retrieve-course-and-student-files">Deposit or retrieve course and student files</h3>
<p>On the host, place course files in <code>jupyterhub_volumes/course/</code> (they appear read-only to students), shared files in <code>jupyterhub_volumes/shared/</code>, and collect student work from <code>jupyterhub_volumes/users/</code>.</p>
</section>
</section>
<section id="user-management" class="level2">
<h2 class="anchored" data-anchor-id="user-management">User Management</h2>
<section id="option-1-predefined-user-list" class="level3">
<h3 class="anchored" data-anchor-id="option-1-predefined-user-list">Option 1: Predefined User List</h3>
<p>In <code>jupyterhub_config.py</code>, uncomment and modify:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>c.Authenticator.allowed_users <span class="op">=</span> {<span class="st">'student1'</span>, <span class="st">'student2'</span>, <span class="st">'student3'</span>}</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
</section>
<section id="option-2-allow-everyone-for-testing" class="level3">
<h3 class="anchored" data-anchor-id="option-2-allow-everyone-for-testing">Option 2: Allow Everyone (for testing)</h3>
<p>By default, the configuration allows any user:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>c.Authenticator.allow_all <span class="op">=</span> <span class="va">True</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<p>⚠️ <strong>Warning</strong>: DummyAuthenticator is ONLY for local testing!</p>
</section>
</section>
<section id="kernel-verification" class="level2">
<h2 class="anchored" data-anchor-id="kernel-verification">Kernel Verification</h2>
<p>Once logged in, create a new notebook and verify you have access to:</p>
<ul>
<li><strong>Python 3</strong> (default kernel)</li>
<li><strong>R</strong> (R kernel)</li>
<li><strong>Bash</strong> (bash kernel)</li>
</ul>
</section>
<section id="customization-for-your-labs" class="level2">
<h2 class="anchored" data-anchor-id="customization-for-your-labs">Customization for Your Labs</h2>
<section id="add-additional-r-packages" class="level3">
<h3 class="anchored" data-anchor-id="add-additional-r-packages">Add Additional R Packages</h3>
<p>Modify the <code>Dockerfile</code> (before <code>USER ${NB_UID}</code>):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13"><pre class="sourceCode dockerfile code-with-copy"><code class="sourceCode dockerfile"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">RUN</span> <span class="ex">R</span> <span class="at">-e</span> <span class="st">"install.packages(c('your_package'), repos='http://cran.rstudio.com/')"</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<p>Then rerun <code>./start-jupyterhub.sh</code> to rebuild and restart.</p>
</section>
<section id="add-python-packages" class="level3">
<h3 class="anchored" data-anchor-id="add-python-packages">Add Python Packages</h3>
<p>Add to the <code>Dockerfile</code> (before <code>USER ${NB_UID}</code>):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14"><pre class="sourceCode dockerfile code-with-copy"><code class="sourceCode dockerfile"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">RUN</span> <span class="ex">pip</span> install numpy pandas matplotlib seaborn</span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
<p>Then rerun <code>./start-jupyterhub.sh</code> to rebuild and restart.</p>
</section>
<section id="change-port-if-8000-is-occupied" class="level3">
<h3 class="anchored" data-anchor-id="change-port-if-8000-is-occupied">Change Port (if 8000 is occupied)</h3>
<p>Modify in <code>docker-compose.yml</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ports</span><span class="kw">:</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="at"> </span><span class="kw">-</span><span class="at"> </span><span class="st">"8001:8000"</span><span class="co"> # Accessible on localhost:8001</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
</section>
</section>
<section id="advantages-of-this-approach" class="level2">
<h2 class="anchored" data-anchor-id="advantages-of-this-approach">Advantages of This Approach</h2>
<p><strong>Everything in Docker</strong>: No need to install Python/JupyterHub on your computer<br>
<strong>Portable</strong>: Easy to deploy on another server<br>
<strong>Isolated</strong>: No pollution of your system environment<br>
<strong>Easy to Clean</strong>: A simple <code>docker-compose down</code> is enough<br>
<strong>Reproducible</strong>: Students will have exactly the same environment</p>
</section>
<section id="troubleshooting" class="level2">
<h2 class="anchored" data-anchor-id="troubleshooting">Troubleshooting</h2>
<ul>
<li>Docker daemon unavailable: make sure OrbStack/Docker Desktop/daemon is running; verify <code>/var/run/docker.sock</code> exists.</li>
<li>Student containers do not start: check <code>docker-compose logs jupyterhub</code> and confirm the images exist with <code>docker images | grep jupyterhub-student</code>.</li>
<li>Port conflict: change the published port in <code>docker-compose.yml</code>.</li>
</ul>
<p><strong>I want to start from scratch</strong>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="bu">pushd</span> obijupyterhub</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="ex">docker-compose</span> down <span class="at">-v</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="ex">docker</span> rmi jupyterhub-hub jupyterhub-student</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="bu">popd</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="co"># Then rebuild everything</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="ex">./start-jupyterhub.sh</span></span></code></pre></div><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></div>
</section>
</section>
</main>
<!-- /main column -->
<script id="quarto-html-after-body" type="application/javascript">
window.document.addEventListener("DOMContentLoaded", function (event) {
const icon = "";
const anchorJS = new window.AnchorJS();
anchorJS.options = {
placement: 'right',
icon: icon
};
anchorJS.add('.anchored');
const isCodeAnnotation = (el) => {
for (const clz of el.classList) {
if (clz.startsWith('code-annotation-')) {
return true;
}
}
return false;
}
const onCopySuccess = function(e) {
// button target
const button = e.trigger;
// don't keep focus
button.blur();
// flash "checked"
button.classList.add('code-copy-button-checked');
var currentTitle = button.getAttribute("title");
button.setAttribute("title", "Copied!");
let tooltip;
if (window.bootstrap) {
button.setAttribute("data-bs-toggle", "tooltip");
button.setAttribute("data-bs-placement", "left");
button.setAttribute("data-bs-title", "Copied!");
tooltip = new bootstrap.Tooltip(button,
{ trigger: "manual",
customClass: "code-copy-button-tooltip",
offset: [0, -8]});
tooltip.show();
}
setTimeout(function() {
if (tooltip) {
tooltip.hide();
button.removeAttribute("data-bs-title");
button.removeAttribute("data-bs-toggle");
button.removeAttribute("data-bs-placement");
}
button.setAttribute("title", currentTitle);
button.classList.remove('code-copy-button-checked');
}, 1000);
// clear code selection
e.clearSelection();
}
const getTextToCopy = function(trigger) {
const outerScaffold = trigger.parentElement.cloneNode(true);
const codeEl = outerScaffold.querySelector('code');
for (const childEl of codeEl.children) {
if (isCodeAnnotation(childEl)) {
childEl.remove();
}
}
return codeEl.innerText;
}
const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
text: getTextToCopy
});
clipboard.on('success', onCopySuccess);
if (window.document.getElementById('quarto-embedded-source-code-modal')) {
const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
text: getTextToCopy,
container: window.document.getElementById('quarto-embedded-source-code-modal')
});
clipboardModal.on('success', onCopySuccess);
}
var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
var mailtoRegex = new RegExp(/^mailto:/);
var filterRegex = new RegExp('/' + window.location.host + '/');
var isInternal = (href) => {
return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
}
// Inspect non-navigation links and adorn them if external
var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
for (var i=0; i<links.length; i++) {
const link = links[i];
if (!isInternal(link.href)) {
// undo the damage that might have been done by quarto-nav.js in the case of
// links that we want to consider external
if (link.dataset.originalHref !== undefined) {
link.href = link.dataset.originalHref;
}
}
}
function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
const config = {
allowHTML: true,
maxWidth: 500,
delay: 100,
arrow: false,
appendTo: function(el) {
return el.parentElement;
},
interactive: true,
interactiveBorder: 10,
theme: 'quarto',
placement: 'bottom-start',
};
if (contentFn) {
config.content = contentFn;
}
if (onTriggerFn) {
config.onTrigger = onTriggerFn;
}
if (onUntriggerFn) {
config.onUntrigger = onUntriggerFn;
}
window.tippy(el, config);
}
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
for (var i=0; i<noterefs.length; i++) {
const ref = noterefs[i];
tippyHover(ref, function() {
// use id or data attribute instead here
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
try { href = new URL(href).hash; } catch {}
const id = href.replace(/^#\/?/, "");
const note = window.document.getElementById(id);
if (note) {
return note.innerHTML;
} else {
return "";
}
});
}
const xrefs = window.document.querySelectorAll('a.quarto-xref');
const processXRef = (id, note) => {
// Strip column container classes
const stripColumnClz = (el) => {
el.classList.remove("page-full", "page-columns");
if (el.children) {
for (const child of el.children) {
stripColumnClz(child);
}
}
}
stripColumnClz(note)
if (id === null || id.startsWith('sec-')) {
// Special case sections, only their first couple elements
const container = document.createElement("div");
if (note.children && note.children.length > 2) {
container.appendChild(note.children[0].cloneNode(true));
for (let i = 1; i < note.children.length; i++) {
const child = note.children[i];
if (child.tagName === "P" && child.innerText === "") {
continue;
} else {
container.appendChild(child.cloneNode(true));
break;
}
}
if (window.Quarto?.typesetMath) {
window.Quarto.typesetMath(container);
}
return container.innerHTML
} else {
if (window.Quarto?.typesetMath) {
window.Quarto.typesetMath(note);
}
return note.innerHTML;
}
} else {
// Remove any anchor links if they are present
const anchorLink = note.querySelector('a.anchorjs-link');
if (anchorLink) {
anchorLink.remove();
}
if (window.Quarto?.typesetMath) {
window.Quarto.typesetMath(note);
}
if (note.classList.contains("callout")) {
return note.outerHTML;
} else {
return note.innerHTML;
}
}
}
for (var i=0; i<xrefs.length; i++) {
const xref = xrefs[i];
tippyHover(xref, undefined, function(instance) {
instance.disable();
let url = xref.getAttribute('href');
let hash = undefined;
if (url.startsWith('#')) {
hash = url;
} else {
try { hash = new URL(url).hash; } catch {}
}
if (hash) {
const id = hash.replace(/^#\/?/, "");
const note = window.document.getElementById(id);
if (note !== null) {
try {
const html = processXRef(id, note.cloneNode(true));
instance.setContent(html);
} finally {
instance.enable();
instance.show();
}
} else {
// See if we can fetch this
fetch(url.split('#')[0])
.then(res => res.text())
.then(html => {
const parser = new DOMParser();
const htmlDoc = parser.parseFromString(html, "text/html");
const note = htmlDoc.getElementById(id);
if (note !== null) {
const html = processXRef(id, note);
instance.setContent(html);
}
}).finally(() => {
instance.enable();
instance.show();
});
}
} else {
// See if we can fetch a full url (with no hash to target)
// This is a special case and we should probably do some content thinning / targeting
fetch(url)
.then(res => res.text())
.then(html => {
const parser = new DOMParser();
const htmlDoc = parser.parseFromString(html, "text/html");
const note = htmlDoc.querySelector('main.content');
if (note !== null) {
// This should only happen for chapter cross references
// (since there is no id in the URL)
// remove the first header
if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
note.children[0].remove();
}
const html = processXRef(null, note);
instance.setContent(html);
}
}).finally(() => {
instance.enable();
instance.show();
});
}
}, function(instance) {
});
}
let selectedAnnoteEl;
const selectorForAnnotation = ( cell, annotation) => {
let cellAttr = 'data-code-cell="' + cell + '"';
let lineAttr = 'data-code-annotation="' + annotation + '"';
const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
return selector;
}
const selectCodeLines = (annoteEl) => {
const doc = window.document;
const targetCell = annoteEl.getAttribute("data-target-cell");
const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
const lines = annoteSpan.getAttribute("data-code-lines").split(",");
const lineIds = lines.map((line) => {
return targetCell + "-" + line;
})
let top = null;
let height = null;
let parent = null;
if (lineIds.length > 0) {
//compute the position of the single el (top and bottom and make a div)
const el = window.document.getElementById(lineIds[0]);
top = el.offsetTop;
height = el.offsetHeight;
parent = el.parentElement.parentElement;
if (lineIds.length > 1) {
const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
const bottom = lastEl.offsetTop + lastEl.offsetHeight;
height = bottom - top;
}
if (top !== null && height !== null && parent !== null) {
// cook up a div (if necessary) and position it
let div = window.document.getElementById("code-annotation-line-highlight");
if (div === null) {
div = window.document.createElement("div");
div.setAttribute("id", "code-annotation-line-highlight");
div.style.position = 'absolute';
parent.appendChild(div);
}
div.style.top = top - 2 + "px";
div.style.height = height + 4 + "px";
div.style.left = 0;
let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
if (gutterDiv === null) {
gutterDiv = window.document.createElement("div");
gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
gutterDiv.style.position = 'absolute';
const codeCell = window.document.getElementById(targetCell);
const gutter = codeCell.querySelector('.code-annotation-gutter');
gutter.appendChild(gutterDiv);
}
gutterDiv.style.top = top - 2 + "px";
gutterDiv.style.height = height + 4 + "px";
}
selectedAnnoteEl = annoteEl;
}
};
const unselectCodeLines = () => {
const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
elementsIds.forEach((elId) => {
const div = window.document.getElementById(elId);
if (div) {
div.remove();
}
});
selectedAnnoteEl = undefined;
};
// Handle positioning of the toggle
window.addEventListener(
"resize",
throttle(() => {
elRect = undefined;
if (selectedAnnoteEl) {
selectCodeLines(selectedAnnoteEl);
}
}, 10)
);
function throttle(fn, ms) {
let throttle = false;
let timer;
return (...args) => {
if(!throttle) { // first call gets through
fn.apply(this, args);
throttle = true;
} else { // all the others get throttled
if(timer) clearTimeout(timer); // cancel #2
timer = setTimeout(() => {
fn.apply(this, args);
timer = throttle = false;
}, ms);
}
};
}
// Attach click handler to the DT
const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
for (const annoteDlNode of annoteDls) {
annoteDlNode.addEventListener('click', (event) => {
const clickedEl = event.target;
if (clickedEl !== selectedAnnoteEl) {
unselectCodeLines();
const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
if (activeEl) {
activeEl.classList.remove('code-annotation-active');
}
selectCodeLines(clickedEl);
clickedEl.classList.add('code-annotation-active');
} else {
// Unselect the line
unselectCodeLines();
clickedEl.classList.remove('code-annotation-active');
}
});
}
const findCites = (el) => {
const parentEl = el.parentElement;
if (parentEl) {
const cites = parentEl.dataset.cites;
if (cites) {
return {
el,
cites: cites.split(' ')
};
} else {
return findCites(el.parentElement)
}
} else {
return undefined;
}
};
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
for (var i=0; i<bibliorefs.length; i++) {
const ref = bibliorefs[i];
const citeInfo = findCites(ref);
if (citeInfo) {
tippyHover(citeInfo.el, function() {
var popup = window.document.createElement('div');
citeInfo.cites.forEach(function(cite) {
var citeDiv = window.document.createElement('div');
citeDiv.classList.add('hanging-indent');
citeDiv.classList.add('csl-entry');
var biblioDiv = window.document.getElementById('ref-' + cite);
if (biblioDiv) {
citeDiv.innerHTML = biblioDiv.innerHTML;
}
popup.appendChild(citeDiv);
});
return popup.innerHTML;
});
}
}
});
</script>
</div> <!-- /content -->
</body></html>

283
Readme.md
View File

@@ -1,146 +1,106 @@
# JupyterHub Configuration with OrbStack on Mac (all in Docker)
# OBIJupyterHub - the DNA Metabarcoding Learning Server
## Prerequisites
## Intended use
You must have docker running on your computer
This project packages the MetabarcodingSchool training lab into one reproducible bundle. You get Python, R, and Bash kernels, a Quarto-built course website, and preconfigured admin/student accounts, so onboarding a class is a single command instead of a day of setup. Everything runs locally on a single machine, student work persists between sessions, and `./start-jupyterhub.sh` takes care of building images, rendering the site, preparing volumes, and bringing JupyterHub up at `http://localhost:8888`. Defaults (accounts, passwords, volumes) live in the repo so instructors can tweak them quickly.
- On MacOS, [OrbStack](https://orbstack.dev/ "A Docker implementation optimised for MacOS") is recommanded
## Prerequisites (with quick checks)
## Installation Steps
You need Docker, Docker Compose, Quarto, and Python 3 available on the machine that will host the lab.
### 1. Create Directory Structure
- macOS: install [OrbStack](https://orbstack.dev/) (recommended) or Docker Desktop; both ship Docker Engine and Compose.
- Linux: install Docker Engine and the Compose plugin from your distribution (e.g., `sudo apt install docker.io docker-compose-plugin`) or from Dockers official packages.
- Windows: install Docker Desktop with the WSL2 backend enabled.
- Quarto CLI: get installers from <https://quarto.org/docs/get-started/>.
- Python 3: any recent version is fine (only the standard library is used).
Verify from a terminal; if a command is missing, install it before moving on:
```bash
docker --version
docker compose version # or: docker-compose --version
quarto --version
python3 --version
```
## How the startup script works
`./start-jupyterhub.sh` is the single entry point. It builds the Docker images, renders the course website, prepares the volume folders, and starts the stack. Internally it:
- creates the `jupyterhub_volumes/` tree (caddy, course, shared, users, web…)
- builds `jupyterhub-student` and `jupyterhub-hub` images
- renders the Quarto site from `web_src/`, generates PDF galleries and `pages.json`, and copies everything into `jupyterhub_volumes/web/`
- runs `docker-compose up -d --remove-orphans`
You can tailor what it does with a few flags:
- `--no-build` (or `--offline`): skip Docker image builds and reuse existing images (useful when offline).
- `--force-rebuild`: rebuild images without cache.
- `--stop-server`: stop the stack and remove student containers, then exit.
- `--update-lectures`: rebuild the course website only (no Docker stop/start).
- `--build-obidoc`: force rebuilding the obidoc documentation (auto-built if empty; skipped in offline mode).
## Installation and first run
1) Clone the project:
```bash
git clone https://forge.metabarcoding.org/MetabarcodingSchool/OBIJupyterHub.git
```
Enter into the `OBIJupyterHub` directory
```bash
cd OBIJupyterHub
```
#### File Structure
Your `OBIJupyterHub` directory should contain:
2) (Optional) glance at the structure youll populate:
```
OBIJupyterHub
├── start-jupyterhub.sh - The script used to setup and start the server
├── obijupyterhub - The files describing the docker images and the stack
│   ├── Caddyfile
├── start-jupyterhub.sh - single entry point (build + render + start)
├── obijupyterhub - Docker images and stack definitions
│   ├── docker-compose.yml
│   ├── Dockerfile
│   ├── Dockerfile.hub
│   ── jupyterhub_config.py
│   ├── sftpgo_config.json
│   ── start-notebook.sh
├── jupyterhub_volumes - The directory containing the docker volumes
│   ├── caddy
│   ── course - Read only volume mounted on every student container
│   │   ├── bin
│   │   └── R_packages
│   ├── jupyterhub
│   ├── shared - Read write volume shared in every student container
│   ├── users
│   └── web
│   ├── img
│   │   └── welcome_metabar.webp
│   ├── index.html
│   └── pages
├── Readme.md - This documentation
├── tools
│   ├── generate_pages_json.py
│   └── install_packages.sh
└─── web_src - The quarto document sources used to build the web site
   ├── _output
   ├── _quarto.yml
   ├── 00_home.qmd
   ├── lectures
   │   └── computers
   │   └── regex
   │   ├── lecture_regex.qmd
   │   ├── slides_regex.qmd
   │   └── slides.css
   └── scripts
   └── copy-to-web.sh
│   ── jupyterhub_config.py
├── jupyterhub_volumes - data persisted on the host
│   ── course - read-only for students (notebooks, data, bin, R packages)
│   ├── shared - shared read/write space for everyone
│   ├── users - per-user persistent data
│   ── web - rendered course website
└── web_src - Quarto sources for the course website
```
### 2. Start JupyterHub
3) Prepare course materials (optional before first run):
- Put notebooks, datasets, scripts, binaries, or PDFs for students under `jupyterhub_volumes/course/`. They will appear read-only at `/home/jovyan/work/course/`.
- For collaborative work, drop files in `jupyterhub_volumes/shared/` (read/write for all at `/home/jovyan/work/shared/`).
- Edit or add Quarto sources in `web_src/` to update the course website; the script will render them.
From the terminal, in the `OBIJupyterHub` directory, run the following command:
4) Start everything (build + render + launch):
``` bash
```bash
./start-jupyterhub.sh
```
### 3. Access JupyterHub
5) Access JupyterHub in a browser at `http://localhost:8888`.
Open your browser and go to: **http://localhost:8888**
6) Stop the stack when youre done (run from `obijupyterhub/`):
You can log in as a student with any username and password: `metabar2025`
## Useful Commands
### View JupyterHub logs
``` bash
cd obijupyterhub
docker-compose logs -f jupyterhub
```
### View all containers (hub + students)
``` bash
docker ps | grep jupyterhub
```
### Stop JupyterHub
``` bash
cd obijupyterhub
```bash
docker-compose down
```
### Restart JupyterHub (after config modification)
### Operating the stack (one command, a few options)
``` bash
cd obijupyterhub
docker-compose restart jupyterhub
```
- Start or rebuild: `./start-jupyterhub.sh` (rebuilds images, regenerates the website, starts the stack).
- Start without rebuilding images (offline): `./start-jupyterhub.sh --no-build`
- Force rebuild without cache: `./start-jupyterhub.sh --force-rebuild`
- Stop only: `./start-jupyterhub.sh --stop-server`
- Rebuild website only (no Docker stop/start): `./start-jupyterhub.sh --update-lectures`
- Rebuild obidoc docs: `./start-jupyterhub.sh --build-obidoc` (also builds automatically if `jupyterhub_volumes/web/obidoc` is empty; skipped in offline mode)
- Access at `http://localhost:8888` (students: any username / password `metabar2025`; admin: `admin` / `admin2025`).
- Check logs from `obijupyterhub/` with `docker-compose logs -f jupyterhub`.
- Stop with `docker-compose down` (from `obijupyterhub/`). Rerun `./start-jupyterhub.sh` to start again or after config changes.
### View logs for a specific student
## Managing shared data
``` bash
docker logs jupyter-<username>
```
Replace `<username>` by the actual username of the student.
### Clean up after lab
``` bash
# Stop and remove all containers
cd obijupyterhub
docker-compose down
# Remove student containers
docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f
# Remove volumes (WARNING: deletes student data)
docker volume ls | grep jupyterhub-user | awk '{print $2}' | xargs docker volume rm
# Clean everything (containers + volumes + network)
docker-compose down -v
docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f
docker volume prune -f
```
## Managing Shared Data
### Directory Structure for Each Student
Each student will see this directory structure in their JupyterLab (everything under `work/` is persistent):
Each student lands in `/home/jovyan/work/` with three key areas: their own files, a shared space, and a read-only course space. Everything under `work/` is persisted on the host in `jupyterhub_volumes`.
```
work/ # Personal workspace root (persistent)
@@ -153,42 +113,22 @@ work/ # Personal workspace root (persistent)
└── [course materials] # Your course files
```
**R Package Priority:**
1. R checks `work/R_packages/` first (personal, writable)
1. Then `work/course/R_packages/` (shared, read-only, installed by prof)
1. Then system libraries
**Important:** Everything is under `work/`, so all student files are automatically saved in their persistent volume.
R looks for packages in this order: personal `work/R_packages/`, then shared `work/course/R_packages/`, then system libraries. Because everything lives under `work/`, student files survive restarts.
### User Accounts
**Admin Account:**
- Username: `admin`
- Password: `admin2025` (change in docker-compose.yml: `JUPYTERHUB_ADMIN_PASSWORD`)
- Can write to `course/` directory
**Student Accounts:**
- Username: any name
- Password: `metabar2025` (change in docker-compose.yml: `JUPYTERHUB_PASSWORD`)
- Read-only access to `course/` directory
Defaults are defined in `obijupyterhub/docker-compose.yml`: admin (`admin` / `admin2025`) with write access to `course/`, and students (any username, password `metabar2025`) with read-only access to `course/`. Adjust `JUPYTERHUB_ADMIN_PASSWORD` and `JUPYTERHUB_PASSWORD` there, then rerun `./start-jupyterhub.sh`.
### Installing R Packages (Admin Only)
**From your Mac (recommended):**
From the host, install shared R packages into `course/R_packages/`:
``` bash
# Install packages
tools/install_packages.sh reshape2 plotly knitr
```
This script: - Installs packages in the `course/R_packages/` directory - All students can use them (read-only) - No need to rebuild the image
**Students can also install their own packages:**
Students can install packages in their personal `work/R_packages/`:
Students can install their own packages into their personal `work/R_packages/`:
```r
# Install in personal library (each student has their own)
@@ -223,43 +163,9 @@ list.files("/home/jovyan/work/R_packages")
list.files("/home/jovyan/work/course/R_packages")
```
### Deposit Files for Course
### Deposit or retrieve course and student files
To put files in the `course/` directory (accessible read-only):
``` bash
# Create a temporary directory
mkdir -p ~/jupyterhub-tp/course-files
# Copy your files into it
cp my_notebooks.ipynb ~/jupyterhub-tp/course-files/
cp my_data.csv ~/jupyterhub-tp/course-files/
# Copy into Docker volume
docker run --rm \
-v jupyterhub-course:/target \
-v ~/jupyterhub-tp/course-files:/source \
alpine sh -c "cp -r /source/* /target/"
```
### Retrieve Student Work
``` bash
# List user volumes
docker volume ls | grep 'obijupyterhub_user-'
# Copy files from a specific student
docker run --rm \
-v obijupyterhub_user-alice:/source \
-v ~/submissions:/target \
alpine sh -c "cp -r /source/* /target/alice/"
# Copy all shared work
docker run --rm \
-v obijupyterhub_shared:/source \
-v ~/submissions/shared:/target \
alpine sh -c "cp -r /source/* /target/"
```
On the host, place course files in `jupyterhub_volumes/course/` (they appear read-only to students), shared files in `jupyterhub_volumes/shared/`, and collect student work from `jupyterhub_volumes/users/`.
## User Management
@@ -299,11 +205,7 @@ Modify the `Dockerfile` (before `USER ${NB_UID}`):
RUN R -e "install.packages(c('your_package'), repos='http://cran.rstudio.com/')"
```
Then restart the server (it rebuilds the images if needed):
```bash
./start-jupyterhub.sh
```
Then rerun `./start-jupyterhub.sh` to rebuild and restart.
### Add Python Packages
@@ -313,14 +215,7 @@ Add to the `Dockerfile` (before `USER ${NB_UID}`):
RUN pip install numpy pandas matplotlib seaborn
```
### Distribute Files to Students
Create a `files_lab/` directory and add to the `Dockerfile`:
``` dockerfile
COPY files_lab/ /home/${NB_USER}/lab/
RUN chown -R ${NB_UID}:${NB_GID} /home/${NB_USER}/lab
```
Then rerun `./start-jupyterhub.sh` to rebuild and restart.
### Change Port (if 8000 is occupied)
@@ -341,29 +236,19 @@ ports:
## Troubleshooting
**Error "Cannot connect to Docker daemon"**:
- Check that OrbStack is running
- Verify the socket exists: `ls -la /var/run/docker.sock`
**Student containers don't start**:
- Check logs: `docker-compose logs jupyterhub`
- Verify student image exists: `docker images | grep jupyterhub-student`
**Port 8000 already in use**:
- Change port in `docker-compose.yml`
- Docker daemon unavailable: make sure OrbStack/Docker Desktop/daemon is running; verify `/var/run/docker.sock` exists.
- Student containers do not start: check `docker-compose logs jupyterhub` and confirm the images exist with `docker images | grep jupyterhub-student`.
- Port conflict: change the published port in `docker-compose.yml`.
**I want to start from scratch**:
``` bash
push obijupyterhub
pushd obijupyterhub
docker-compose down -v
docker rmi jupyterhub-hub jupyterhub-student
popd
# Then rebuild everything
./start-jupyterhub.sh
```
```

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,145 @@
class QuartoAxeReporter {
constructor(axeResult, options) {
this.axeResult = axeResult;
this.options = options;
}
report() {
throw new Error("report() is an abstract method");
}
}
class QuartoAxeJsonReporter extends QuartoAxeReporter {
constructor(axeResult, options) {
super(axeResult, options);
}
report() {
console.log(JSON.stringify(this.axeResult, null, 2));
}
}
class QuartoAxeConsoleReporter extends QuartoAxeReporter {
constructor(axeResult, options) {
super(axeResult, options);
}
report() {
for (const violation of this.axeResult.violations) {
console.log(violation.description);
for (const node of violation.nodes) {
for (const target of node.target) {
console.log(target);
console.log(document.querySelector(target));
}
}
}
}
}
class QuartoAxeDocumentReporter extends QuartoAxeReporter {
constructor(axeResult, options) {
super(axeResult, options);
}
createViolationElement(violation) {
const violationElement = document.createElement("div");
const descriptionElement = document.createElement("div");
descriptionElement.className = "quarto-axe-violation-description";
descriptionElement.innerText = `${violation.impact.replace(/^[a-z]/, match => match.toLocaleUpperCase())}: ${violation.description}`;
violationElement.appendChild(descriptionElement);
const helpElement = document.createElement("div");
helpElement.className = "quarto-axe-violation-help";
helpElement.innerText = violation.help;
violationElement.appendChild(helpElement);
const nodesElement = document.createElement("div");
nodesElement.className = "quarto-axe-violation-nodes";
violationElement.appendChild(nodesElement);
const nodeElement = document.createElement("div");
nodeElement.className = "quarto-axe-violation-selector";
for (const node of violation.nodes) {
for (const target of node.target) {
const targetElement = document.createElement("span");
targetElement.className = "quarto-axe-violation-target";
targetElement.innerText = target;
nodeElement.appendChild(targetElement);
nodeElement.addEventListener("mouseenter", () => {
const element = document.querySelector(target);
if (element) {
element.scrollIntoView({ behavior: "smooth", block: "center" });
element.classList.add("quarto-axe-hover-highlight");
setTimeout(() => {
element.style.border = "";
}, 2000);
}
});
nodeElement.addEventListener("mouseleave", () => {
const element = document.querySelector(target);
if (element) {
element.classList.remove("quarto-axe-hover-highlight");
}
});
nodeElement.addEventListener("click", () => {
console.log(document.querySelector(target));
});
nodeElement.appendChild(targetElement);
}
nodesElement.appendChild(nodeElement);
}
return violationElement;
}
report() {
const violations = this.axeResult.violations;
const reportElement = document.createElement("div");
reportElement.className = "quarto-axe-report";
if (violations.length === 0) {
const noViolationsElement = document.createElement("div");
noViolationsElement.className = "quarto-axe-no-violations";
noViolationsElement.innerText = "No axe-core violations found.";
reportElement.appendChild(noViolationsElement);
}
violations.forEach((violation) => {
reportElement.appendChild(this.createViolationElement(violation));
});
document.querySelector("main").appendChild(reportElement);
}
}
const reporters = {
json: QuartoAxeJsonReporter,
console: QuartoAxeConsoleReporter,
document: QuartoAxeDocumentReporter,
};
class QuartoAxeChecker {
constructor(opts) {
this.options = opts;
}
async init() {
const axe = (await import("https://cdn.skypack.dev/pin/axe-core@v4.10.3-aVOFXWsJaCpVrtv89pCa/mode=imports,min/optimized/axe-core.js")).default;
const result = await axe.run({
exclude: [
// https://github.com/microsoft/tabster/issues/288
// MS has claimed they won't fix this, so we need to add an exclusion to
// all tabster elements
"[data-tabster-dummy]"
],
preload: { assets: ['cssom'], timeout: 50000 }
});
const reporter = this.options === true ? new QuartoAxeConsoleReporter(result) : new reporters[this.options.output](result, this.options);
reporter.report();
}
}
export async function init() {
const opts = document.querySelector("#quarto-axe-checker-options");
if (opts) {
const jsonOptions = JSON.parse(atob(opts.textContent));
const checker = new QuartoAxeChecker(jsonOptions);
await checker.init();
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,236 @@
/* quarto syntax highlight colors */
:root {
--quarto-hl-ot-color: #003B4F;
--quarto-hl-at-color: #657422;
--quarto-hl-ss-color: #20794D;
--quarto-hl-an-color: #5E5E5E;
--quarto-hl-fu-color: #4758AB;
--quarto-hl-st-color: #20794D;
--quarto-hl-cf-color: #003B4F;
--quarto-hl-op-color: #5E5E5E;
--quarto-hl-er-color: #AD0000;
--quarto-hl-bn-color: #AD0000;
--quarto-hl-al-color: #AD0000;
--quarto-hl-va-color: #111111;
--quarto-hl-bu-color: inherit;
--quarto-hl-ex-color: inherit;
--quarto-hl-pp-color: #AD0000;
--quarto-hl-in-color: #5E5E5E;
--quarto-hl-vs-color: #20794D;
--quarto-hl-wa-color: #5E5E5E;
--quarto-hl-do-color: #5E5E5E;
--quarto-hl-im-color: #00769E;
--quarto-hl-ch-color: #20794D;
--quarto-hl-dt-color: #AD0000;
--quarto-hl-fl-color: #AD0000;
--quarto-hl-co-color: #5E5E5E;
--quarto-hl-cv-color: #5E5E5E;
--quarto-hl-cn-color: #8f5902;
--quarto-hl-sc-color: #5E5E5E;
--quarto-hl-dv-color: #AD0000;
--quarto-hl-kw-color: #003B4F;
}
/* other quarto variables */
:root {
--quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
/* syntax highlight based on Pandoc's rules */
pre > code.sourceCode > span {
color: #003B4F;
}
code.sourceCode > span {
color: #003B4F;
}
div.sourceCode,
div.sourceCode pre.sourceCode {
color: #003B4F;
}
/* Normal */
code span {
color: #003B4F;
}
/* Alert */
code span.al {
color: #AD0000;
font-style: inherit;
}
/* Annotation */
code span.an {
color: #5E5E5E;
font-style: inherit;
}
/* Attribute */
code span.at {
color: #657422;
font-style: inherit;
}
/* BaseN */
code span.bn {
color: #AD0000;
font-style: inherit;
}
/* BuiltIn */
code span.bu {
font-style: inherit;
}
/* ControlFlow */
code span.cf {
color: #003B4F;
font-weight: bold;
font-style: inherit;
}
/* Char */
code span.ch {
color: #20794D;
font-style: inherit;
}
/* Constant */
code span.cn {
color: #8f5902;
font-style: inherit;
}
/* Comment */
code span.co {
color: #5E5E5E;
font-style: inherit;
}
/* CommentVar */
code span.cv {
color: #5E5E5E;
font-style: italic;
}
/* Documentation */
code span.do {
color: #5E5E5E;
font-style: italic;
}
/* DataType */
code span.dt {
color: #AD0000;
font-style: inherit;
}
/* DecVal */
code span.dv {
color: #AD0000;
font-style: inherit;
}
/* Error */
code span.er {
color: #AD0000;
font-style: inherit;
}
/* Extension */
code span.ex {
font-style: inherit;
}
/* Float */
code span.fl {
color: #AD0000;
font-style: inherit;
}
/* Function */
code span.fu {
color: #4758AB;
font-style: inherit;
}
/* Import */
code span.im {
color: #00769E;
font-style: inherit;
}
/* Information */
code span.in {
color: #5E5E5E;
font-style: inherit;
}
/* Keyword */
code span.kw {
color: #003B4F;
font-weight: bold;
font-style: inherit;
}
/* Operator */
code span.op {
color: #5E5E5E;
font-style: inherit;
}
/* Other */
code span.ot {
color: #003B4F;
font-style: inherit;
}
/* Preprocessor */
code span.pp {
color: #AD0000;
font-style: inherit;
}
/* SpecialChar */
code span.sc {
color: #5E5E5E;
font-style: inherit;
}
/* SpecialString */
code span.ss {
color: #20794D;
font-style: inherit;
}
/* String */
code span.st {
color: #20794D;
font-style: inherit;
}
/* Variable */
code span.va {
color: #111111;
font-style: inherit;
}
/* VerbatimString */
code span.vs {
color: #20794D;
font-style: inherit;
}
/* Warning */
code span.wa {
color: #5E5E5E;
font-style: italic;
}
.prevent-inlining {
content: "</";
}
/*# sourceMappingURL=2dce1cc6c82594539e1579de68416b47.css.map */

View File

@@ -0,0 +1,847 @@
import * as tabsets from "./tabsets/tabsets.js";
import * as axe from "./axe/axe-check.js";
const sectionChanged = new CustomEvent("quarto-sectionChanged", {
detail: {},
bubbles: true,
cancelable: false,
composed: false,
});
const layoutMarginEls = () => {
// Find any conflicting margin elements and add margins to the
// top to prevent overlap
const marginChildren = window.document.querySelectorAll(
".column-margin.column-container > *, .margin-caption, .aside"
);
let lastBottom = 0;
for (const marginChild of marginChildren) {
if (marginChild.offsetParent !== null) {
// clear the top margin so we recompute it
marginChild.style.marginTop = null;
const top = marginChild.getBoundingClientRect().top + window.scrollY;
if (top < lastBottom) {
const marginChildStyle = window.getComputedStyle(marginChild);
const marginBottom = parseFloat(marginChildStyle["marginBottom"]);
const margin = lastBottom - top + marginBottom;
marginChild.style.marginTop = `${margin}px`;
}
const styles = window.getComputedStyle(marginChild);
const marginTop = parseFloat(styles["marginTop"]);
lastBottom = top + marginChild.getBoundingClientRect().height + marginTop;
}
}
};
window.document.addEventListener("DOMContentLoaded", function (_event) {
// Recompute the position of margin elements anytime the body size changes
if (window.ResizeObserver) {
const resizeObserver = new window.ResizeObserver(
throttle(() => {
layoutMarginEls();
if (
window.document.body.getBoundingClientRect().width < 990 &&
isReaderMode()
) {
quartoToggleReader();
}
}, 50)
);
resizeObserver.observe(window.document.body);
}
const tocEl = window.document.querySelector('nav.toc-active[role="doc-toc"]');
const sidebarEl = window.document.getElementById("quarto-sidebar");
const leftTocEl = window.document.getElementById("quarto-sidebar-toc-left");
const marginSidebarEl = window.document.getElementById(
"quarto-margin-sidebar"
);
// function to determine whether the element has a previous sibling that is active
const prevSiblingIsActiveLink = (el) => {
const sibling = el.previousElementSibling;
if (sibling && sibling.tagName === "A") {
return sibling.classList.contains("active");
} else {
return false;
}
};
// dispatch for htmlwidgets
// they use slideenter event to trigger resize
function fireSlideEnter() {
const event = window.document.createEvent("Event");
event.initEvent("slideenter", true, true);
window.document.dispatchEvent(event);
}
const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]');
tabs.forEach((tab) => {
tab.addEventListener("shown.bs.tab", fireSlideEnter);
});
// dispatch for shiny
// they use BS shown and hidden events to trigger rendering
function distpatchShinyEvents(previous, current) {
if (window.jQuery) {
if (previous) {
window.jQuery(previous).trigger("hidden");
}
if (current) {
window.jQuery(current).trigger("shown");
}
}
}
// tabby.js listener: Trigger event for htmlwidget and shiny
document.addEventListener(
"tabby",
function (event) {
fireSlideEnter();
distpatchShinyEvents(event.detail.previousTab, event.detail.tab);
},
false
);
// Track scrolling and mark TOC links as active
// get table of contents and sidebar (bail if we don't have at least one)
const tocLinks = tocEl
? [...tocEl.querySelectorAll("a[data-scroll-target]")]
: [];
const makeActive = (link) => tocLinks[link].classList.add("active");
const removeActive = (link) => tocLinks[link].classList.remove("active");
const removeAllActive = () =>
[...Array(tocLinks.length).keys()].forEach((link) => removeActive(link));
// activate the anchor for a section associated with this TOC entry
tocLinks.forEach((link) => {
link.addEventListener("click", () => {
if (link.href.indexOf("#") !== -1) {
const anchor = link.href.split("#")[1];
const heading = window.document.querySelector(
`[data-anchor-id="${anchor}"]`
);
if (heading) {
// Add the class
heading.classList.add("reveal-anchorjs-link");
// function to show the anchor
const handleMouseout = () => {
heading.classList.remove("reveal-anchorjs-link");
heading.removeEventListener("mouseout", handleMouseout);
};
// add a function to clear the anchor when the user mouses out of it
heading.addEventListener("mouseout", handleMouseout);
}
}
});
});
const sections = tocLinks.map((link) => {
const target = link.getAttribute("data-scroll-target");
if (target.startsWith("#")) {
return window.document.getElementById(decodeURI(`${target.slice(1)}`));
} else {
return window.document.querySelector(decodeURI(`${target}`));
}
});
const sectionMargin = 200;
let currentActive = 0;
// track whether we've initialized state the first time
let init = false;
const updateActiveLink = () => {
// The index from bottom to top (e.g. reversed list)
let sectionIndex = -1;
if (
window.innerHeight + window.pageYOffset >=
window.document.body.offsetHeight
) {
// This is the no-scroll case where last section should be the active one
sectionIndex = 0;
} else {
// This finds the last section visible on screen that should be made active
sectionIndex = [...sections].reverse().findIndex((section) => {
if (section) {
return window.pageYOffset >= section.offsetTop - sectionMargin;
} else {
return false;
}
});
}
if (sectionIndex > -1) {
const current = sections.length - sectionIndex - 1;
if (current !== currentActive) {
removeAllActive();
currentActive = current;
makeActive(current);
if (init) {
window.dispatchEvent(sectionChanged);
}
init = true;
}
}
};
const inHiddenRegion = (top, bottom, hiddenRegions) => {
for (const region of hiddenRegions) {
if (top <= region.bottom && bottom >= region.top) {
return true;
}
}
return false;
};
const categorySelector = "header.quarto-title-block .quarto-category";
const activateCategories = (href) => {
// Find any categories
// Surround them with a link pointing back to:
// #category=Authoring
try {
const categoryEls = window.document.querySelectorAll(categorySelector);
for (const categoryEl of categoryEls) {
const categoryText = categoryEl.textContent;
if (categoryText) {
const link = `${href}#category=${encodeURIComponent(categoryText)}`;
const linkEl = window.document.createElement("a");
linkEl.setAttribute("href", link);
for (const child of categoryEl.childNodes) {
linkEl.append(child);
}
categoryEl.appendChild(linkEl);
}
}
} catch {
// Ignore errors
}
};
function hasTitleCategories() {
return window.document.querySelector(categorySelector) !== null;
}
function offsetRelativeUrl(url) {
const offset = getMeta("quarto:offset");
return offset ? offset + url : url;
}
function offsetAbsoluteUrl(url) {
const offset = getMeta("quarto:offset");
const baseUrl = new URL(offset, window.location);
const projRelativeUrl = url.replace(baseUrl, "");
if (projRelativeUrl.startsWith("/")) {
return projRelativeUrl;
} else {
return "/" + projRelativeUrl;
}
}
// read a meta tag value
function getMeta(metaName) {
const metas = window.document.getElementsByTagName("meta");
for (let i = 0; i < metas.length; i++) {
if (metas[i].getAttribute("name") === metaName) {
return metas[i].getAttribute("content");
}
}
return "";
}
async function findAndActivateCategories() {
// Categories search with listing only use path without query
const currentPagePath = offsetAbsoluteUrl(
window.location.origin + window.location.pathname
);
const response = await fetch(offsetRelativeUrl("listings.json"));
if (response.status == 200) {
return response.json().then(function (listingPaths) {
const listingHrefs = [];
for (const listingPath of listingPaths) {
const pathWithoutLeadingSlash = listingPath.listing.substring(1);
for (const item of listingPath.items) {
const encodedItem = encodeURI(item);
if (
encodedItem === currentPagePath ||
encodedItem === currentPagePath + "index.html"
) {
// Resolve this path against the offset to be sure
// we already are using the correct path to the listing
// (this adjusts the listing urls to be rooted against
// whatever root the page is actually running against)
const relative = offsetRelativeUrl(pathWithoutLeadingSlash);
const baseUrl = window.location;
const resolvedPath = new URL(relative, baseUrl);
listingHrefs.push(resolvedPath.pathname);
break;
}
}
}
// Look up the tree for a nearby linting and use that if we find one
const nearestListing = findNearestParentListing(
offsetAbsoluteUrl(window.location.pathname),
listingHrefs
);
if (nearestListing) {
activateCategories(nearestListing);
} else {
// See if the referrer is a listing page for this item
const referredRelativePath = offsetAbsoluteUrl(document.referrer);
const referrerListing = listingHrefs.find((listingHref) => {
const isListingReferrer =
listingHref === referredRelativePath ||
listingHref === referredRelativePath + "index.html";
return isListingReferrer;
});
if (referrerListing) {
// Try to use the referrer if possible
activateCategories(referrerListing);
} else if (listingHrefs.length > 0) {
// Otherwise, just fall back to the first listing
activateCategories(listingHrefs[0]);
}
}
});
}
}
if (hasTitleCategories()) {
findAndActivateCategories();
}
const findNearestParentListing = (href, listingHrefs) => {
if (!href || !listingHrefs) {
return undefined;
}
// Look up the tree for a nearby linting and use that if we find one
const relativeParts = href.substring(1).split("/");
while (relativeParts.length > 0) {
const path = relativeParts.join("/");
for (const listingHref of listingHrefs) {
if (listingHref.startsWith(path)) {
return listingHref;
}
}
relativeParts.pop();
}
return undefined;
};
const manageSidebarVisiblity = (el, placeholderDescriptor) => {
let isVisible = true;
let elRect;
return (hiddenRegions) => {
if (el === null) {
return;
}
// Find the last element of the TOC
const lastChildEl = el.lastElementChild;
if (lastChildEl) {
// Converts the sidebar to a menu
const convertToMenu = () => {
for (const child of el.children) {
child.style.opacity = 0;
child.style.overflow = "hidden";
child.style.pointerEvents = "none";
}
nexttick(() => {
const toggleContainer = window.document.createElement("div");
toggleContainer.style.width = "100%";
toggleContainer.classList.add("zindex-over-content");
toggleContainer.classList.add("quarto-sidebar-toggle");
toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom
toggleContainer.id = placeholderDescriptor.id;
toggleContainer.style.position = "fixed";
const toggleIcon = window.document.createElement("i");
toggleIcon.classList.add("quarto-sidebar-toggle-icon");
toggleIcon.classList.add("bi");
toggleIcon.classList.add("bi-caret-down-fill");
const toggleTitle = window.document.createElement("div");
const titleEl = window.document.body.querySelector(
placeholderDescriptor.titleSelector
);
if (titleEl) {
toggleTitle.append(
titleEl.textContent || titleEl.innerText,
toggleIcon
);
}
toggleTitle.classList.add("zindex-over-content");
toggleTitle.classList.add("quarto-sidebar-toggle-title");
toggleContainer.append(toggleTitle);
const toggleContents = window.document.createElement("div");
toggleContents.classList = el.classList;
toggleContents.classList.add("zindex-over-content");
toggleContents.classList.add("quarto-sidebar-toggle-contents");
for (const child of el.children) {
if (child.id === "toc-title") {
continue;
}
const clone = child.cloneNode(true);
clone.style.opacity = 1;
clone.style.pointerEvents = null;
clone.style.display = null;
toggleContents.append(clone);
}
toggleContents.style.height = "0px";
const positionToggle = () => {
// position the element (top left of parent, same width as parent)
if (!elRect) {
elRect = el.getBoundingClientRect();
}
toggleContainer.style.left = `${elRect.left}px`;
toggleContainer.style.top = `${elRect.top}px`;
toggleContainer.style.width = `${elRect.width}px`;
};
positionToggle();
toggleContainer.append(toggleContents);
el.parentElement.prepend(toggleContainer);
// Process clicks
let tocShowing = false;
// Allow the caller to control whether this is dismissed
// when it is clicked (e.g. sidebar navigation supports
// opening and closing the nav tree, so don't dismiss on click)
const clickEl = placeholderDescriptor.dismissOnClick
? toggleContainer
: toggleTitle;
const closeToggle = () => {
if (tocShowing) {
toggleContainer.classList.remove("expanded");
toggleContents.style.height = "0px";
tocShowing = false;
}
};
// Get rid of any expanded toggle if the user scrolls
window.document.addEventListener(
"scroll",
throttle(() => {
closeToggle();
}, 50)
);
// Handle positioning of the toggle
window.addEventListener(
"resize",
throttle(() => {
elRect = undefined;
positionToggle();
}, 50)
);
window.addEventListener("quarto-hrChanged", () => {
elRect = undefined;
});
// Process the click
clickEl.onclick = () => {
if (!tocShowing) {
toggleContainer.classList.add("expanded");
toggleContents.style.height = null;
tocShowing = true;
} else {
closeToggle();
}
};
});
};
// Converts a sidebar from a menu back to a sidebar
const convertToSidebar = () => {
for (const child of el.children) {
child.style.opacity = 1;
child.style.overflow = null;
child.style.pointerEvents = null;
}
const placeholderEl = window.document.getElementById(
placeholderDescriptor.id
);
if (placeholderEl) {
placeholderEl.remove();
}
el.classList.remove("rollup");
};
if (isReaderMode()) {
convertToMenu();
isVisible = false;
} else {
// Find the top and bottom o the element that is being managed
const elTop = el.offsetTop;
const elBottom =
elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight;
if (!isVisible) {
// If the element is current not visible reveal if there are
// no conflicts with overlay regions
if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) {
convertToSidebar();
isVisible = true;
}
} else {
// If the element is visible, hide it if it conflicts with overlay regions
// and insert a placeholder toggle (or if we're in reader mode)
if (inHiddenRegion(elTop, elBottom, hiddenRegions)) {
convertToMenu();
isVisible = false;
}
}
}
}
};
};
const tabEls = document.querySelectorAll('a[data-bs-toggle="tab"]');
for (const tabEl of tabEls) {
const id = tabEl.getAttribute("data-bs-target");
if (id) {
const columnEl = document.querySelector(
`${id} .column-margin, .tabset-margin-content`
);
if (columnEl)
tabEl.addEventListener("shown.bs.tab", function (event) {
const el = event.srcElement;
if (el) {
const visibleCls = `${el.id}-margin-content`;
// walk up until we find a parent tabset
let panelTabsetEl = el.parentElement;
while (panelTabsetEl) {
if (panelTabsetEl.classList.contains("panel-tabset")) {
break;
}
panelTabsetEl = panelTabsetEl.parentElement;
}
if (panelTabsetEl) {
const prevSib = panelTabsetEl.previousElementSibling;
if (
prevSib &&
prevSib.classList.contains("tabset-margin-container")
) {
const childNodes = prevSib.querySelectorAll(
".tabset-margin-content"
);
for (const childEl of childNodes) {
if (childEl.classList.contains(visibleCls)) {
childEl.classList.remove("collapse");
} else {
childEl.classList.add("collapse");
}
}
}
}
}
layoutMarginEls();
});
}
}
// Manage the visibility of the toc and the sidebar
const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, {
id: "quarto-toc-toggle",
titleSelector: "#toc-title",
dismissOnClick: true,
});
const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, {
id: "quarto-sidebarnav-toggle",
titleSelector: ".title",
dismissOnClick: false,
});
let tocLeftScrollVisibility;
if (leftTocEl) {
tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, {
id: "quarto-lefttoc-toggle",
titleSelector: "#toc-title",
dismissOnClick: true,
});
}
// Find the first element that uses formatting in special columns
const conflictingEls = window.document.body.querySelectorAll(
'[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]'
);
// Filter all the possibly conflicting elements into ones
// the do conflict on the left or ride side
const arrConflictingEls = Array.from(conflictingEls);
const leftSideConflictEls = arrConflictingEls.filter((el) => {
if (el.tagName === "ASIDE") {
return false;
}
return Array.from(el.classList).find((className) => {
return (
className !== "column-body" &&
className.startsWith("column-") &&
!className.endsWith("right") &&
!className.endsWith("container") &&
className !== "column-margin"
);
});
});
const rightSideConflictEls = arrConflictingEls.filter((el) => {
if (el.tagName === "ASIDE") {
return true;
}
const hasMarginCaption = Array.from(el.classList).find((className) => {
return className == "margin-caption";
});
if (hasMarginCaption) {
return true;
}
return Array.from(el.classList).find((className) => {
return (
className !== "column-body" &&
!className.endsWith("container") &&
className.startsWith("column-") &&
!className.endsWith("left")
);
});
});
const kOverlapPaddingSize = 10;
function toRegions(els) {
return els.map((el) => {
const boundRect = el.getBoundingClientRect();
const top =
boundRect.top +
document.documentElement.scrollTop -
kOverlapPaddingSize;
return {
top,
bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize,
};
});
}
let hasObserved = false;
const visibleItemObserver = (els) => {
let visibleElements = [...els];
const intersectionObserver = new IntersectionObserver(
(entries, _observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
if (visibleElements.indexOf(entry.target) === -1) {
visibleElements.push(entry.target);
}
} else {
visibleElements = visibleElements.filter((visibleEntry) => {
return visibleEntry !== entry;
});
}
});
if (!hasObserved) {
hideOverlappedSidebars();
}
hasObserved = true;
},
{}
);
els.forEach((el) => {
intersectionObserver.observe(el);
});
return {
getVisibleEntries: () => {
return visibleElements;
},
};
};
const rightElementObserver = visibleItemObserver(rightSideConflictEls);
const leftElementObserver = visibleItemObserver(leftSideConflictEls);
const hideOverlappedSidebars = () => {
marginScrollVisibility(toRegions(rightElementObserver.getVisibleEntries()));
sidebarScrollVisiblity(toRegions(leftElementObserver.getVisibleEntries()));
if (tocLeftScrollVisibility) {
tocLeftScrollVisibility(
toRegions(leftElementObserver.getVisibleEntries())
);
}
};
window.quartoToggleReader = () => {
// Applies a slow class (or removes it)
// to update the transition speed
const slowTransition = (slow) => {
const manageTransition = (id, slow) => {
const el = document.getElementById(id);
if (el) {
if (slow) {
el.classList.add("slow");
} else {
el.classList.remove("slow");
}
}
};
manageTransition("TOC", slow);
manageTransition("quarto-sidebar", slow);
};
const readerMode = !isReaderMode();
setReaderModeValue(readerMode);
// If we're entering reader mode, slow the transition
if (readerMode) {
slowTransition(readerMode);
}
highlightReaderToggle(readerMode);
hideOverlappedSidebars();
// If we're exiting reader mode, restore the non-slow transition
if (!readerMode) {
slowTransition(!readerMode);
}
};
const highlightReaderToggle = (readerMode) => {
const els = document.querySelectorAll(".quarto-reader-toggle");
if (els) {
els.forEach((el) => {
if (readerMode) {
el.classList.add("reader");
} else {
el.classList.remove("reader");
}
});
}
};
const setReaderModeValue = (val) => {
if (window.location.protocol !== "file:") {
window.localStorage.setItem("quarto-reader-mode", val);
} else {
localReaderMode = val;
}
};
const isReaderMode = () => {
if (window.location.protocol !== "file:") {
return window.localStorage.getItem("quarto-reader-mode") === "true";
} else {
return localReaderMode;
}
};
let localReaderMode = null;
const tocOpenDepthStr = tocEl?.getAttribute("data-toc-expanded");
const tocOpenDepth = tocOpenDepthStr ? Number(tocOpenDepthStr) : 1;
// Walk the TOC and collapse/expand nodes
// Nodes are expanded if:
// - they are top level
// - they have children that are 'active' links
// - they are directly below an link that is 'active'
const walk = (el, depth) => {
// Tick depth when we enter a UL
if (el.tagName === "UL") {
depth = depth + 1;
}
// It this is active link
let isActiveNode = false;
if (el.tagName === "A" && el.classList.contains("active")) {
isActiveNode = true;
}
// See if there is an active child to this element
let hasActiveChild = false;
for (const child of el.children) {
hasActiveChild = walk(child, depth) || hasActiveChild;
}
// Process the collapse state if this is an UL
if (el.tagName === "UL") {
if (tocOpenDepth === -1 && depth > 1) {
// toc-expand: false
el.classList.add("collapse");
} else if (
depth <= tocOpenDepth ||
hasActiveChild ||
prevSiblingIsActiveLink(el)
) {
el.classList.remove("collapse");
} else {
el.classList.add("collapse");
}
// untick depth when we leave a UL
depth = depth - 1;
}
return hasActiveChild || isActiveNode;
};
// walk the TOC and expand / collapse any items that should be shown
if (tocEl) {
updateActiveLink();
walk(tocEl, 0);
}
// Throttle the scroll event and walk peridiocally
window.document.addEventListener(
"scroll",
throttle(() => {
if (tocEl) {
updateActiveLink();
walk(tocEl, 0);
}
if (!isReaderMode()) {
hideOverlappedSidebars();
}
}, 5)
);
window.addEventListener(
"resize",
throttle(() => {
if (tocEl) {
updateActiveLink();
walk(tocEl, 0);
}
if (!isReaderMode()) {
hideOverlappedSidebars();
}
}, 10)
);
hideOverlappedSidebars();
highlightReaderToggle(isReaderMode());
});
tabsets.init();
axe.init();
function throttle(func, wait) {
let waiting = false;
return function () {
if (!waiting) {
func.apply(this, arguments);
waiting = true;
setTimeout(function () {
waiting = false;
}, wait);
}
};
}
function nexttick(func) {
return setTimeout(func, 0);
}

View File

@@ -0,0 +1,95 @@
// grouped tabsets
export function init() {
window.addEventListener("pageshow", (_event) => {
function getTabSettings() {
const data = localStorage.getItem("quarto-persistent-tabsets-data");
if (!data) {
localStorage.setItem("quarto-persistent-tabsets-data", "{}");
return {};
}
if (data) {
return JSON.parse(data);
}
}
function setTabSettings(data) {
localStorage.setItem(
"quarto-persistent-tabsets-data",
JSON.stringify(data)
);
}
function setTabState(groupName, groupValue) {
const data = getTabSettings();
data[groupName] = groupValue;
setTabSettings(data);
}
function toggleTab(tab, active) {
const tabPanelId = tab.getAttribute("aria-controls");
const tabPanel = document.getElementById(tabPanelId);
if (active) {
tab.classList.add("active");
tabPanel.classList.add("active");
} else {
tab.classList.remove("active");
tabPanel.classList.remove("active");
}
}
function toggleAll(selectedGroup, selectorsToSync) {
for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) {
const active = selectedGroup === thisGroup;
for (const tab of tabs) {
toggleTab(tab, active);
}
}
}
function findSelectorsToSyncByLanguage() {
const result = {};
const tabs = Array.from(
document.querySelectorAll(`div[data-group] a[id^='tabset-']`)
);
for (const item of tabs) {
const div = item.parentElement.parentElement.parentElement;
const group = div.getAttribute("data-group");
if (!result[group]) {
result[group] = {};
}
const selectorsToSync = result[group];
const value = item.innerHTML;
if (!selectorsToSync[value]) {
selectorsToSync[value] = [];
}
selectorsToSync[value].push(item);
}
return result;
}
function setupSelectorSync() {
const selectorsToSync = findSelectorsToSyncByLanguage();
Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => {
Object.entries(tabSetsByValue).forEach(([value, items]) => {
items.forEach((item) => {
item.addEventListener("click", (_event) => {
setTabState(group, value);
toggleAll(value, selectorsToSync[group]);
});
});
});
});
return selectorsToSync;
}
const selectorsToSync = setupSelectorSync();
for (const [group, selectedName] of Object.entries(getTabSettings())) {
const selectors = selectorsToSync[group];
// it's possible that stale state gives us empty selections, so we explicitly check here.
if (selectors) {
toggleAll(selectedName, selectors);
}
}
});
}

View File

@@ -0,0 +1 @@
.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
/.quarto/
**/*.quarto_ipynb
/pages/
/pages/
/obidoc/

View File

@@ -1,56 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#343a40">
<meta name="color-scheme" content="light dark"><meta property="og:url" content="http://metabar:8888/obidoc/404.html">
<meta property="og:site_name" content="OBITools4 documentation">
<meta property="og:title" content="404 Page not found">
<meta property="og:locale" content="en_us">
<meta property="og:type" content="website">
<title>404 Page not found | OBITools4 documentation</title>
<link rel="icon" href="/obidoc/favicon.png" >
<link rel="manifest" href="/obidoc/manifest.json">
<link rel="canonical" href="http://metabar:8888/obidoc/404.html">
<link rel="stylesheet" href="/obidoc/book.min.5fd7b8e2d1c0ae15da279c52ff32731130386f71b58f011468f20d0056fe6b78.css" integrity="sha256-X9e44tHArhXaJ5xS/zJzETA4b3G1jwEUaPINAFb&#43;a3g=" crossorigin="anonymous">
<script defer src="/obidoc/fuse.min.js"></script>
<script defer src="/obidoc/en.search.min.4da51bdd2d833922fdbc0e19df517221387fc625ffb68ee140d605b3c5b68058.js" integrity="sha256-TaUb3S2DOSL9vA4Z31FyITh/xiX/to7hQNYFs8W2gFg=" crossorigin="anonymous"></script>
<script defer src="/obidoc/sw.min.32af8eafce4180aa1c5dea66d99fb26ba9043ea7c7a4c706138c91d9051b285e.js" integrity="sha256-Mq&#43;Or85BgKocXepm2Z&#43;ya6kEPqfHpMcGE4yR2QUbKF4=" crossorigin="anonymous"></script>
<!--
Made with Book Theme
https://github.com/alex-shpak/hugo-book
-->
<link rel="stylesheet" type="text/css" href="http://metabar:8888/obidoc/hugo-cite.css" />
<style>
.not-found {
text-align: center;
}
.not-found h1 {
margin: .25em 0 0 0;
opacity: .25;
font-size: 40vmin;
}
</style>
</head>
<body>
<main class="flex justify-center not-found">
<div>
<h1>404</h1>
<h2>Page Not Found</h2>
<h3>
<a href="/obidoc/">OBITools4 documentation</a>
</h3>
</div>
</main>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Categories on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/categories/</link>
<description>Recent content in Categories on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/categories/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,9 +0,0 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<title>http://metabar:8888/obidoc/categories/</title>
<link rel="canonical" href="http://metabar:8888/obidoc/categories/">
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=http://metabar:8888/obidoc/categories/">
</head>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Commands on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/commands/</link>
<description>Recent content in Commands on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/commands/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,9 +0,0 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<title>http://metabar:8888/obidoc/commands/</title>
<link rel="canonical" href="http://metabar:8888/obidoc/commands/">
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=http://metabar:8888/obidoc/commands/">
</head>
</html>

View File

@@ -1 +0,0 @@
.admonition{margin:1rem 0;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,0.12);transition:all 0.3s ease}.admonition-header{padding:0.5rem 1rem;display:flex;align-items:center;font-weight:600;border-bottom:1px solid rgba(0,0,0,0.1);font-size:1.1rem;border-radius:4px 4px 0 0}.admonition-header svg{width:1.1em;height:1.1em;margin-right:0.5rem;fill:currentColor}.admonition-content{padding:1rem;background-color:#fff;border-radius:0 0 4px 4px;color:#000;transition:background-color 0.3s ease, color 0.3s ease}.admonition-content p{margin:0 0 0.5rem 0}.admonition-content p:last-child{margin-bottom:0}.admonition-content ul,.admonition-content ol{margin:0 0 0.5rem 0;padding-left:1.2rem}.admonition-content ul:last-child,.admonition-content ol:last-child{margin-bottom:0}.admonition-content blockquote{margin:0 0 0.5rem 0;padding-left:1rem;border-left:3px solid #e0e0e0}.admonition-content blockquote:last-child{margin-bottom:0}.admonition-content code{background-color:#f5f5f5;color:#24292e;padding:0.2em 0.4em;border-radius:3px;font-size:0.9em}@media (prefers-color-scheme: dark){.admonition-content{background-color:#1D1E20;color:#e6e6e6}.admonition-content code{background-color:#313244;color:#cdd6f4}.admonition-content blockquote{border-left-color:#45475a;color:#cdd6f4}}body.dark .admonition-content{background-color:#1D1E20;color:#e6e6e6}body.dark .admonition-content code{background-color:#313244;color:#cdd6f4}body.dark .admonition-content blockquote{border-left-color:#45475a;color:#cdd6f4}.admonition.abstract{background:transparent;border-left:4px solid #209fb5}.admonition.abstract .admonition-header{background:rgba(32,159,181,0.1);color:#209fb5}.admonition.caution{background:transparent;border-left:4px solid #e64553}.admonition.caution .admonition-header{background:rgba(230,69,83,0.1);color:#e64553}.admonition.code{background:transparent;border-left:4px solid #7287fd}.admonition.code .admonition-header{background:rgba(114,135,253,0.1);color:#7287fd}.admonition.conclusion{background:transparent;border-left:4px solid #dd7878}.admonition.conclusion .admonition-header{background:rgba(221,120,120,0.1);color:#dd7878}.admonition.danger{background:transparent;border-left:4px solid #fe640b}.admonition.danger .admonition-header{background:rgba(254,100,11,0.1);color:#fe640b}.admonition.error{background:transparent;border-left:4px solid #d20f39}.admonition.error .admonition-header{background:rgba(210,15,57,0.1);color:#d20f39}.admonition.example{background:transparent;border-left:4px solid #dc8a78}.admonition.example .admonition-header{background:rgba(220,138,120,0.1);color:#dc8a78}.admonition.experiment{background:transparent;border-left:4px solid #51bb2a}.admonition.experiment .admonition-header{background:rgba(81,187,42,0.1);color:#51bb2a}.admonition.goal{background:transparent;border-left:4px solid #e64553}.admonition.goal .admonition-header{background:rgba(230,69,83,0.1);color:#e64553}.admonition.idea{background:transparent;border-left:4px solid #df8e1d}.admonition.idea .admonition-header{background:rgba(223,142,29,0.1);color:#df8e1d}.admonition.important{background:transparent;border-left:4px solid #7D4DDA}.admonition.important .admonition-header{background:rgba(125,77,218,0.1);color:#7D4DDA}.admonition.info{background:transparent;border-left:4px solid #04a5e5}.admonition.info .admonition-header{background:rgba(4,165,229,0.1);color:#04a5e5}.admonition.memo{background:transparent;border-left:4px solid #e64553}.admonition.memo .admonition-header{background:rgba(230,69,83,0.1);color:#e64553}.admonition.note{background:transparent;border-left:4px solid #096ae1}.admonition.note .admonition-header{background:rgba(9,106,225,0.1);color:#096ae1}.admonition.notify{background:transparent;border-left:4px solid #0d48bd}.admonition.notify .admonition-header{background:rgba(13,72,189,0.1);color:#0d48bd}.admonition.question{background:transparent;border-left:4px solid #179299}.admonition.question .admonition-header{background:rgba(23,146,153,0.1);color:#179299}.admonition.quote{background:transparent;border-left:4px solid #7287fd}.admonition.quote .admonition-header{background:rgba(114,135,253,0.1);color:#7287fd}.admonition.success{background:transparent;border-left:4px solid #40a02b}.admonition.success .admonition-header{background:rgba(64,160,43,0.1);color:#40a02b}.admonition.task{background:transparent;border-left:4px solid #8839ef}.admonition.task .admonition-header{background:rgba(136,57,239,0.1);color:#8839ef}.admonition.tip{background:transparent;border-left:4px solid #179299}.admonition.tip .admonition-header{background:rgba(23,146,153,0.1);color:#179299}.admonition.warning{background:transparent;border-left:4px solid #df8e1d}.admonition.warning .admonition-header{background:rgba(223,142,29,0.1);color:#df8e1d}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Advanced tools on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/advanced/</link>
<description>Recent content in Advanced tools on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/advanced/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Sequence alignments on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/alignments/</link>
<description>Recent content in Sequence alignments on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/alignments/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Exact alignment on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/alignments/obipairing/exact-alignment/</link>
<description>Recent content in Exact alignment on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/commands/alignments/obipairing/exact-alignment/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,149 +0,0 @@
---
title: "Untitled"
format: html
editor: visual
---
```{r}
library(tidyverse)
library(plotly)
library(matrixStats)
```
```{r}
log_sum_exp <- function(a,b) {
m <- map2_dbl(a,b,max)
m + log(exp(a-m)+exp(b-m))
}
```
$$
\log(1 - e^b) = \log\left(-e^{(1-b)}\right)
$$
```{r}
log1m_exp <- function(b) {
if (any(b >= 0)) {
stop(glue::glue("b must be negative (b={b})"))
}
return(log(-expm1(b))) # expm1(b) = exp(b) - 1, pour éviter les erreurs d'arrondi
}
```
$$
\log(e^a - e^b) = a + \log(1 - e^{b-a})
$$
```{r}
log_diff_exp <- function(a, b) {
# Vérifier si a > b pour éviter des résultats indéfinis
if (any(a < b)) {
stop(glue::glue("Erreur : a ({a}) doit etre strictement sup<75>rieur <20> b ({b}) pour que e^a - e^b soit positif."))
}
# Calculer log(e^a - e^b) de manière stable
ifelse(a == b, -Inf,a + log1m_exp(b-a))
}
```
$$
P_{error} = 10^{-\frac{Q}{10}}
$$
$$
\begin{aligned}
q_F &= -\frac{Q_F}{10} \cdot \log(10) \\
q_R &= -\frac{Q_R}{10} \cdot \log(10) \\
P(macth | Obs(match)) &= (1-e^{q_F}) (1-e^{q_R}) + (1-e^{q_F})\frac{e^{q_R}}{4}+ (1-e^{q_R})\frac{e^{q_F}}{4} + \frac{e^{q_F+q_R}}{4} \\
&=1 - e^{q_R} - e^{q_F} + e^{q_F+q_R} + \frac{e^{q_R}}{4} - \frac{e^{q_F+q_R}}{4} + \frac{e^{q_F}}{4} - \frac{e^{q_F+q_R}}{4} + \frac{e^{q_F+q_R}}{4} \\
&= \frac{4 - 4e^{q_F} - 4e^{q_R} + 4e^{q_F+q_R} + e^{q_F} + e^{q_R} - e^{q_F+q_R}}{4} \\
&= \frac{4 - 3e^{q_F}- 3e^{q_R} + 3e^{q_F+q_R}}{4}\\
&= \frac{4 - 3(e^{q_F}+e^{q_R}-e^{q_F+q_R})}{4} \\
&= 1 - \frac{3}{4}\left(e^{q_F}+e^{q_R}-e^{q_F+q_R}\right)
\end{aligned}
$$
```{r}
Pm_match_observed <- function(Q_F, Q_R) {
l10 <- log(10)
l3 <- log(3)
l4 <- log(4)
q_F <- -Q_F/10*l10
q_R <- -Q_R/10*l10
term1 <- log_sum_exp(q_F,q_R)
term2 <- log_diff_exp(term1,q_F+q_R) + l3 - l4
log1m_exp(term2)
}
```
$$
\begin{aligned}
P(macth | Obs(mismatch)) &= \frac{(1-e^{q_F})e^{q_R}}{4} + \frac{(1-e^{q_R})e^{q_F}}{4} + \frac{e^{q_F+q_R}}{4} \\
&= \frac{(1-e^{q_F})e^{q_R} + (1-e^{q_R})e^{q_F} + e^{q_F+q_R}}{4} \\
&= \frac{e^{q_R} - e^{q_F+q_R} + e^{q_F} - e^{q_F+q_R} + e^{q_F+q_R}}{4} \\
&= \frac{e^{q_F} + e^{q_R} - e^{q_F+q_R}}{4}
\end{aligned}
$$
```{r}
Pm_mismatch_observed <- function(Q_F, Q_R) {
l10 <- log(10)
l3 <- log(3)
l4 <- log(4)
q_F <- -Q_F/10*l10
q_R <- -Q_R/10*l10
term1 <- log_sum_exp(q_F,q_R)
log_diff_exp(term1,q_F+q_R) - l4
}
```
```{r}
score_match_observed <- function(Q_F, Q_R) {
Pm_match_observed(Q_F,Q_R) - log1m_exp(Pm_match_observed(Q_F,Q_R))
}
score_mismatch_observed <- function(Q_F, Q_R) {
Pm_mismatch_observed(Q_F,Q_R) - log1m_exp(Pm_mismatch_observed(Q_F,Q_R))
}
```
```{r}
scores <- expand_grid(QF=0:40,QR=0:40) %>%
mutate(score_match_observed = round(score_match_observed(QF,QR),2),
score_mismatch_observed = round(score_mismatch_observed(QF,QR),2))
```
```{r}
plot_match <- plot_ly(scores,
x=~QF, y=~QR, z=~score_match_observed,
type="mesh3d") %>%
layout(
plot_bgcolor = "#bababa",
scene = list(
xaxis = list(title = "Q forward read"), # Change x/y/z axis title
yaxis = list(title = "Q reverse read"),
zaxis = list(title = "Score match")))
```
```{r}
plot_mismatch <- plot_ly(scores,
x=~QF, y=~QR, z=~score_mismatch_observed,
type="mesh3d") %>%
layout(
plot_bgcolor = "#bababa",
scene = list(
xaxis = list(title = "Q forward read"), # Change x/y/z axis title
yaxis = list(title = "Q reverse read"),
zaxis = list(title = "Score mismatch")))
```
```{r}
write(plotly_json(plot_match,FALSE),"content/docs/commands/alignments/obipairing/exact-alignment/match.json")
write(plotly_json(plot_mismatch,FALSE),"content/docs/commands/alignments/obipairing/exact-alignment/mismatch.json")
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The FASTA-like alignment on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/alignments/obipairing/fasta-like/</link>
<description>Recent content in The FASTA-like alignment on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/commands/alignments/obipairing/fasta-like/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Basics on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/basics/</link>
<description>Recent content in Basics on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/basics/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Demultiplexing samples on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/demultiplexing/</link>
<description>Recent content in Demultiplexing samples on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/demultiplexing/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Experimentals on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/experimental/</link>
<description>Recent content in Experimentals on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/experimental/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The OBITools4 commands on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/</link>
<description>Recent content in The OBITools4 commands on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate>Fri, 04 Oct 2024 17:16:03 +0200</lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Glossary of tags</title>
<link>http://metabar:8888/obidoc/docs/commands/tags/</link>
<pubDate>Fri, 04 Oct 2024 17:16:03 +0200</pubDate>
<guid>http://metabar:8888/obidoc/docs/commands/tags/</guid>
<description>&lt;h1 id=&#34;glossary-of-tags&#34;&gt;&#xA; Glossary of tags&#xA; &lt;a class=&#34;anchor&#34; href=&#34;#glossary-of-tags&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;h3 id=&#34;--d--&#34;&gt;&#xA; - D -&#xA; &lt;a class=&#34;anchor&#34; href=&#34;#--d--&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;definition&lt;/strong&gt; :&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;text information about the sequence present in the original sequence file.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;direction&lt;/strong&gt; :&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;set to “forward” if the original sequence did not need to be reverse-complemented to be processed, set to “reverse” otherwise.&#xA;(&#xA; &lt;a href=&#34;http://metabar:8888/obidoc/obitools/obipcr/&#34;&gt;obipcr&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;--f--&#34;&gt;&#xA; - F -&#xA; &lt;a class=&#34;anchor&#34; href=&#34;#--f--&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;forward_error&lt;/strong&gt; :&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Number of mismatch between forward primer and priming site&#xA;(&#xA; &lt;a href=&#34;http://metabar:8888/obidoc/obitools/obipcr/&#34;&gt;obipcr&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;forward_match&lt;/strong&gt; :&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Forward primer priming site sequence&#xA;(&#xA; &lt;a href=&#34;http://metabar:8888/obidoc/obitools/obipcr/&#34;&gt;obipcr&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;forward_primer&lt;/strong&gt; :&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Forward primer sequence&#xA;(&#xA; &lt;a href=&#34;http://metabar:8888/obidoc/obitools/obipcr/&#34;&gt;obipcr&lt;/a&gt;)&lt;/p&gt;</description>
</item>
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Shared command options on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/options/</link>
<description>Recent content in Shared command options on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/options/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,6 +0,0 @@
>AB061527 {"count":1,"definition":"Sorex unguiculatus mitochondrial NA, complete genome.","family_name":"Soricidae","family_taxid":9376,"genus_name":"Sorex","genus_taxid":9379,"obicleandb_level":"family","obicleandb_trusted":2.2137847111025621e-13,"species_name":"Sorex unguiculatus","species_taxid":62275,"taxid":62275}
ttagccctaaacttaggtatttaatctaacaaaaatacccgtcagagaactactagcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>AL355887 {"count":2,"definition":"Human chromosome 14 NA sequence BAC R-179O11 of library RPCI-11 from chromosome 14 of Homo sapiens (Human)XXKW HTG.; HTGS_ACTIVFIN.","family_name":"Hominidae","family_taxid":9604,"genus_name":"Homo","genus_taxid":9605,"obicleandb_level":"genus","obicleandb_trusted":0,"species_name":"Homo sapiens","species_taxid":9606,"taxid":9606}
ttagccctaaactctagtagttacattaacaaaaccattcgtcagaatactacgagcaac
agcttaaaactcaaaggacctggcagttctttatatccct

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Others on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/others/</link>
<description>Recent content in Others on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/others/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Taxonomy on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/commands/taxonomy/</link>
<description>Recent content in Taxonomy on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/commands/taxonomy/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,604 +0,0 @@
#!/usr/bin/env python3
import re
import gzip
import struct
import sys
import time
import getopt
from functools import cmp_to_key
_dbenable=False
#####
#
#
# Generic file function
#
#
#####
def universalOpen(file):
if isinstance(file,str):
if file[-3:] == '.gz':
rep = gzip.open(file)
else:
rep = open(file)
else:
rep = file
return rep
def universalTell(file):
if isinstance(file, gzip.GzipFile):
file=file.myfileobj
return file.tell()
def fileSize(file):
if isinstance(file, gzip.GzipFile):
file=file.myfileobj
pos = file.tell()
file.seek(0,2)
length = file.tell()
file.seek(pos,0)
return length
def progressBar(pos,max,reset=False,delta=[]):
if reset:
del delta[:]
if not delta:
delta.append(time.time())
delta.append(time.time())
delta[1]=time.time()
elapsed = delta[1]-delta[0]
percent = float(pos)/max * 100
remain = time.strftime('%H:%M:%S',time.gmtime(elapsed / percent * (100-percent)))
bar = '#' * int(percent/2)
bar+= '|/-\\-'[pos % 5]
bar+= ' ' * (50 - int(percent/2))
sys.stderr.write('\r%5.1f %% |%s] remain : %s' %(percent,bar,remain))
#####
#
#
# NCBI Dump Taxonomy reader
#
#
#####
def endLessIterator(endedlist):
for x in endedlist:
yield x
while(1):
yield endedlist[-1]
class ColumnFile(object):
def __init__(self,stream,sep=None,strip=True,types=None):
if isinstance(stream,str):
self._stream = open(stream)
else:
try:
iter(stream)
self._stream = stream
except TypeError:
raise ValueError('stream must be string or an iterator')
self._delimiter=sep
self._strip=strip
if types:
self._types=[x for x in types]
for i in range(len(self._types)):
if self._types[i] is bool:
self._types[i]=ColumnFile.str2bool
else:
self._types=None
def str2bool(x):
return bool(eval(x.strip()[0].upper(),{'T':True,'V':True,'F':False}))
str2bool = staticmethod(str2bool)
def __iter__(self):
return self
def __next__(self):
ligne = next(self._stream)
data = ligne.split(self._delimiter)
if self._strip or self._types:
data = [x.strip() for x in data]
if self._types:
it = endLessIterator(self._types)
data = [x[1](x[0]) for x in ((y,next(it)) for y in data)]
return data
def taxonCmp(t1,t2):
if t1[0] < t2[0]:
return -1
elif t1[0] > t2[0]:
return +1
return 0
def bsearchTaxon(taxonomy,taxid):
taxCount = len(taxonomy)
begin = 0
end = taxCount
oldcheck=taxCount
check = int(begin + end / 2)
while check != oldcheck and taxonomy[check][0]!=taxid :
if taxonomy[check][0] < taxid:
begin=check
else:
end=check
oldcheck=check
check = int((begin + end) / 2)
if taxonomy[check][0]==taxid:
return check
else:
return None
def readNodeTable(file):
file = universalOpen(file)
nodes = ColumnFile(file,
sep='|',
types=(int,int,str,
str,str,bool,
int,bool,int,
bool,bool,bool,str))
print("Reading taxonomy dump file...", file=sys.stderr)
taxonomy=[[n[0],n[2],n[1]] for n in nodes]
print("List all taxonomy rank...", file=sys.stderr)
ranks =list(set(x[1] for x in taxonomy))
ranks.sort()
ranks = {rank: index for index, rank in enumerate(ranks)}
print("Sorting taxons...", file=sys.stderr)
taxonomy.sort(key=lambda x: x[0])
print("Indexing taxonomy...", file=sys.stderr)
index = {}
for t in taxonomy:
index[t[0]]=bsearchTaxon(taxonomy, t[0])
print("Indexing parent and rank...", file=sys.stderr)
for t in taxonomy:
t[1]=ranks[t[1]]
t[2]=index[t[2]]
return taxonomy,ranks,index
def nameIterator(file):
file = universalOpen(file)
names = ColumnFile(file,
sep='|',
types=(int,str,
str,str))
for taxid,name,unique,classname,white in names:
yield taxid,name,classname
def mergedNodeIterator(file):
file = universalOpen(file)
merged = ColumnFile(file,
sep='|',
types=(int,int,str))
for taxid,current,white in merged:
yield taxid,current
def deletedNodeIterator(file):
file = universalOpen(file)
deleted = ColumnFile(file,
sep='|',
types=(int,str))
for taxid,white in deleted:
yield taxid
def readTaxonomyDump(taxdir):
taxonomy,ranks,index = readNodeTable('%s/nodes.dmp' % taxdir)
print("Adding scientific name...", file=sys.stderr)
alternativeName=[]
for taxid,name,classname in nameIterator('%s/names.dmp' % taxdir):
alternativeName.append((name,classname,index[taxid]))
if classname == 'scientific name':
taxonomy[index[taxid]].append(name)
print("Adding taxid alias...", file=sys.stderr)
for taxid,current in mergedNodeIterator('%s/merged.dmp' % taxdir):
index[taxid]=index[current]
print("Adding deleted taxid...", file=sys.stderr)
for taxid in deletedNodeIterator('%s/delnodes.dmp' % taxdir):
index[taxid]=None
return taxonomy,ranks,alternativeName,index
#####
#
#
# Genbank/EMBL sequence reader
#
#
#####
def entryIterator(file):
file = universalOpen(file)
rep =[]
ligne = file.readline()
while ligne:
rep.append(ligne)
if ligne == '//\n':
rep = ''.join(rep)
yield rep
rep = []
ligne = file.readline()
def fastaEntryIterator(file):
file = universalOpen(file)
rep =[]
ligne = file.readline()
while ligne:
if ligne[0] == '>' and rep:
rep = ''.join(rep)
yield rep
rep = []
rep.append(ligne)
ligne = file.readline()
if rep:
rep = ''.join(rep)
yield rep
_cleanSeq = re.compile('[ \n0-9]+')
def cleanSeq(seq):
return _cleanSeq.sub('',seq)
_gbParseID = re.compile('(?<=^LOCUS {7})[^ ]+(?= )',re.MULTILINE)
_gbParseDE = re.compile('(?<=^DEFINITION {2}).+?\\. *$(?=[^ ])',re.MULTILINE+re.DOTALL)
_gbParseSQ = re.compile('(?<=^ORIGIN).+?(?=^//$)',re.MULTILINE+re.DOTALL)
_gbParseTX = re.compile('(?<= /db_xref="taxon:)[0-9]+(?=")')
def genbankEntryParser(entry):
Id = _gbParseID.findall(entry)[0]
De = ' '.join(_gbParseDE.findall(entry)[0].split())
Sq = cleanSeq(_gbParseSQ.findall(entry)[0].upper())
try:
Tx = int(_gbParseTX.findall(entry)[0])
except IndexError:
Tx = None
return {'id':Id,'taxid':Tx,'definition':De,'sequence':Sq}
######################
_cleanDef = re.compile('[\nDE]')
def cleanDef(definition):
return _cleanDef.sub('',definition)
_emblParseID = re.compile('(?<=^ID {3})[^ ]+(?=;)',re.MULTILINE)
_emblParseDE = re.compile('(?<=^DE {3}).+?\\. *$(?=[^ ])',re.MULTILINE+re.DOTALL)
_emblParseSQ = re.compile('(?<=^ ).+?(?=^//$)',re.MULTILINE+re.DOTALL)
_emblParseTX = re.compile('(?<= /db_xref="taxon:)[0-9]+(?=")')
def emblEntryParser(entry):
Id = _emblParseID.findall(entry)[0]
De = ' '.join(cleanDef(_emblParseDE.findall(entry)[0]).split())
Sq = cleanSeq(_emblParseSQ.findall(entry)[0].upper())
try:
Tx = int(_emblParseTX.findall(entry)[0])
except IndexError:
Tx = None
return {'id':Id,'taxid':Tx,'definition':De,'sequence':Sq}
######################
_fastaSplit=re.compile(';\\W*')
def parseFasta(seq):
seq=seq.split('\n')
title = seq[0].strip()[1:].split(None,1)
id=title[0]
if len(title) == 2:
field = _fastaSplit.split(title[1])
else:
field=[]
info = dict(x.split('=',1) for x in field if '=' in x)
definition = ' '.join([x for x in field if '=' not in x])
seq=(''.join([x.strip() for x in seq[1:]])).upper()
return id,seq,definition,info
def fastaEntryParser(entry):
id,seq,definition,info = parseFasta(entry)
Tx = info.get('taxid',None)
if Tx is not None:
match = re.search(r'taxon:(\d+)', Tx)
if match:
Tx = match.group(1)
Tx=int(Tx)
return {'id':id,'taxid':Tx,'definition':definition,'sequence':seq}
def sequenceIteratorFactory(entryParser,entryIterator):
def sequenceIterator(file):
for entry in entryIterator(file):
yield entryParser(entry)
return sequenceIterator
def taxonomyInfo(entry,connection):
taxid = entry['taxid']
curseur = connection.cursor()
curseur.execute("""
select taxid,species,genus,family,
taxonomy.scientificName(taxid) as sn,
taxonomy.scientificName(species) as species_sn,
taxonomy.scientificName(genus) as genus_sn,
taxonomy.scientificName(family) as family_sn
from
(
select alias as taxid,
taxonomy.getSpecies(alias) as species,
taxonomy.getGenus(alias) as genus,
taxonomy.getFamily(alias) as family
from taxonomy.aliases
where id=%d ) as tax
""" % taxid)
rep = curseur.fetchone()
entry['current_taxid']=rep[0]
entry['species']=rep[1]
entry['genus']=rep[2]
entry['family']=rep[3]
entry['scientific_name']=rep[4]
entry['species_sn']=rep[5]
entry['genus_sn']=rep[6]
entry['family_sn']=rep[7]
return entry
#####
#
#
# Binary writer
#
#
#####
def ecoSeqPacker(sq):
compactseq = gzip.zlib.compress(bytes(sq['sequence'],"ascii"),9)
cptseqlength = len(compactseq)
delength = len(sq['definition'])
totalSize = 4 + 20 + 4 + 4 + 4 + cptseqlength + delength
packed = struct.pack('> I I 20s I I I %ds %ds' % (delength,cptseqlength),
totalSize,
sq['taxid'],
bytes(sq['id'],"ascii"),
delength,
len(sq['sequence']),
cptseqlength,
bytes(sq['definition'],"ascii"),
compactseq)
assert len(packed) == totalSize+4, "error in sequence packing"
return packed
def ecoTaxPacker(tx):
namelength = len(tx[3])
totalSize = 4 + 4 + 4 + 4 + namelength
packed = struct.pack('> I I I I I %ds' % namelength,
totalSize,
tx[0],
tx[1],
tx[2],
namelength,
bytes(tx[3],"ascii"))
return packed
def ecoRankPacker(rank):
namelength = len(rank)
packed = struct.pack('> I %ds' % namelength,
namelength,
bytes(rank, 'ascii'))
return packed
def ecoNamePacker(name):
namelength = len(name[0])
classlength= len(name[1])
totalSize = namelength + classlength + 4 + 4 + 4 + 4
packed = struct.pack('> I I I I I %ds %ds' % (namelength,classlength),
totalSize,
int(name[1]=='scientific name'),
namelength,
classlength,
name[2],
bytes(name[0], 'ascii'),
bytes(name[1], 'ascii'))
return packed
def ecoSeqWriter(file,input,taxindex,parser):
output = open(file,'wb')
input = universalOpen(input)
inputsize = fileSize(input)
entries = parser(input)
seqcount=0
skipped = []
output.write(struct.pack('> I',seqcount))
progressBar(1, inputsize,reset=True)
for entry in entries:
if entry['taxid'] is not None:
try:
entry['taxid']=taxindex[entry['taxid']]
except KeyError:
entry['taxid']=None
if entry['taxid'] is not None:
seqcount+=1
output.write(ecoSeqPacker(entry))
else:
skipped.append(entry['id'])
where = universalTell(input)
progressBar(where, inputsize)
print(" Readed sequences : %d " % seqcount, end=' ', file=sys.stderr)
else:
skipped.append(entry['id'])
print(file=sys.stderr)
output.seek(0,0)
output.write(struct.pack('> I',seqcount))
output.close()
return skipped
def ecoTaxWriter(file,taxonomy):
output = open(file,'wb')
output.write(struct.pack('> I',len(taxonomy)))
for tx in taxonomy:
output.write(ecoTaxPacker(tx))
output.close()
def ecoRankWriter(file,ranks):
output = open(file,'wb')
output.write(struct.pack('> I',len(ranks)))
rankNames = list(ranks.keys())
rankNames.sort()
for rank in rankNames:
output.write(ecoRankPacker(rank))
output.close()
def nameCmp(n1,n2):
name1=n1[0].upper()
name2=n2[0].upper()
if name1 < name2:
return -1
elif name1 > name2:
return 1
return 0
def ecoNameWriter(file,names):
output = open(file,'wb')
output.write(struct.pack('> I',len(names)))
names.sort(key=lambda x:x[0].upper())
for name in names:
output.write(ecoNamePacker(name))
output.close()
def ecoDBWriter(prefix,taxonomy,seqFileNames,parser):
ecoRankWriter('%s.rdx' % prefix, taxonomy[1])
ecoTaxWriter('%s.tdx' % prefix, taxonomy[0])
ecoNameWriter('%s.ndx' % prefix, taxonomy[2])
filecount = 0
for filename in seqFileNames:
filecount+=1
sk=ecoSeqWriter('%s_%03d.sdx' % (prefix,filecount),
filename,
taxonomy[3],
parser)
if sk:
print("Skipped entry :", file=sys.stderr)
print(sk, file=sys.stderr)
def ecoParseOptions(arguments):
opt = {
'prefix' : 'ecodb',
'taxdir' : 'taxdump',
'parser' : sequenceIteratorFactory(genbankEntryParser,
entryIterator)
}
o,filenames = getopt.getopt(arguments,
'ht:T:n:gfe',
['help',
'taxonomy=',
'taxonomy_db=',
'name=',
'genbank',
'fasta',
'embl'])
for name,value in o:
if name in ('-h','--help'):
printHelp()
exit()
elif name in ('-t','--taxonomy'):
opt['taxmod']='dump'
opt['taxdir']=value
elif name in ('-T','--taxonomy_db'):
opt['taxmod']='db'
opt['taxdb']=value
elif name in ('-n','--name'):
opt['prefix']=value
elif name in ('-g','--genbank'):
opt['parser']=sequenceIteratorFactory(genbankEntryParser,
entryIterator)
elif name in ('-f','--fasta'):
opt['parser']=sequenceIteratorFactory(fastaEntryParser,
fastaEntryIterator)
elif name in ('-e','--embl'):
opt['parser']=sequenceIteratorFactory(emblEntryParser,
entryIterator)
else:
raise ValueError('Unknown option %s' % name)
return opt,filenames
def printHelp():
print("-----------------------------------")
print(" ecoPCRFormat.py")
print("-----------------------------------")
print("ecoPCRFormat.py [option] <argument>")
print("-----------------------------------")
print("-e --embl :[E]mbl format")
print("-f --fasta :[F]asta format")
print("-g --genbank :[G]enbank format")
print("-h --help :[H]elp - print this help")
print("-n --name :[N]ame of the new database created")
print("-t --taxonomy :[T]axonomy - path to the taxonomy database")
print(" :bcp-like dump from GenBank taxonomy database.")
print("-----------------------------------")
if __name__ == '__main__':
opt,filenames = ecoParseOptions(sys.argv[1:])
taxonomy = readTaxonomyDump(opt['taxdir'])
ecoDBWriter(opt['prefix'], taxonomy, filenames, opt['parser'])

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Designing new barcodes on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/cookbook/ecoprimers/</link>
<description>Recent content in Designing new barcodes on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/cookbook/ecoprimers/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

View File

@@ -1,103 +0,0 @@
SHELL := /bin/bash
FTPNCBI=ftp.ncbi.nlm.nih.gov
GBURL=https://$(FTPNCBI)/genbank
GBRELEASE_URL=$(GBURL)/GB_Release_Number
TAXOURL=https://$(FTPNCBI)/pub/taxonomy/taxdump.tar.gz
GBRELEASE:=$(shell curl $(GBRELEASE_URL))
GBDIV_ALL:=$(shell curl -L ${GBURL} \
| grep -E 'gb.+\.seq\.gz' \
| sed -E 's@^.*<a href="gb([^0-9]+)[0-9]+\.seq.gz.*$$@\1@' \
| sort \
| uniq)
GBDIV=bct inv mam phg pln pri rod vrl vrt
DIRECTORIES=fasta fasta_fgs
GBFILE_ALL:=$(shell curl -L ${GBURL} \
| grep -E "gb($$(tr ' ' '|' <<< "${GBDIV}"))[0-9]+" \
| sed -E 's@^<a href="(gb.+.seq.gz)">.*$$@\1@')
SUFFIXES += .d
NODEPS:=clean taxonomy
DEPFILES:=$(wildcard Release_$(GBRELEASE)/depends/*.d)
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
#Chances are, these files don't exist. GMake will create them and
#clean up automatically afterwards
-include $(DEPFILES)
endif
all: depends directories FORCE
@make downloads
downloads: taxonomy fasta_files
@echo Genbank Release number $(GBRELEASE)
@echo all divisions : $(GBDIV_ALL)
FORCE:
@sleep 1
.PHONY: all directories depends taxonomy fasta_files FORCE
depends: directories Release_$(GBRELEASE)/depends/gbfiles.d Makefile
division: $(GBDIV)
taxonomy: directories Release_$(GBRELEASE)/taxonomy
directories: Release_$(GBRELEASE)/fasta Release_$(GBRELEASE)/stamp Release_$(GBRELEASE)/tmp
Release_$(GBRELEASE):
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/fasta: Release_$(GBRELEASE)
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/stamp: Release_$(GBRELEASE)
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/tmp: Release_$(GBRELEASE)
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/depends/gbfiles.d: Makefile
@echo Create depends directory
@mkdir -p Release_$(GBRELEASE)/depends
@for f in ${GBFILE_ALL} ; do \
echo -e "Release_$(GBRELEASE)/stamp/$$f.stamp:" ; \
echo -e "\t@echo Downloading file : $$f..." ; \
echo -e "\t@mkdir -p Release_$(GBRELEASE)/tmp" ; \
echo -e "\t@mkdir -p Release_$(GBRELEASE)/stamp" ; \
echo -e "\t@curl -L ${GBURL}/$$f > Release_$(GBRELEASE)/tmp/$$f && touch \$$@" ; \
echo ; \
div=$$(sed -E 's@^gb(...).*$$@\1@' <<< $$f) ; \
fasta="Release_$(GBRELEASE)/fasta/$$div/$${f/.seq.gz/.fasta.gz}" ; \
fasta_fgs="Release_$(GBRELEASE)/fasta_fgs/$$div/$${f/.seq.gz/.fasta.gz}" ; \
fasta_files="$$fasta_files $$fasta" ; \
fasta_fgs_files="$$fasta_fgs_files $$fasta_fgs" ; \
echo -e "$$fasta: Release_$(GBRELEASE)/stamp/$$f.stamp" ; \
echo -e "\t@echo converting file : \$$< in fasta" ; \
echo -e "\t@mkdir -p Release_$(GBRELEASE)/fasta/$$div" ; \
echo -e "\t@obiconvert -Z --fasta-output --skip-empty \\" ; \
echo -e "\t Release_$(GBRELEASE)/tmp/$$f > Release_$(GBRELEASE)/tmp/$${f/.seq.gz/.fasta.gz} \\" ; \
echo -e "\t && mv Release_$(GBRELEASE)/tmp/$${f/.seq.gz/.fasta.gz} \$$@ \\" ; \
echo -e "\t && rm -f Release_$(GBRELEASE)/tmp/$$f \\" ; \
echo -e "\t || rm -f \$$@" ; \
echo -e "\t@echo conversion of $$@ done." ; \
echo ; \
done > $@ ; \
echo >> $@ ; \
echo "fasta_files: $$fasta_files" >> $@ ;
Release_$(GBRELEASE)/taxonomy:
mkdir -p $@
curl -iL $(TAXOURL) \
| tar -C $@ -zxf -

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Analysing an Illumina data set on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/cookbook/illumina/</link>
<description>Recent content in Analysing an Illumina data set on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/cookbook/illumina/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,26 +0,0 @@
>HELIUM_000100422_612GNAAXX:7:118:3572:14633#0/1_sub[28..126] {"count":10172,"merged_sample":{"26a_F040644":10172},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":12205}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:99:9351:13090#0/1_sub[28..127] {"count":260,"merged_sample":{"29a_F260619":260},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":337}}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:10111:9078#0/1_sub[28..127] {"count":7146,"merged_sample":{"13a_F730603":7146},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":8039}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:38:14204:12725#0/1_sub[28..126] {"count":87,"merged_sample":{"26a_F040644":87},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":202}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:98:16207:5869#0/1_sub[78..81] {"count":2007,"merged_sample":{"29a_F260619":2007},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":2021}}
tttt
>HELIUM_000100422_612GNAAXX:7:30:9942:4495#0/1_sub[28..126] {"count":95,"merged_sample":{"26a_F040644":11,"29a_F260619":84},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s","29a_F260619":"h"},"obiclean_weight":{"26a_F040644":12,"29a_F260619":105}}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:51:16702:19393#0/1_sub[28..127] {"count":12004,"merged_sample":{"15a_F730814":7465,"29a_F260619":4539},"obiclean_head":true,"obiclean_headcount":2,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":0,"obiclean_status":{"15a_F730814":"h","29a_F260619":"h"},"obiclean_weight":{"15a_F730814":8822,"29a_F260619":5789}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:84:14502:1617#0/1_sub[28..127] {"count":319,"merged_sample":{"29a_F260619":319},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":376}}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:50:10637:6527#0/1_sub[28..126] {"count":366,"merged_sample":{"13a_F730603":13,"15a_F730814":5,"26a_F040644":347,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":4,"obiclean_singletoncount":3,"obiclean_status":{"13a_F730603":"s","15a_F730814":"s","26a_F040644":"h","29a_F260619":"s"},"obiclean_weight":{"13a_F730603":17,"15a_F730814":5,"26a_F040644":468,"29a_F260619":1}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct

View File

@@ -1,24 +0,0 @@
>HELIUM_000100422_612GNAAXX:7:118:3572:14633#0/1_sub[28..126] {"count":10172,"merged_sample":{"26a_F040644":10172},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":12205}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:99:9351:13090#0/1_sub[28..127] {"count":260,"merged_sample":{"29a_F260619":260},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":337}}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:10111:9078#0/1_sub[28..127] {"count":7146,"merged_sample":{"13a_F730603":7146},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":8039}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:38:14204:12725#0/1_sub[28..126] {"count":87,"merged_sample":{"26a_F040644":87},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":202}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:30:9942:4495#0/1_sub[28..126] {"count":95,"merged_sample":{"26a_F040644":11,"29a_F260619":84},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s","29a_F260619":"h"},"obiclean_weight":{"26a_F040644":12,"29a_F260619":105}}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:51:16702:19393#0/1_sub[28..127] {"count":12004,"merged_sample":{"15a_F730814":7465,"29a_F260619":4539},"obiclean_head":true,"obiclean_headcount":2,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":0,"obiclean_status":{"15a_F730814":"h","29a_F260619":"h"},"obiclean_weight":{"15a_F730814":8822,"29a_F260619":5789}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:84:14502:1617#0/1_sub[28..127] {"count":319,"merged_sample":{"29a_F260619":319},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":376}}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:50:10637:6527#0/1_sub[28..126] {"count":366,"merged_sample":{"13a_F730603":13,"15a_F730814":5,"26a_F040644":347,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":4,"obiclean_singletoncount":3,"obiclean_status":{"13a_F730603":"s","15a_F730814":"s","26a_F040644":"h","29a_F260619":"s"},"obiclean_weight":{"13a_F730603":17,"15a_F730814":5,"26a_F040644":468,"29a_F260619":1}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct

View File

@@ -1,329 +0,0 @@
>HELIUM_000100422_612GNAAXX:7:56:19300:10949#0/1_sub[28..127] {"count":37,"merged_sample":{"29a_F260619":37},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":43}}
ttagccctaaacacaagtaattaatataacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:63:4595:15643#0/1_sub[28..126] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":4}}
ttagccctaaacataagctattccataacaaaataattcgccagagtactaccggcaata
gcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:7:8807:7823#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":3}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtcataccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:19171:11413#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":1,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":1,"obiclean_mutation":{"HELIUM_000100422_612GNAAXX:7:8:6794:4925#0/1_sub[28..127]":"(t)->(g)@38"},"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"i","29a_F260619":"s"},"obiclean_weight":{"15a_F730814":1,"29a_F260619":1}}
ttagccctaaacacaagtaattaatataacaaaagtagtcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:44:5008:2115#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaaca
gcctgaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:53:16956:10563#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":4}}
ttagccctaaacataaacattcaataaacaaggatgttcgcaagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:54:10323:7022#0/1_sub[28..127] {"count":3,"merged_sample":{"13a_F730603":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":7}}
ttagccctaaacacaaataattatataaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:45:7460:13396#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":3}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttatgcccgt
>HELIUM_000100422_612GNAAXX:7:58:8409:9911#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaacattcaataaacaaaataattcgccagaggactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:118:3572:14633#0/1_sub[28..126] {"count":10172,"merged_sample":{"26a_F040644":10172},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":12205}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:100:18844:15930#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":2}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaagcgcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:29:9723:20435#0/1_sub[28..127] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":4}}
ttagccctaaacacaaataattacacaaacaaaattgttcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:43:4660:16319#0/1_sub[28..126] {"count":22,"merged_sample":{"26a_F040644":22},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":42}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:103:11045:3860#0/1_sub[28..127] {"count":4,"merged_sample":{"15a_F730814":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":4}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaagggcttggcggtgctttatgccctt
>HELIUM_000100422_612GNAAXX:7:67:10944:19430#0/1_sub[28..127] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":3}}
ttagccctaaacacaagtaattaatataacaaaattattcgtcagagtactaccggcaat
agcttaaaactcaaaggacgtggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:56:6962:17278#0/1_sub[28..126] {"count":4,"merged_sample":{"26a_F040644":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":7}}
ttagccctaaacataaacattcaataaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:60:13553:20530#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":1,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":2,"obiclean_status":{"15a_F730814":"s","29a_F260619":"s"},"obiclean_weight":{"15a_F730814":1,"29a_F260619":1}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
atgttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:35:13167:18371#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaagaatgttcgccggagaactactaggaaca
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:105:1895:7593#0/1_sub[28..127] {"count":11,"merged_sample":{"29a_F260619":11},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":13}}
ttagccctaaacctcaacagttaaatcaacaaaactgctcgccagaacactacgagccac
agcttaaaactcaaaggacctggcggtgcttcatatccct
>HELIUM_000100422_612GNAAXX:7:118:15661:12736#0/1_sub[28..127] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":2}}
ttagccctaaacacaagtaattaatataacaaaattatccgcaagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:30:8391:13152#0/1_sub[28..127] {"count":17,"merged_sample":{"13a_F730603":17},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":25}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaac
agcccaaaactcaaaggacttggcggtgcttcacaccctt
>HELIUM_000100422_612GNAAXX:7:95:14375:10838#0/1_sub[28..127] {"count":4,"merged_sample":{"29a_F260619":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":5}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:82:13334:18499#0/1_sub[28..127] {"count":6,"merged_sample":{"29a_F260619":6},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":10}}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:11272:1128#0/1_sub[28..127] {"count":2,"merged_sample":{"13a_F730603":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":2}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactactagcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:7:6016:14767#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":4}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtacgtctagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:99:9351:13090#0/1_sub[28..127] {"count":260,"merged_sample":{"29a_F260619":260},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":337}}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:9:8337:12329#0/1_sub[28..126] {"count":5,"merged_sample":{"26a_F040644":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":6}}
ttagccctaaacataaacagtcaataaacaaggatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:15:12854:18952#0/1_sub[28..126] {"count":10,"merged_sample":{"29a_F260619":10},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":16}}
ttagccctaaacataagctattccataacaaaattattcgccagagtactaccggcaata
gcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:1:4513:20277#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaaccattctataacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:57:18237:6765#0/1_sub[28..127] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":3}}
ttagccctaaacacaagtaattaatataacaaaattatgcgccagagtactgccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:10111:9078#0/1_sub[28..127] {"count":7146,"merged_sample":{"13a_F730603":7146},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":8039}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:119:8691:15994#0/1_sub[28..127] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":2}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcgat
agcttaaaacgcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:6:1739:11421#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaagaatgttcgctagagtactactagcaaca
gcctgacactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:73:17136:17728#0/1_sub[28..127] {"count":6,"merged_sample":{"13a_F730603":6},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":7}}
ctagccttaaacacaaatagttatgcaaacaaaattattcgccagagtactaccggcaac
agcccaaaactcaaaggacttggcggtgcttcacaccctt
>HELIUM_000100422_612GNAAXX:7:76:9874:3117#0/1_sub[28..127] {"count":9,"merged_sample":{"29a_F260619":9},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":12}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:38:14204:12725#0/1_sub[28..126] {"count":87,"merged_sample":{"26a_F040644":87},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":202}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:18:16679:15889#0/1_sub[28..127] {"count":4,"merged_sample":{"29a_F260619":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":4}}
ttagccctaaacctcaacagttaaatcaacaaaactgctcgccagaacactacgagccac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:52:6908:8410#0/1_sub[28..126] {"count":5,"merged_sample":{"26a_F040644":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":10}}
ttagccctaaacataagctattctataacaaaataattcgccagagaactactagcaaca
gcttaaaactcaaaggacttggcggtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:71:13461:7411#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":3}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagaagactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:98:16207:5869#0/1_sub[78..81] {"count":2007,"merged_sample":{"29a_F260619":2007},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":2021}}
tttt
>HELIUM_000100422_612GNAAXX:7:47:6989:13864#0/1_sub[28..126] {"count":3,"merged_sample":{"26a_F040644":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaaccattctataacaaaataattcgccagagaactactagcaaca
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:72:8941:18482#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaatg
gcctaaaactcaaaggacttggtggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:25:10818:13742#0/1_sub[28..133] {"count":8,"merged_sample":{"26a_F040644":8},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":8}}
ttagccctaaacgtaaactgcaaactattccataataaaataattcgcccaagaactact
agcaacagcttaaaactcaaaggacttggtggtgctttctacccct
>HELIUM_000100422_612GNAAXX:7:70:11509:6042#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":2}}
ttagccctaaacacaagaaattaatataacaaaaatattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:30:9942:4495#0/1_sub[28..126] {"count":95,"merged_sample":{"26a_F040644":11,"29a_F260619":84},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s","29a_F260619":"h"},"obiclean_weight":{"26a_F040644":12,"29a_F260619":105}}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:46:4342:17317#0/1_sub[28..126] {"count":5,"merged_sample":{"26a_F040644":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":8}}
ttagccctaaacataaatcattctataacaaaataattcgccggagaactactaggaaca
gcttaaaactcaaaggacttggcggtgccttacgtccct
>HELIUM_000100422_612GNAAXX:7:111:17844:17230#0/1_sub[28..126] {"count":13,"merged_sample":{"26a_F040644":13},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":17}}
ttagccctaaacataaatcagtctataacaaaataattcgccagagaactactagcaaca
gcttaaaactcaaaggacgtggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:34:17680:16952#0/1_sub[28..127] {"count":15,"merged_sample":{"13a_F730603":15},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":15}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgcttcacaccctt
>HELIUM_000100422_612GNAAXX:7:34:2640:2539#0/1_sub[28..127] {"count":19,"merged_sample":{"29a_F260619":19},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":25}}
ttagccctaaacacaaataattacacaaacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:71:18891:9661#0/1_sub[28..126] {"count":3,"merged_sample":{"26a_F040644":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaatcagtctataacaaaataattcgccagagaactactagcaaca
gcttaaaactcaaaggacgtggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:26:16553:1613#0/1_sub[77..81] {"count":38,"merged_sample":{"13a_F730603":38},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":38}}
caata
>HELIUM_000100422_612GNAAXX:7:45:5732:11220#0/1_sub[28..126] {"count":3,"merged_sample":{"26a_F040644":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggtggtgctttctacccct
>HELIUM_000100422_612GNAAXX:7:1:14254:1103#0/1_sub[28..126] {"count":8,"merged_sample":{"26a_F040644":8},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":11}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:50:17151:20608#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:96:13203:2879#0/1_sub[28..127] {"count":5,"merged_sample":{"13a_F730603":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":6}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaac
agcccaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:78:18041:18996#0/1_sub[28..126] {"count":13,"merged_sample":{"13a_F730603":9,"15a_F730814":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":2,"obiclean_status":{"13a_F730603":"s","15a_F730814":"s"},"obiclean_weight":{"13a_F730603":9,"15a_F730814":4}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:80:18387:10166#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":1,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":1,"obiclean_mutation":{"HELIUM_000100422_612GNAAXX:7:100:14685:15065#0/1_sub[28..127]":"(a)->(t)@24","HELIUM_000100422_612GNAAXX:7:84:14502:1617#0/1_sub[28..127]":"(t)->(g)@71"},"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s","29a_F260619":"i"},"obiclean_weight":{"15a_F730814":1,"29a_F260619":1}}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaacgcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:54:10113:12172#0/1_sub[28..127] {"count":7,"merged_sample":{"15a_F730814":4,"29a_F260619":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":2,"obiclean_status":{"15a_F730814":"s","29a_F260619":"s"},"obiclean_weight":{"15a_F730814":5,"29a_F260619":4}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:97:17822:18365#0/1_sub[28..127] {"count":3,"merged_sample":{"29a_F260619":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":4}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactgccggcaat
agcttaaaactcaaaggacttggcggtgctttatcccctt
>HELIUM_000100422_612GNAAXX:7:87:6328:12406#0/1_sub[28..126] {"count":6,"merged_sample":{"26a_F040644":6},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":8}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:7:4611:13145#0/1_sub[28..127] {"count":3,"merged_sample":{"13a_F730603":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":4}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtacgtccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:51:16702:19393#0/1_sub[28..127] {"count":12004,"merged_sample":{"15a_F730814":7465,"29a_F260619":4539},"obiclean_head":true,"obiclean_headcount":2,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":0,"obiclean_status":{"15a_F730814":"h","29a_F260619":"h"},"obiclean_weight":{"15a_F730814":8822,"29a_F260619":5789}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:78:6346:5817#0/1_sub[28..127] {"count":5,"merged_sample":{"13a_F730603":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":5}}
ttagccctaaacacaaataattatataaacaaaattattcgccagagtactaccggcaac
agcccaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:7:15122:17310#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":1,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":1,"obiclean_mutation":{"HELIUM_000100422_612GNAAXX:7:94:6384:20392#0/1_sub[28..127]":"(a)->(t)@52"},"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"i","29a_F260619":"s"},"obiclean_weight":{"15a_F730814":1,"29a_F260619":1}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtacttcctgcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:27:7695:17738#0/1_sub[28..126] {"count":7,"merged_sample":{"26a_F040644":7},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":11}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:48:15379:13773#0/1_sub[28..126] {"count":5,"merged_sample":{"26a_F040644":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":5}}
ttagccctaaacatagataattttacaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:117:16246:17184#0/1_sub[28..127] {"count":5,"merged_sample":{"13a_F730603":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":10}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagaggactactagcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:87:11044:6323#0/1_sub[28..126] {"count":69,"merged_sample":{"26a_F040644":69},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":84}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:40:12248:18615#0/1_sub[28..126] {"count":4,"merged_sample":{"26a_F040644":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":4}}
ttagccctaaacataagctattctataacaaaataattcgccagagaactactagcaaca
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:7:6470:13562#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":2}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtacctccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:72:11850:15705#0/1_sub[28..126] {"count":4,"merged_sample":{"26a_F040644":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":4}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:82:8566:4827#0/1_sub[28..126] {"count":6,"merged_sample":{"26a_F040644":6},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":9}}
ttagccctaaacataaacattcaataaacaaggatgttcgcaagagtactactagcaatg
gcctaaaactcaaaggacttggtggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:43:16297:17399#0/1_sub[28..127] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":3}}
ttagccctaaacacaagtaattaatataacaaaattgttcaccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:7:15117:2564#0/1_sub[28..127] {"count":2,"merged_sample":{"13a_F730603":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":2}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtacctccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:90:4058:17862#0/1_sub[28..127] {"count":4,"merged_sample":{"13a_F730603":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":5}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagaggactactagcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:43:13909:1377#0/1_sub[28..126] {"count":10,"merged_sample":{"26a_F040644":10},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":14}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaatg
gcctaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:36:3584:21256#0/1_sub[28..127] {"count":2,"merged_sample":{"13a_F730603":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":2}}
ctagccttaaacacaaatagttatgcaaacaaagctattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttatgccctt
>HELIUM_000100422_612GNAAXX:7:80:13357:2959#0/1_sub[74..81] {"count":12,"merged_sample":{"29a_F260619":12},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":12}}
ccgatagg
>HELIUM_000100422_612GNAAXX:7:70:8097:4516#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaagaaacaagaatgttcaccagagtactactagcaatg
gcctaaaactcaaaggacttggcagtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:7:8746:5790#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtacctctagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:8:9165:18915#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactatgaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:85:7323:6139#0/1_sub[28..126] {"count":9,"merged_sample":{"26a_F040644":9},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":16}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:23:6103:3418#0/1_sub[28..126] {"count":3,"merged_sample":{"26a_F040644":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":4}}
ttagccctaaacatagataattttacaacaaaataattcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:107:2103:10677#0/1_sub[28..127] {"count":20,"merged_sample":{"13a_F730603":20},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":22}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:1:15993:20360#0/1_sub[28..127] {"count":4,"merged_sample":{"13a_F730603":4},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":4}}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactacctgcaat
agcttaaaactcaaaggacttggcggtgctttatgccctt
>HELIUM_000100422_612GNAAXX:7:103:1205:6990#0/1_sub[28..127] {"count":2,"merged_sample":{"13a_F730603":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":2}}
ttagccctaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:111:2380:10482#0/1_sub[28..126] {"count":2,"merged_sample":{"29a_F260619":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":2}}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaata
gcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:76:10530:11312#0/1_sub[28..126] {"count":43,"merged_sample":{"26a_F040644":43},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":69}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:40:15984:4911#0/1_sub[28..126] {"count":16,"merged_sample":{"26a_F040644":16},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":30}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaata
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:109:19171:17424#0/1_sub[28..126] {"count":2,"merged_sample":{"13a_F730603":1,"26a_F040644":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":1,"obiclean_mutation":{"HELIUM_000100422_612GNAAXX:7:50:10637:6527#0/1_sub[28..126]":"(a)->(t)@51"},"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s","26a_F040644":"i"},"obiclean_weight":{"13a_F730603":1,"26a_F040644":1}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggacttctagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:77:17898:19592#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":1,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":2,"obiclean_status":{"15a_F730814":"s","29a_F260619":"s"},"obiclean_weight":{"15a_F730814":1,"29a_F260619":1}}
ttagccctaaacacaagtaattaatataacaaaataattcgccagaggactactagcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:32:4908:16517#0/1_sub[78..81] {"count":7,"merged_sample":{"29a_F260619":7},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":7}}
ccgc
>HELIUM_000100422_612GNAAXX:7:100:8022:19461#0/1_sub[28..127] {"count":5,"merged_sample":{"29a_F260619":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":11}}
ttagccctaaacacaagtaattaatataacaaaataattcgccagagaactactagcaac
agattaaacctcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:59:2390:15297#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaaggatgttcgcaagagtactactagcaatg
gcctaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:98:10839:20244#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":2}}
ttagccctaaacataaacattcaataaacaaggatgttcgccagagtactactagcaatg
gcctaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:34:13086:6440#0/1_sub[28..127] {"count":14,"merged_sample":{"13a_F730603":14},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":18}}
ttagccctaaacacaaataattatataaacaaaattattcgccagagtactaccggcaac
agcccaaaactcaaaggacttggcggtgcttcacaccctt
>HELIUM_000100422_612GNAAXX:7:73:10944:14101#0/1_sub[28..127] {"count":2,"merged_sample":{"13a_F730603":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"13a_F730603":"s"},"obiclean_weight":{"13a_F730603":3}}
ttagccctaaacacaaataattatataaacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:61:17561:21218#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaatcattctataacaaaataattcgccggagaactactaggaaca
gcttaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:93:7569:17305#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaatcagtctataacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:55:11954:15731#0/1_sub[28..126] {"count":6,"merged_sample":{"29a_F260619":6},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":7}}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:84:14502:1617#0/1_sub[28..127] {"count":319,"merged_sample":{"29a_F260619":319},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":376}}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:54:15067:12524#0/1_sub[28..126] {"count":26,"merged_sample":{"26a_F040644":26},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":49}}
ttagccctaaacatagataattttacaacaaaataattcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:6:10451:2548#0/1_sub[28..126] {"count":12,"merged_sample":{"26a_F040644":12},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":15}}
ttagccctaaacataaacagtcaataaacaaggatgttcgccagagtactactagcaatg
gcctaaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:23:10872:20213#0/1_sub[28..126] {"count":2,"merged_sample":{"26a_F040644":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":3}}
ttagccctaaacataaatcattctataacaaaataattcgccggagaactactagcaaca
gcttaaaactcaaaggacttggcggtgccttacgtccct
>HELIUM_000100422_612GNAAXX:7:50:10637:6527#0/1_sub[28..126] {"count":366,"merged_sample":{"13a_F730603":13,"15a_F730814":5,"26a_F040644":347,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":4,"obiclean_singletoncount":3,"obiclean_status":{"13a_F730603":"s","15a_F730814":"s","26a_F040644":"h","29a_F260619":"s"},"obiclean_weight":{"13a_F730603":17,"15a_F730814":5,"26a_F040644":468,"29a_F260619":1}}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:98:6034:5203#0/1_sub[28..127] {"count":3,"merged_sample":{"29a_F260619":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":4}}
ttagccctaaacacaagtaattaatataacaaaattattcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:70:2429:19509#0/1_sub[28..126] {"count":5,"merged_sample":{"26a_F040644":5},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":5}}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgccttacgtccct
>HELIUM_000100422_612GNAAXX:7:65:1843:2567#0/1_sub[28..126] {"count":7,"merged_sample":{"26a_F040644":7},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s"},"obiclean_weight":{"26a_F040644":11}}
ttagccctaaacataaaccattctataacaaaataattcgccagagaactactagcaaca
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:92:1339:19811#0/1_sub[28..127] {"count":3,"merged_sample":{"29a_F260619":3},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"29a_F260619":"s"},"obiclean_weight":{"29a_F260619":3}}
ttagccctaaacacaagtaattacacaaacaaaattgttcacaagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:15:13855:1746#0/1_sub[28..127] {"count":3,"merged_sample":{"15a_F730814":2,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":1,"obiclean_mutation":{"HELIUM_000100422_612GNAAXX:7:7:14405:19348#0/1_sub[28..127]":"(t)->(g)@51"},"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s","29a_F260619":"i"},"obiclean_weight":{"15a_F730814":3,"29a_F260619":1}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtgcgaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:7:7092:11003#0/1_sub[28..127] {"count":2,"merged_sample":{"15a_F730814":2},"obiclean_head":true,"obiclean_headcount":0,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":1,"obiclean_status":{"15a_F730814":"s"},"obiclean_weight":{"15a_F730814":2}}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtacgtccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt

View File

@@ -1,24 +0,0 @@
>HELIUM_000100422_612GNAAXX:7:118:3572:14633#0/1_sub[28..126] {"count":10172,"merged_sample":{"26a_F040644":10172},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":12205},"obitag_bestid":0.9797979797979798,"obitag_bestmatch":"AY227529","obitag_match_count":1,"obitag_rank":"genus","obitag_similarity_method":"lcs","taxid":"taxon:9992 [Marmota]@genus"}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:99:9351:13090#0/1_sub[28..127] {"count":260,"merged_sample":{"29a_F260619":260},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":337},"obitag_bestid":0.9405940594059405,"obitag_bestmatch":"AF154263","obitag_match_count":9,"obitag_rank":"infraorder","obitag_similarity_method":"lcs","taxid":"taxon:35500 [Pecora]@infraorder"}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:10111:9078#0/1_sub[28..127] {"count":7146,"merged_sample":{"13a_F730603":7146},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":8039},"obitag_bestid":1,"obitag_bestmatch":"AB245427","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","taxid":"taxon:9860 [Cervus elaphus]@species"}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:38:14204:12725#0/1_sub[28..126] {"count":87,"merged_sample":{"26a_F040644":87},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":202},"obitag_bestid":0.9494949494949495,"obitag_bestmatch":"AY227530","obitag_match_count":2,"obitag_rank":"tribe","obitag_similarity_method":"lcs","taxid":"taxon:337730 [Marmotini]@tribe"}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:30:9942:4495#0/1_sub[28..126] {"count":95,"merged_sample":{"26a_F040644":11,"29a_F260619":84},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":1,"obiclean_status":{"26a_F040644":"s","29a_F260619":"h"},"obiclean_weight":{"26a_F040644":12,"29a_F260619":105},"obitag_bestid":0.9595959595959596,"obitag_bestmatch":"AC187326","obitag_match_count":1,"obitag_rank":"subspecies","obitag_similarity_method":"lcs","taxid":"taxon:9615 [Canis lupus familiaris]@subspecies"}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:51:16702:19393#0/1_sub[28..127] {"count":12004,"merged_sample":{"15a_F730814":7465,"29a_F260619":4539},"obiclean_head":true,"obiclean_headcount":2,"obiclean_internalcount":0,"obiclean_samplecount":2,"obiclean_singletoncount":0,"obiclean_status":{"15a_F730814":"h","29a_F260619":"h"},"obiclean_weight":{"15a_F730814":8822,"29a_F260619":5789},"obitag_bestid":1,"obitag_bestmatch":"AJ885202","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","taxid":"taxon:9858 [Capreolus capreolus]@species"}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:84:14502:1617#0/1_sub[28..127] {"count":319,"merged_sample":{"29a_F260619":319},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":1,"obiclean_singletoncount":0,"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":376},"obitag_bestid":1,"obitag_bestmatch":"AJ972683","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","taxid":"taxon:9858 [Capreolus capreolus]@species"}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:50:10637:6527#0/1_sub[28..126] {"count":366,"merged_sample":{"13a_F730603":13,"15a_F730814":5,"26a_F040644":347,"29a_F260619":1},"obiclean_head":true,"obiclean_headcount":1,"obiclean_internalcount":0,"obiclean_samplecount":4,"obiclean_singletoncount":3,"obiclean_status":{"13a_F730603":"s","15a_F730814":"s","26a_F040644":"h","29a_F260619":"s"},"obiclean_weight":{"13a_F730603":17,"15a_F730814":5,"26a_F040644":468,"29a_F260619":1},"obitag_bestid":1,"obitag_bestmatch":"AB048590","obitag_match_count":1,"obitag_rank":"genus","obitag_similarity_method":"lcs","taxid":"taxon:9611 [Canis]@genus"}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct

View File

@@ -1,24 +0,0 @@
>seq0001 {"count":10172,"merged_sample":{"26a_F040644":10172},"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":12205},"obitag_bestid":0.9797979797979798,"obitag_bestmatch":"AY227529","obitag_match_count":1,"obitag_rank":"genus","obitag_similarity_method":"lcs","seq_number":1,"taxid":"taxon:9992 [Marmota]@genus"}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>seq0002 {"count":260,"merged_sample":{"29a_F260619":260},"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":337},"obitag_bestid":0.9405940594059405,"obitag_bestmatch":"AF154263","obitag_match_count":9,"obitag_rank":"infraorder","obitag_similarity_method":"lcs","seq_number":2,"taxid":"taxon:35500 [Pecora]@infraorder"}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>seq0003 {"count":7146,"merged_sample":{"13a_F730603":7146},"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":8039},"obitag_bestid":1,"obitag_bestmatch":"AB245427","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","seq_number":3,"taxid":"taxon:9860 [Cervus elaphus]@species"}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>seq0004 {"count":87,"merged_sample":{"26a_F040644":87},"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":202},"obitag_bestid":0.9494949494949495,"obitag_bestmatch":"AY227530","obitag_match_count":2,"obitag_rank":"tribe","obitag_similarity_method":"lcs","seq_number":4,"taxid":"taxon:337730 [Marmotini]@tribe"}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>seq0005 {"count":95,"merged_sample":{"26a_F040644":11,"29a_F260619":84},"obiclean_status":{"26a_F040644":"s","29a_F260619":"h"},"obiclean_weight":{"26a_F040644":12,"29a_F260619":105},"obitag_bestid":0.9595959595959596,"obitag_bestmatch":"AC187326","obitag_match_count":1,"obitag_rank":"subspecies","obitag_similarity_method":"lcs","seq_number":5,"taxid":"taxon:9615 [Canis lupus familiaris]@subspecies"}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcagtgctttatacccct
>seq0006 {"count":12004,"merged_sample":{"15a_F730814":7465,"29a_F260619":4539},"obiclean_status":{"15a_F730814":"h","29a_F260619":"h"},"obiclean_weight":{"15a_F730814":8822,"29a_F260619":5789},"obitag_bestid":1,"obitag_bestmatch":"AJ885202","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","seq_number":6,"taxid":"taxon:9858 [Capreolus capreolus]@species"}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>seq0007 {"count":319,"merged_sample":{"29a_F260619":319},"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":376},"obitag_bestid":1,"obitag_bestmatch":"AJ972683","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","seq_number":7,"taxid":"taxon:9858 [Capreolus capreolus]@species"}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>seq0008 {"count":366,"merged_sample":{"13a_F730603":13,"15a_F730814":5,"26a_F040644":347,"29a_F260619":1},"obiclean_status":{"13a_F730603":"s","15a_F730814":"s","26a_F040644":"h","29a_F260619":"s"},"obiclean_weight":{"13a_F730603":17,"15a_F730814":5,"26a_F040644":468,"29a_F260619":1},"obitag_bestid":1,"obitag_bestmatch":"AB048590","obitag_match_count":1,"obitag_rank":"genus","obitag_similarity_method":"lcs","seq_number":8,"taxid":"taxon:9611 [Canis]@genus"}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct

View File

@@ -1,9 +0,0 @@
id,count,obitag_bestid,obitag_bestmatch,obitag_match_count,obitag_rank,obitag_similarity_method,seq_number,taxid,sequence
seq0001,10172,0.9797979797979798,AY227529,1,genus,lcs,1,taxon:9992 [Marmota]@genus,ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaacagcctgaaactcaaaggacttggcggtgctttacatccct
seq0002,260,0.9405940594059405,AF154263,9,infraorder,lcs,2,taxon:35500 [Pecora]@infraorder,ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaacagcttaaaactcaaaggacttggcggtgctttataccctt
seq0003,7146,1,AB245427,1,species,lcs,3,taxon:9860 [Cervus elaphus]@species,ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttataccctt
seq0004,87,0.9494949494949495,AY227530,2,tribe,lcs,4,taxon:337730 [Marmotini]@tribe,ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaatagcttaaaactcaaaggacttggcggtgctttatatccct
seq0005,95,0.9595959595959596,AC187326,1,subspecies,lcs,5,taxon:9615 [Canis lupus familiaris]@subspecies,ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaacagattaaacctcaaaggacttggcagtgctttatacccct
seq0006,12004,1,AJ885202,1,species,lcs,6,taxon:9858 [Capreolus capreolus]@species,ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttataccctt
seq0007,319,1,AJ972683,1,species,lcs,7,taxon:9858 [Capreolus capreolus]@species,ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttataccctt
seq0008,366,1,AB048590,1,genus,lcs,8,taxon:9611 [Canis]@genus,ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaatagcttaaaactcaaaggacttggcggtgctttatatccct
1 id count obitag_bestid obitag_bestmatch obitag_match_count obitag_rank obitag_similarity_method seq_number taxid sequence
2 seq0001 10172 0.9797979797979798 AY227529 1 genus lcs 1 taxon:9992 [Marmota]@genus ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaacagcctgaaactcaaaggacttggcggtgctttacatccct
3 seq0002 260 0.9405940594059405 AF154263 9 infraorder lcs 2 taxon:35500 [Pecora]@infraorder ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaacagcttaaaactcaaaggacttggcggtgctttataccctt
4 seq0003 7146 1 AB245427 1 species lcs 3 taxon:9860 [Cervus elaphus]@species ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttataccctt
5 seq0004 87 0.9494949494949495 AY227530 2 tribe lcs 4 taxon:337730 [Marmotini]@tribe ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaatagcttaaaactcaaaggacttggcggtgctttatatccct
6 seq0005 95 0.9595959595959596 AC187326 1 subspecies lcs 5 taxon:9615 [Canis lupus familiaris]@subspecies ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaacagattaaacctcaaaggacttggcagtgctttatacccct
7 seq0006 12004 1 AJ885202 1 species lcs 6 taxon:9858 [Capreolus capreolus]@species ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttataccctt
8 seq0007 319 1 AJ972683 1 species lcs 7 taxon:9858 [Capreolus capreolus]@species ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttataccctt
9 seq0008 366 1 AB048590 1 genus lcs 8 taxon:9611 [Canis]@genus ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaatagcttaaaactcaaaggacttggcggtgctttatatccct

View File

@@ -1,6 +0,0 @@
id,seq0001,seq0002,seq0003,seq0004,seq0005,seq0006,seq0007,seq0008
29a_F260619,0,337,0,0,105,5789,376,1
15a_F730814,0,0,0,0,0,8822,0,5
13a_F730603,0,0,8039,0,0,0,0,17
26a_F040644,12205,0,0,202,12,0,0,468
1 id seq0001 seq0002 seq0003 seq0004 seq0005 seq0006 seq0007 seq0008
2 29a_F260619 0 337 0 0 105 5789 376 1
3 15a_F730814 0 0 0 0 0 8822 0 5
4 13a_F730603 0 0 8039 0 0 0 0 17
5 26a_F040644 12205 0 0 202 12 0 0 468

View File

@@ -1,24 +0,0 @@
>HELIUM_000100422_612GNAAXX:7:118:3572:14633#0/1_sub[28..126] {"count":10172,"merged_sample":{"26a_F040644":10172},"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":12205},"obitag_bestid":0.9797979797979798,"obitag_bestmatch":"AY227529","obitag_match_count":1,"obitag_rank":"genus","obitag_similarity_method":"lcs","taxid":"taxon:9992 [Marmota]@genus"}
ttagccctaaacataaacattcaataaacaagaatgttcgccagagtactactagcaaca
gcctgaaactcaaaggacttggcggtgctttacatccct
>HELIUM_000100422_612GNAAXX:7:99:9351:13090#0/1_sub[28..127] {"count":260,"merged_sample":{"29a_F260619":260},"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":337},"obitag_bestid":0.9405940594059405,"obitag_bestmatch":"AF154263","obitag_match_count":9,"obitag_rank":"infraorder","obitag_similarity_method":"lcs","taxid":"taxon:35500 [Pecora]@infraorder"}
ttagccctaaacacaaataattacacaaacaaaattgttcaccagagtactagcggcaac
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:108:10111:9078#0/1_sub[28..127] {"count":7146,"merged_sample":{"13a_F730603":7146},"obiclean_status":{"13a_F730603":"h"},"obiclean_weight":{"13a_F730603":8039},"obitag_bestid":1,"obitag_bestmatch":"AB245427","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","taxid":"taxon:9860 [Cervus elaphus]@species"}
ctagccttaaacacaaatagttatgcaaacaaaactattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:38:14204:12725#0/1_sub[28..126] {"count":87,"merged_sample":{"26a_F040644":87},"obiclean_status":{"26a_F040644":"h"},"obiclean_weight":{"26a_F040644":202},"obitag_bestid":0.9494949494949495,"obitag_bestmatch":"AY227530","obitag_match_count":2,"obitag_rank":"tribe","obitag_similarity_method":"lcs","taxid":"taxon:337730 [Marmotini]@tribe"}
ttagccctaaacataaacattcaataaacaagaatgttcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct
>HELIUM_000100422_612GNAAXX:7:30:9942:4495#0/1_sub[28..126] {"count":95,"merged_sample":{"26a_F040644":11,"29a_F260619":84},"obiclean_status":{"26a_F040644":"s","29a_F260619":"h"},"obiclean_weight":{"26a_F040644":12,"29a_F260619":105},"obitag_bestid":0.9595959595959596,"obitag_bestmatch":"AC187326","obitag_match_count":1,"obitag_rank":"subspecies","obitag_similarity_method":"lcs","taxid":"taxon:9615 [Canis lupus familiaris]@subspecies"}
ttagccctaaacataagctattccataacaaaataattcgccagagaactactagcaaca
gattaaacctcaaaggacttggcagtgctttatacccct
>HELIUM_000100422_612GNAAXX:7:51:16702:19393#0/1_sub[28..127] {"count":12004,"merged_sample":{"15a_F730814":7465,"29a_F260619":4539},"obiclean_status":{"15a_F730814":"h","29a_F260619":"h"},"obiclean_weight":{"15a_F730814":8822,"29a_F260619":5789},"obitag_bestid":1,"obitag_bestmatch":"AJ885202","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","taxid":"taxon:9858 [Capreolus capreolus]@species"}
ttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:84:14502:1617#0/1_sub[28..127] {"count":319,"merged_sample":{"29a_F260619":319},"obiclean_status":{"29a_F260619":"h"},"obiclean_weight":{"29a_F260619":376},"obitag_bestid":1,"obitag_bestmatch":"AJ972683","obitag_match_count":1,"obitag_rank":"species","obitag_similarity_method":"lcs","taxid":"taxon:9858 [Capreolus capreolus]@species"}
ttagccctaaacacaagtaattattataacaaaattattcgccagagtactaccggcaat
agcttaaaactcaaaggacttggcggtgctttataccctt
>HELIUM_000100422_612GNAAXX:7:50:10637:6527#0/1_sub[28..126] {"count":366,"merged_sample":{"13a_F730603":13,"15a_F730814":5,"26a_F040644":347,"29a_F260619":1},"obiclean_status":{"13a_F730603":"s","15a_F730814":"s","26a_F040644":"h","29a_F260619":"s"},"obiclean_weight":{"13a_F730603":17,"15a_F730814":5,"26a_F040644":468,"29a_F260619":1},"obitag_bestid":1,"obitag_bestmatch":"AB048590","obitag_match_count":1,"obitag_rank":"genus","obitag_similarity_method":"lcs","taxid":"taxon:9611 [Canis]@genus"}
ttagccctaaacatagataattttacaacaaaataattcgccagaggactactagcaata
gcttaaaactcaaaggacttggcggtgctttatatccct

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Cookbook on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/cookbook/</link>
<description>Recent content in Cookbook on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/cookbook/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,102 +0,0 @@
SHELL := /bin/bash
FTPNCBI=ftp.ncbi.nlm.nih.gov
GBURL=https://$(FTPNCBI)/genbank
GBRELEASE_URL=$(GBURL)/GB_Release_Number
TAXOURL=https://$(FTPNCBI)/pub/taxonomy/taxdump.tar.gz
GBRELEASE:=$(shell curl $(GBRELEASE_URL))
GBDIV_ALL:=$(shell curl -L ${GBURL} \
| grep -E 'gb.+\.seq\.gz' \
| sed -E 's@^.*<a href="gb([^0-9]+)[0-9]+\.seq.gz.*$$@\1@' \
| sort \
| uniq)
GBDIV=bct inv mam phg pln pri rod vrl vrt
DIRECTORIES=fasta fasta_fgs
GBFILE_ALL:=$(shell curl -L ${GBURL} \
| grep -E "gb($$(tr ' ' '|' <<< "${GBDIV}"))[0-9]+" \
| sed -E 's@^<a href="(gb.+.seq.gz)">.*$$@\1@')
SUFFIXES += .d
NODEPS:=clean taxonomy
DEPFILES:=$(wildcard Release_$(GBRELEASE)/depends/*.d)
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
#Chances are, these files don't exist. GMake will create them and
#clean up automatically afterwards
-include $(DEPFILES)
endif
all: depends directories FORCE
@make downloads
downloads: taxonomy fasta_files
@echo Genbank Release number $(GBRELEASE)
@echo all divisions : $(GBDIV_ALL)
FORCE:
.PHONY: all directories depends taxonomy fasta_files FORCE
depends: directories Release_$(GBRELEASE)/depends/gbfiles.d Makefile
division: $(GBDIV)
taxonomy: directories Release_$(GBRELEASE)/taxonomy
directories: Release_$(GBRELEASE)/fasta Release_$(GBRELEASE)/stamp Release_$(GBRELEASE)/tmp
Release_$(GBRELEASE):
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/fasta: Release_$(GBRELEASE)
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/stamp: Release_$(GBRELEASE)
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/tmp: Release_$(GBRELEASE)
@mkdir -p $@
@echo Create $@ directory
Release_$(GBRELEASE)/depends/gbfiles.d: Makefile
@echo Create depends directory
@mkdir -p Release_$(GBRELEASE)/depends
@for f in ${GBFILE_ALL} ; do \
echo -e "Release_$(GBRELEASE)/stamp/$$f.stamp:" ; \
echo -e "\t@echo Downloading file : $$f..." ; \
echo -e "\t@mkdir -p Release_$(GBRELEASE)/tmp" ; \
echo -e "\t@mkdir -p Release_$(GBRELEASE)/stamp" ; \
echo -e "\t@curl -L ${GBURL}/$$f > Release_$(GBRELEASE)/tmp/$$f && touch \$$@" ; \
echo ; \
div=$$(sed -E 's@^gb(...).*$$@\1@' <<< $$f) ; \
fasta="Release_$(GBRELEASE)/fasta/$$div/$${f/.seq.gz/.fasta.gz}" ; \
fasta_fgs="Release_$(GBRELEASE)/fasta_fgs/$$div/$${f/.seq.gz/.fasta.gz}" ; \
fasta_files="$$fasta_files $$fasta" ; \
fasta_fgs_files="$$fasta_fgs_files $$fasta_fgs" ; \
echo -e "$$fasta: Release_$(GBRELEASE)/stamp/$$f.stamp" ; \
echo -e "\t@echo converting file : \$$< in fasta" ; \
echo -e "\t@mkdir -p Release_$(GBRELEASE)/fasta/$$div" ; \
echo -e "\t@obiconvert -Z --fasta-output --skip-empty \\" ; \
echo -e "\t Release_$(GBRELEASE)/tmp/$$f > Release_$(GBRELEASE)/tmp/$${f/.seq.gz/.fasta.gz} \\" ; \
echo -e "\t && mv Release_$(GBRELEASE)/tmp/$${f/.seq.gz/.fasta.gz} \$$@ \\" ; \
echo -e "\t && rm -f Release_$(GBRELEASE)/tmp/$$f \\" ; \
echo -e "\t || rm -f \$$@" ; \
echo -e "\t@echo conversion of $$@ done." ; \
echo ; \
done > $@ ; \
echo >> $@ ; \
echo "fasta_files: $$fasta_files" >> $@ ;
Release_$(GBRELEASE)/taxonomy:
mkdir -p $@
curl -iL $(TAXOURL) \
| tar -C $@ -zxf -

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Prepare a local copy of Genbank on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/cookbook/local_genbank/</link>
<description>Recent content in Prepare a local copy of Genbank on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/cookbook/local_genbank/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Oxford Nanopore data analysis on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/cookbook/minion/</link>
<description>Recent content in Oxford Nanopore data analysis on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/cookbook/minion/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Build a reference database on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/cookbook/reference_db/</link>
<description>Recent content in Build a reference database on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<lastBuildDate></lastBuildDate>
<atom:link href="http://metabar:8888/obidoc/docs/cookbook/reference_db/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>File formats on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/file_format/</link>
<description>Recent content in File formats on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/file_format/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Annotation of sequences on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/file_format/sequence_files/annotations/</link>
<description>Recent content in Annotation of sequences on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/file_format/sequence_files/annotations/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>CSV format on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/file_format/sequence_files/csv/</link>
<description>Recent content in CSV format on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/file_format/sequence_files/csv/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,6 +0,0 @@
>AB061527 {"count":1,"definition":"Sorex unguiculatus mitochondrial NA, complete genome.","family_name":"Soricidae","family_taxid":9376,"genus_name":"Sorex","genus_taxid":9379,"obicleandb_level":"family","obicleandb_trusted":2.2137847111025621e-13,"species_name":"Sorex unguiculatus","species_taxid":62275,"taxid":62275}
ttagccctaaacttaggtatttaatctaacaaaaatacccgtcagagaactactagcaat
agcttaaaactcaaaggacttggcggtgctttatatccct
>AL355887 {"count":2,"definition":"Human chromosome 14 NA sequence BAC R-179O11 of library RPCI-11 from chromosome 14 of Homo sapiens (Human)XXKW HTG.; HTGS_ACTIVFIN.","family_name":"Hominidae","family_taxid":9604,"genus_name":"Homo","genus_taxid":9605,"obicleandb_level":"genus","obicleandb_trusted":0,"species_name":"Homo sapiens","species_taxid":9606,"taxid":9606}
ttagccctaaactctagtagttacattaacaaaaccattcgtcagaatactacgagcaac
agcttaaaactcaaaggacctggcagttctttatatccct

View File

@@ -1,8 +0,0 @@
@HELIUM_000100422_612GNAAXX:7:108:5640:3823#0/1 {"ali_dir":"left","ali_length":62,"mode":"alignment","pairing_mismatches":{"(T:26)->(G:13)":62,"(T:34)->(G:18)":48},"score":484,"score_norm":0.968,"seq_a_single":46,"seq_ab_match":60,"seq_b_single":46}
ccgcctcctttagataccccactatgcttagccctaaacacaagtaattaatataacaaaattgttcgccagagtactaccggcaatagcttaaaactcaaaggacttggcggtgctttatacccttctagaggagcctgttctaaggaggcgg
+
CCCCCCCBCCCCCCCCCCCCCCCCCCCCCCBCCCCCBCCCCCCC<CcCccbe[`F`accXV<TA\RYU\\ee_e[XZ[XEEEEEEEEEE?EEEEEEEEEEDEEEEEEECCCCCCCCCCCCCCCCCCCCCCCACCCCCACCCCCCCCCCCCCCCC
@HELIUM_000100422_612GNAAXX:7:97:14311:19299#0/1 {"ali_dir":"left","ali_length":62,"mode":"alignment","pairing_mismatches":{"(A:02)->(G:30)":104,"(A:34)->(G:14)":64,"(C:02)->(A:30)":86,"(C:02)->(T:20)":108,"(C:27)->(G:32)":83,"(C:34)->(G:18)":57,"(T:02)->(G:26)":87,"(T:22)->(G:14)":66,"(T:29)->(G:11)":62,"(T:32)->(G:30)":48},"score":283,"score_norm":0.839,"seq_a_single":46,"seq_ab_match":52,"seq_b_single":46}
ccgcctcctttagataccccactatgcttagccctaaacacaagtaattaatataacaaaattattcgccagagtactaccggcaagagcttaaaactcaaaggacttggcggtgctttatacccttctagaggagcctgttctaaggaggcgg
+
CCCCCCCCCCCCCCCCCCCCCCCBBCCC?BCCCCCBC?CCCC@@;AVA`cWeb_TYC\UIN?IDP8QJMKRPVGLQAFPPc`AbAFB5A4>AAA56A><>8>>F@A><8??@BB+<?;?C@9CCCCCC<CC=CCCCCCCCCBC?CBCCCCC@CC

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Sequence file formats on OBITools4 documentation</title>
<link>http://metabar:8888/obidoc/docs/file_format/sequence_files/</link>
<description>Recent content in Sequence file formats on OBITools4 documentation</description>
<generator>Hugo</generator>
<language>en-us</language>
<atom:link href="http://metabar:8888/obidoc/docs/file_format/sequence_files/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1,30 +0,0 @@
taxid,parent,taxonomic_rank,scientific_name
taxon:1 [root]@no rank,taxon:1 [root]@no rank,no rank,root
taxon:131567 [cellular organisms]@no rank,taxon:1 [root]@no rank,no rank,cellular organisms
taxon:2759 [Eukaryota]@superkingdom,taxon:131567 [cellular organisms]@no rank,superkingdom,Eukaryota
taxon:33090 [Viridiplantae]@kingdom,taxon:2759 [Eukaryota]@superkingdom,kingdom,Viridiplantae
taxon:35493 [Streptophyta]@phylum,taxon:33090 [Viridiplantae]@kingdom,phylum,Streptophyta
taxon:131221 [Streptophytina]@subphylum,taxon:35493 [Streptophyta]@phylum,subphylum,Streptophytina
taxon:3193 [Embryophyta]@clade,taxon:131221 [Streptophytina]@subphylum,clade,Embryophyta
taxon:58023 [Tracheophyta]@clade,taxon:3193 [Embryophyta]@clade,clade,Tracheophyta
taxon:78536 [Euphyllophyta]@clade,taxon:58023 [Tracheophyta]@clade,clade,Euphyllophyta
taxon:58024 [Spermatophyta]@clade,taxon:78536 [Euphyllophyta]@clade,clade,Spermatophyta
taxon:3398 [Magnoliopsida]@class,taxon:58024 [Spermatophyta]@clade,class,Magnoliopsida
taxon:1437183 [Mesangiospermae]@clade,taxon:3398 [Magnoliopsida]@class,clade,Mesangiospermae
taxon:71240 [eudicotyledons]@clade,taxon:1437183 [Mesangiospermae]@clade,clade,eudicotyledons
taxon:91827 [Gunneridae]@clade,taxon:71240 [eudicotyledons]@clade,clade,Gunneridae
taxon:1437201 [Pentapetalae]@clade,taxon:91827 [Gunneridae]@clade,clade,Pentapetalae
taxon:71275 [rosids]@clade,taxon:1437201 [Pentapetalae]@clade,clade,rosids
taxon:91835 [fabids]@clade,taxon:71275 [rosids]@clade,clade,fabids
taxon:3502 [Fagales]@order,taxon:91835 [fabids]@clade,order,Fagales
taxon:3514 [Betulaceae]@family,taxon:3502 [Fagales]@order,family,Betulaceae
taxon:3504 [Betula]@genus,taxon:3514 [Betulaceae]@family,genus,Betula
taxon:1685988 [Betula murrayana]@species,taxon:3504 [Betula]@genus,species,Betula murrayana
taxon:361422 [Betula ovalifolia]@species,taxon:3504 [Betula]@genus,species,Betula ovalifolia
taxon:1685972 [Betula x caerulea]@species,taxon:3504 [Betula]@genus,species,Betula x caerulea
taxon:216986 [Betula schmidtii]@species,taxon:3504 [Betula]@genus,species,Betula schmidtii
taxon:312791 [Betula michauxii]@species,taxon:3504 [Betula]@genus,species,Betula michauxii
taxon:3015411 [Betula pamirica]@species,taxon:3504 [Betula]@genus,species,Betula pamirica
taxon:312792 [Betula raddeana]@species,taxon:3504 [Betula]@genus,species,Betula raddeana
taxon:216991 [Betula humilis]@species,taxon:3504 [Betula]@genus,species,Betula humilis
taxon:2218489 [Betula ovalifolia x Betula ermanii]@species,taxon:3504 [Betula]@genus,species,Betula ovalifolia x Betula ermanii
1 taxid parent taxonomic_rank scientific_name
2 taxon:1 [root]@no rank taxon:1 [root]@no rank no rank root
3 taxon:131567 [cellular organisms]@no rank taxon:1 [root]@no rank no rank cellular organisms
4 taxon:2759 [Eukaryota]@superkingdom taxon:131567 [cellular organisms]@no rank superkingdom Eukaryota
5 taxon:33090 [Viridiplantae]@kingdom taxon:2759 [Eukaryota]@superkingdom kingdom Viridiplantae
6 taxon:35493 [Streptophyta]@phylum taxon:33090 [Viridiplantae]@kingdom phylum Streptophyta
7 taxon:131221 [Streptophytina]@subphylum taxon:35493 [Streptophyta]@phylum subphylum Streptophytina
8 taxon:3193 [Embryophyta]@clade taxon:131221 [Streptophytina]@subphylum clade Embryophyta
9 taxon:58023 [Tracheophyta]@clade taxon:3193 [Embryophyta]@clade clade Tracheophyta
10 taxon:78536 [Euphyllophyta]@clade taxon:58023 [Tracheophyta]@clade clade Euphyllophyta
11 taxon:58024 [Spermatophyta]@clade taxon:78536 [Euphyllophyta]@clade clade Spermatophyta
12 taxon:3398 [Magnoliopsida]@class taxon:58024 [Spermatophyta]@clade class Magnoliopsida
13 taxon:1437183 [Mesangiospermae]@clade taxon:3398 [Magnoliopsida]@class clade Mesangiospermae
14 taxon:71240 [eudicotyledons]@clade taxon:1437183 [Mesangiospermae]@clade clade eudicotyledons
15 taxon:91827 [Gunneridae]@clade taxon:71240 [eudicotyledons]@clade clade Gunneridae
16 taxon:1437201 [Pentapetalae]@clade taxon:91827 [Gunneridae]@clade clade Pentapetalae
17 taxon:71275 [rosids]@clade taxon:1437201 [Pentapetalae]@clade clade rosids
18 taxon:91835 [fabids]@clade taxon:71275 [rosids]@clade clade fabids
19 taxon:3502 [Fagales]@order taxon:91835 [fabids]@clade order Fagales
20 taxon:3514 [Betulaceae]@family taxon:3502 [Fagales]@order family Betulaceae
21 taxon:3504 [Betula]@genus taxon:3514 [Betulaceae]@family genus Betula
22 taxon:1685988 [Betula murrayana]@species taxon:3504 [Betula]@genus species Betula murrayana
23 taxon:361422 [Betula ovalifolia]@species taxon:3504 [Betula]@genus species Betula ovalifolia
24 taxon:1685972 [Betula x caerulea]@species taxon:3504 [Betula]@genus species Betula x caerulea
25 taxon:216986 [Betula schmidtii]@species taxon:3504 [Betula]@genus species Betula schmidtii
26 taxon:312791 [Betula michauxii]@species taxon:3504 [Betula]@genus species Betula michauxii
27 taxon:3015411 [Betula pamirica]@species taxon:3504 [Betula]@genus species Betula pamirica
28 taxon:312792 [Betula raddeana]@species taxon:3504 [Betula]@genus species Betula raddeana
29 taxon:216991 [Betula humilis]@species taxon:3504 [Betula]@genus species Betula humilis
30 taxon:2218489 [Betula ovalifolia x Betula ermanii]@species taxon:3504 [Betula]@genus species Betula ovalifolia x Betula ermanii

Some files were not shown because too many files have changed in this diff Show More