From 93dd116ffd65b30ba9b69d598dbcffe472d26834 Mon Sep 17 00:00:00 2001 From: slsevilla Date: Mon, 8 Jan 2024 22:41:28 +0000 Subject: [PATCH] Deployed 20b8cd9 with MkDocs version: 1.4.2 --- .nojekyll | 0 404.html | 1 + GitHub/basic_actions/index.html | 1 + GitHub/basic_docs/index.html | 146 + GitHub/basic_repo/index.html | 17 + GitHub/howto_functions/index.html | 17 + GitHub/howto_precommit/index.html | 39 + GitHub/howto_setup/index.html | 5 + GitHub/overview/index.html | 1 + GitHub/sop_projpipes/index.html | 2 + GitHub/sop_techdev/index.html | 1 + HPCDME/setup/index.html | 81 + HPCDME/transfer/index.html | 93 + OtherHowTos/datashare/index.html | 19 + OtherHowTos/zenodo/index.html | 1 + Rpackage/build_pkg/index.html | 118 + Rpackage/common_issues/index.html | 14 + Rpackage/setup/index.html | 19 + Tutorials/snakemake/index.html | 1 + UCSC/creating_inputs/index.html | 49 + UCSC/creating_track_info/index.html | 77 + UCSC/creating_tracks/index.html | 1 + UCSC/overview/index.html | 1 + assets/images/doc-book.svg | 9 + assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.51d95adb.min.js | 29 + assets/javascripts/bundle.51d95adb.min.js.map | 8 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.e5c33ebb.min.js | 42 + .../workers/search.e5c33ebb.min.js.map | 8 + assets/stylesheets/main.558e4712.min.css | 1 + assets/stylesheets/main.558e4712.min.css.map | 1 + assets/stylesheets/palette.2505c338.min.css | 1 + .../stylesheets/palette.2505c338.min.css.map | 1 + contributions/index.html | 1 + images/gitmodel.png | Bin 0 -> 124925 bytes index.html | 8 + requirements.txt | 6 + search/search_index.json | 1 + sitemap.xml | 118 + sitemap.xml.gz | Bin 0 -> 213 bytes 68 files changed, 8133 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 GitHub/basic_actions/index.html create mode 100644 GitHub/basic_docs/index.html create mode 100644 GitHub/basic_repo/index.html create mode 100644 GitHub/howto_functions/index.html create mode 100644 GitHub/howto_precommit/index.html create mode 100644 GitHub/howto_setup/index.html create mode 100644 GitHub/overview/index.html create mode 100644 GitHub/sop_projpipes/index.html create mode 100644 GitHub/sop_techdev/index.html create mode 100644 HPCDME/setup/index.html create mode 100644 HPCDME/transfer/index.html create mode 100644 OtherHowTos/datashare/index.html create mode 100644 OtherHowTos/zenodo/index.html create mode 100644 Rpackage/build_pkg/index.html create mode 100644 Rpackage/common_issues/index.html create mode 100644 Rpackage/setup/index.html create mode 100644 Tutorials/snakemake/index.html create mode 100644 UCSC/creating_inputs/index.html create mode 100644 UCSC/creating_track_info/index.html create mode 100644 UCSC/creating_tracks/index.html create mode 100644 UCSC/overview/index.html create mode 100644 assets/images/doc-book.svg create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.51d95adb.min.js create mode 100644 assets/javascripts/bundle.51d95adb.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.e5c33ebb.min.js create mode 100644 assets/javascripts/workers/search.e5c33ebb.min.js.map create mode 100644 assets/stylesheets/main.558e4712.min.css create mode 100644 assets/stylesheets/main.558e4712.min.css.map create mode 100644 assets/stylesheets/palette.2505c338.min.css create mode 100644 assets/stylesheets/palette.2505c338.min.css.map create mode 100644 contributions/index.html create mode 100644 images/gitmodel.png create mode 100644 index.html create mode 100644 requirements.txt create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..93001e5 --- /dev/null +++ b/404.html @@ -0,0 +1 @@ + CCBR How Tos
\ No newline at end of file diff --git a/GitHub/basic_actions/index.html b/GitHub/basic_actions/index.html new file mode 100644 index 0000000..866f7cd --- /dev/null +++ b/GitHub/basic_actions/index.html @@ -0,0 +1 @@ + Creating GitHub Actions - CCBR How Tos
Skip to content

GitHub Basics: GitHub Actions

The following describe the minimum GitHub actions that should be deployed with any production pipeline. The actions are automatically provided via the cookiecutter templates: NextFlow and Snakemake.

  1. Documentation (assumes mkdocs build; required for all repos)

    • These rules will automatically update any documentation built with mkdocs for all PR's.
    • Rule Name(s): mkdocs_build → pages-build-and-deployment
  2. Lintr (required for CCBR projects and new pipelines)

    • This rule will automatically perform a lintr with the data provided in the .test folder of the pipeline. Review the GitHub Best Practices - Test Data page for more information.
  3. Dry-run with test sample data for any PR to dev branch (required for CCBR projects and new pipelines)

    • This rule will automatically perform a dry-run with the data provided in the .test folder of the pipeline. Review the GitHub Best Practices - Test Data page for more information.
  4. Full-run with full sample data for any PR to main branch (required for CCBR projects and new pipelines)

    • This rule will automatically perform a full-run with the data provided in the .test folder of the pipeline. Review the GitHub Best Practices - Test Data page for more information.
  5. Auto pull/push from source (if applicable for CCBR projects and new pipelines)

    • If the pipeline is forked from another location and updating this forked pipeline is required, an action will automatically perform a pull from the source location at least once a week.

Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/basic_docs/index.html b/GitHub/basic_docs/index.html new file mode 100644 index 0000000..57b753c --- /dev/null +++ b/GitHub/basic_docs/index.html @@ -0,0 +1,146 @@ + Creating your Documentation - CCBR How Tos
Skip to content

GitHub Basics: Documentation

GitHub Pages is quick and easy way to build static websites for your GitHub repositories. Essentially, you write pages in Markdown which are then rendered to HTML and hosted on GitHub, free of cost!

CCBR has used GitHub pages to provide extensive, legible and organized documentation for our pipelines. Examples are included below:

Mkdocs is the with documentation tool preferred, with the Material theme, for most of the CCBR GitHub Pages websites.

Install MkDocs, themes

mkdocs and the Material for mkdocs theme can be installed using the following:

pip install --upgrade pip
+pip install mkdocs
+pip install mkdocs-material
+

Also install other common dependencies:

pip install mkdocs-pymdownx-material-extras
+pip install mkdocs-git-revision-date-localized-plugin
+pip install mkdocs-git-revision-date-plugin
+pip install mkdocs-minify-plugin
+

Conventions

Generally, for GitHub repos with GitHub pages:

  • The repository needs to be public (not private)
  • The main/master branch has the markdown documents under a docs folder at the root level
  • Rendered HTMLs are hosted under a gh-pages branch at root level

Create website

The following steps can be followed to build your first website

Add mkdocs.yaml

mkdocs.yaml needs to be added to the root of the master branch. A template of this file is available in the cookiecutter template.

git clone https://github.com/CCBR/xyz.git
+cd xyz
+vi mkdocs.yaml
+git add mkdocs.yaml
+git commit -m "adding mkdocs.yaml"
+git push
+

Here is a sample mkdocs.yaml:

# Project Information
+site_name: CCBR How Tos
+site_author: Vishal Koparde, Ph.D.
+site_description: >-
+  The **DEVIL** is in the **DETAILS**. Step-by-step detailed How To Guides for data management and other CCBR-relevant tasks.
+
+# Repository
+repo_name: CCBR/HowTos
+repo_url: https://github.com/CCBR/HowTos
+edit_uri: https://github.com/CCBR/HowTos/edit/main/docs/
+
+# Copyright
+copyright: Copyright © 2023 CCBR
+
+# Configuration
+theme:
+  name: material
+  features:
+    - navigation.tabs
+    - navigation.top
+    - navigation.indexes
+    - toc.integrate 
+  palette:
+    - scheme: default
+      primary: indigo
+      accent: indigo
+      toggle:
+        icon: material/toggle-switch-off-outline
+        name: Switch to dark mode
+    - scheme: slate
+      primary: red
+      accent: red
+      toggle:
+        icon: material/toggle-switch
+        name: Switch to light mode
+  logo: assets/images/doc-book.svg
+  favicon: assets/images/favicon.png
+
+# Plugins
+plugins:
+  - search
+  - git-revision-date
+  - minify:
+      minify_html: true
+
+
+# Customization
+extra:
+  social:
+    - icon: fontawesome/solid/users
+      link: http://bioinformatics.cancer.gov
+    - icon: fontawesome/brands/github
+      link: https://github.com/CCRGeneticsBranch
+    - icon: fontawesome/brands/docker
+      link: https://hub.docker.com/orgs/nciccbr/repositories
+  version:
+    provider: mike
+
+
+# Extensions
+markdown_extensions:
+  - markdown.extensions.admonition
+  - markdown.extensions.attr_list
+  - markdown.extensions.def_list
+  - markdown.extensions.footnotes
+  - markdown.extensions.meta
+  - markdown.extensions.toc:
+      permalink: true
+  - pymdownx.arithmatex:
+      generic: true
+  - pymdownx.betterem:
+      smart_enable: all
+  - pymdownx.caret
+  - pymdownx.critic
+  - pymdownx.details
+  - pymdownx.emoji:
+      emoji_index: !!python/name:materialx.emoji.twemoji
+      emoji_generator: !!python/name:materialx.emoji.to_svg
+  - pymdownx.highlight
+  - pymdownx.inlinehilite
+  - pymdownx.keys
+  - pymdownx.magiclink:
+      repo_url_shorthand: true
+      user: squidfunk
+      repo: mkdocs-material
+  - pymdownx.mark
+  - pymdownx.smartsymbols
+  - pymdownx.snippets:
+      check_paths: true
+  - pymdownx.superfences
+  - pymdownx.tabbed
+  - pymdownx.tasklist:
+      custom_checkbox: true
+  - pymdownx.tilde
+
+# Page Tree
+nav:
+  - Intro : index.md
+

Create index.md

Create docs folder, add your index.md there.

mkdir docs
+echo "### Testing" > docs/index.md
+git add docs/index.md
+git commit -m "adding landing page"
+git push
+

Build site

mkdocs can now be used to render .md to HTML

mkdocs build
+INFO     -  Cleaning site directory
+INFO     -  Building documentation to directory: /Users/$USER/Documents/GitRepos/parkit/site
+INFO     -  Documentation built in 0.32 seconds
+

The above command creates a local site folder which is the root of your "to-be-hosted" website. You can now open the HTMLs in the site folder locally to ensure that that HTML is as per you liking. If not, then you can make edits to the .md files and rebuild the site.

NOTE: You do not want to push the site folder back to GH and hence it needs to be added to .gitignore file:

echo "**/site/*" > .gitignore
+git add .gitignore
+git commit -m "adding .gitignore"
+git push
+

Deploy site

The following command with auto-create a gh-pages branch (if it does not exist) and copy the contents of the site folder to the root of that branch. It will also provide you the URL to your newly created website.

mkdocs gh-deploy
+INFO     -  Cleaning site directory
+INFO     -  Building documentation to directory: /Users/kopardevn/Documents/GitRepos/xyz/site
+INFO     -  Documentation built in 0.34 seconds
+WARNING  -  Version check skipped: No version specified in previous deployment.
+INFO     -  Copying '/Users/kopardevn/Documents/GitRepos/xyz/site' to 'gh-pages' branch and pushing to
+            GitHub.
+Enumerating objects: 51, done.
+Counting objects: 100(51/51), done.
+Delta compression using up to 16 threads
+Compressing objects: 100(47/47), done.
+Writing objects: 100(51/51), 441.71 KiB | 4.29 MiB/s, done.
+Total 51 (delta 4), reused 0 (delta 0), pack-reused 0
+remote: Resolving deltas: 100(4/4), done.
+remote:
+remote: Create a pull request for 'gh-pages' on GitHub by visiting:
+remote:      https://github.com/CCBR/xyz/pull/new/gh-pages
+remote:
+To https://github.com/CCBR/xyz.git
+ * [new branch]      gh-pages -> gh-pages
+INFO     -  Your documentation should shortly be available at: https://CCBR.github.io/xyz/
+

Now if you point your web browser to the URL from gh-deploy command (IE https://CCBR.github.io/xyz/) you will see your HTML hosted on GitHub. After creating your docs, the cookiecutter template includes a GitHub action which will automatically perform the above tasks whenever a push is performed to the main branch.

Add to the GitHub page

  1. Go to the main GitHub page of your repository
  2. On the top right select the gear icon next to About
  3. Under Website, select Use your GitHub Pages website.
  4. Select Save Changes

Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/basic_repo/index.html b/GitHub/basic_repo/index.html new file mode 100644 index 0000000..75c62ab --- /dev/null +++ b/GitHub/basic_repo/index.html @@ -0,0 +1,17 @@ + Creating your GitHub Repo - CCBR How Tos
Skip to content

GitHub Basics: Repository

Repository Location

All CCBR developed pipelines, and techdev efforts should be created under CCBR's GitHub Org Account and all CCBR team members should have a minimal of read-only permission to the repository.

Use of CookieCutter Templates

Note: The above templates are themselves under active development! As we continue building a multitude of analysis pipelines, we keep expanding on the list of "commonalities" between these analysis pipelines which need to be added to the template itself. Hence, templates are updated from time-to-time.

Creating a new repository

To create a new repository on Github using gh cli, you can run the following command on Biowulf after you update the new repository name (<ADD NEW REPO NAME>) and the repository description (<ADD REPO DESCRIPTION>) commands below.

Naming Nomenclature: - All Repositories: Do not remove the CCBR/ leading the repository name, as this will correctly place the repository under the CCBR organization account. - CCBR Projects: These should be named with the CCBR#. IE CCBR/CCBR1155 - CCBR Pipelines: These should be descriptive of the pipelines main process; acronyms are encouraged. IE CCBR/CARLISLE - TechDev projects: These should be descriptive of the techDev project to be performed and should begin with techdev_. IE CCBR/techdev_peakcall_benchmarking

1) Creating a new project OR new pipeline repository

gh repo create CCBR/<ADD NEW REPO NAME> \
+--template CCBR/CCBR_NextflowTemplate \
+--description "<ADD REPO DESCRIPTION>" \
+--public \
+--confirm
+
gh repo create CCBR/<ADD NEW REPO NAME> \
+--template CCBR/CCBR_SnakemakeTemplate \
+--description "<ADD REPO DESCRIPTION>" \
+--public \
+--confirm
+

2) Creating a new techDev

gh repo create CCBR/techdev_<ADD NEW REPO NAME> \
+--template CCBR/CCBR_TechDevTemplate \
+--description "<ADD REPO DESCRIPTION>" \
+--public \
+--confirm
+

Once the repo is created, then you can clone a local copy of the new repository:

gh repo clone CCBR/<reponame>.git
+

Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/howto_functions/index.html b/GitHub/howto_functions/index.html new file mode 100644 index 0000000..9186e49 --- /dev/null +++ b/GitHub/howto_functions/index.html @@ -0,0 +1,17 @@ + Basic Commands - CCBR How Tos
Skip to content

GitHub HowTo: Basic Functions

The following outlines basic GitHub function to push and pull from your repository. It also includes information on creating a new branch and deleting a branch. These commands should be used in line with guidance on GitHub Repo Management.

Pushing local changes to remote

Check which files have been changed.

git status
+

Stage files that need to be pushed

git add <thisfile>
+git add <thatfile>
+

Push changes to branch named new_feature

git push origin new_feature
+

Pulling remote changes to local

Pull changes from branch new_feature into your branch old_feature

git checkout old_feature
+git pull new_feature
+

If you have non-compatible changes in the old_feature branch, there are two options: 1) ignore local changes and pull remote anyways. This will delete the changes you've made to your remote respository.

git reset --hard
+git pull
+
2) temporarily stash changes away, pull and reapply changes after.
git stash
+git pull
+git stash pop
+

Creating a new branch

This is a two step process.

  • Create the branch locally

    git checkout -b <newbranch>
    +

  • Push the branch to remote

    git push -u origin <newbranch>
    +
    OR
    git push -u origin HEAD
    +
    This is a shortcut to push the current branch to a branch of the same name on origin and track it so that you don't need to specify origin HEAD in the future.

Deleting branches

Locally

git branch -d <BranchName>
+

on GitHub

git push origin --delete <BranchName>
+

Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/howto_precommit/index.html b/GitHub/howto_precommit/index.html new file mode 100644 index 0000000..01aeb36 --- /dev/null +++ b/GitHub/howto_precommit/index.html @@ -0,0 +1,39 @@ + Using Pre-Commit - CCBR How Tos
Skip to content

GitHub HowTo: Pre-Commit

Pre-commit should be added to all GitHub repositories on Biowulf and any clones created elsewhere to ensure cohesive and informative commit messages. After the creating the repository the following commands should be run in order to initialize the pre-commit hook, and establish the following requirements for all commit messages:

Using Precommit

Pre-commit has been installed as a module on Biowulf. Set up an interactive session, and follow the steps below. A pre-commit configuration file is needed, and can be copied from the CCBR template repo.

# load module on biowulf
+module load precommit
+
+# CD into the GitHub repo
+cd <repo_name>
+
+# install precommit in the repo - this is the only time you need to do this, per local repo location
+pre-commit install
+
+# copy and update the precommit config
+touch .pre-commit.config
+

Structure of Commit Messages

Commits must follow the format listed below, as designated by Angular:

<type>(<scope>): <subject>
+<body>
+<BLANK LINE>
+<footer>
+

Type (REQUIRED)

The type must be one of the following options:

  • build: Changes that affect the build system or external dependencies
  • ci: Changes to our CI configuration files and scripts
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • test: Adding missing tests or correcting existing tests

Scope (OPTIONAL)

The scope must be one of the following options:

  • animations
  • common
  • compiler
  • compiler-cli
  • core
  • elements
  • forms
  • http
  • language-service
  • platform-browser
  • platform-browser-dynamic
  • platform-server
  • platform-webworker
  • platform-webworker-dynamic
  • router
  • service-worker
  • upgrade

Subject (REQUIRED)

The subject must be a succinct description of the change. It should follow the following rules:

  • use the imperative, present tense: "change" not "changed" nor "changes"
  • don't capitalize the first letter
  • no dot (.) at the end

Body (OPTIONAL)

The body should include the motivation for the change and contrast this with previous behavior. It should follow the following rule:

  • use the imperative, present tense: "change" not "changed" nor "changes"

The footer should contain any information about Breaking Changes and is also the place to reference GitHub issues that this commit Closes.

  • Breaking Changes should start with the word BREAKING CHANGE: with a space or two newlines. The rest of the commit message is then used for this.
  • Closed bugs should be listed on a separate line in the footer from Breaking Changes, prefixed with "Closes" keyword (Closes #234 or Closes #123, #245, #992).

Examples

Below are some examples of properly formatted commit messages

# example
+docs(changelog): update changelog to beta.5
+
+# example
+fix(release): need to depend on latest rxjs and zone.js
+
+# example
+feat($browser): onUrlChange event (popstate/hashchange/polling)
+Added new event to $browser:
+- forward popstate event if available
+- forward hashchange event if popstate not available
+- do polling when neither popstate nor hashchange available
+
+Breaks $browser.onHashChange, which was removed (use onUrlChange instead)
+
+# example
+fix($compile): couple of unit tests for IE9
+Older IEs serialize html uppercased, but IE9 does not...
+Would be better to expect case insensitive, unfortunately jasmine does
+not allow to user regexps for throw expectations.
+
+Closes #392
+Breaks foo.bar api, foo.baz should be used instead
+


Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/howto_setup/index.html b/GitHub/howto_setup/index.html new file mode 100644 index 0000000..defc2c8 --- /dev/null +++ b/GitHub/howto_setup/index.html @@ -0,0 +1,5 @@ + Preparing your environment - CCBR How Tos
Skip to content

GitHub Setup: Preparing the Environment

Using GitHub CLI

The gh is installed on Biowulf at /data/CCBR_Pipeliner/db/PipeDB/bin/gh_1.7.0_linux_amd64/bin/gh. You can run the following lines to edit your ~/.bashrc file to add gh to your $PATH:

echo "export PATH=$PATH:/data/CCBR_Pipeliner/db/PipeDB/bin/gh_1.7.0_linux_amd64/bin" >> ~/.bashrc
+source ~/.bashrc
+

Alternatively, you can use the git commands provided through a Biowulf module

module load git
+

Creating PAT for GH

Personal Access Token (PAT) is required to access GitHub (GH) without having to authenticate by other means (like password) every single time. You will need gh cli installed on your laptop or use /data/CCBR_Pipeliner/db/PipeDB/bin/gh_1.7.0_linux_amd64/bin/gh on Biowulf, as described above. You can create a PAT by going here. Then you can copy the PAT and save it into a file on Biowulf (say ~/gh_token). Next, you can run the following command to set everything up correctly on Biowulf (or your laptop)

gh auth login --with-token < ~/git_token
+

Password-less Login

If you hate to re-enter (username and) password every time you push/pull to/from github (or mkdocs gh-deploy), then it is totally worthwhile to spend a couple minutes to set up SSH keys for auto-authentication. The instructions to do this are available here.


Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/overview/index.html b/GitHub/overview/index.html new file mode 100644 index 0000000..e657af5 --- /dev/null +++ b/GitHub/overview/index.html @@ -0,0 +1 @@ + Overview - CCBR How Tos
Skip to content

Overview of GitHub Topics

Getting set-up and familiar with GitHub

  1. Preparing your environment:
    • Describes how to create a PAT, add GH to your bash profile and use password-less login features
  2. Basic Commands:
    • Describes basic functions to be used with this SOP

Basics

  1. Creating your GitHub repo:
    • Provides information on how to setup a GitHub repository under CCBR and the use of templates
  2. Creating your Documentation:
    • Provides information on how to setup documentation under your repository; provided with all template repos
  3. GitHub Actions:
    • Provides information for using GitHub Actions under your repository; provided with all template repos

Best Practices

  1. CCBR Projects, new Pipelines
  2. TechDev

Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/sop_projpipes/index.html b/GitHub/sop_projpipes/index.html new file mode 100644 index 0000000..24367ef --- /dev/null +++ b/GitHub/sop_projpipes/index.html @@ -0,0 +1,2 @@ + Projects,Pipelines - CCBR How Tos
Skip to content

GitHub Best Practices: Projects and Pipelines

Pipeline Documentation

  • All pipelines should provide users with documentation for usage, test data, expected outputs, and troubleshooting information. Mkdocs is the recommended tool to perform this action, however, other tools may be utilized. The template's (NextFlow, Snakemake) were written for mkdocs, and provide basic yaml markdown files provided for this use. They should be edited according to the pipelines function and user needs. Examples of the requirements for each page are provided in the templates.

    1. Background
      • Information on who the pipeline was developed for, and a statement if it's only been tested on Biowulf.
      • Also include a workflow image to summarize the pipeline.
    2. Getting Started
      • This should set the stage for all of the pipeline requirements. This should include the following pages:
        • Introduction
        • Setup Dependencies
        • Login to the cluster
        • Load an interactive session
    3. Preparing Files
      • This should include the following pages:
        • Configs
          • Cluster Config
          • Tools Config
          • Config YAML
            • User Parameters
            • References
        • Preparing Manifests
          • Samples Manifest
    4. Running the Pipeline
      • This should include all information about the various run commands provided within the pipeline. This should include the following pages:
        • Pipeline Overview
        • Commands explained
        • Typical Workflow
    5. Expected Output
      • This should include all pertinent information about output files, including extensions that differentiate files.
    6. Running Test Data
      • This should walk the user through the steps of running the pipeline using test data. This should include the following pages:
        • Getting Started
        • About the test data
        • Submit the test data
        • Review outputs

Repository Management

Security settings

  • Two members of CCBR (creator and one manager) should be granted full administrative privileges to the repository to ensure the source code can be accessed by other members, as needed
  • Both the develop and master branch must be protected (IE have to have a PR to be changed)

CCBR Branch Strategy

Branch Naming

Branch Overview

  • All repositories should include a minimum of two branches at any time:
    • main (master)
    • dev
  • Additional branches should be created as needed. These would include feature branches, developed using individual, feature specific addition and hotfix branches, developed using individual, bug specific fixes.
  • Utilization of these branches should follow the documentation below.

Strategy Outline

  • We encourage the use of the Git Flow tools for some actions, available on Biowulf (module load gitflow). Our current branching strategy is based off of the Git Flow strategy shown below :

ref:https://nvie.com/posts/a-successful-git-branching-model/

  1. Master (named main or master)
    • branch that contains the current release / tagged version of the pipeline
    • merges from Dev branch or hotfix branch allowed
    • merges require actions_master_branch pass from GitHub actions. See GitHub actions #4 for more information testing requirements for merge
  2. Develop (named dev or activeDev)
    • branch that contains current dev
    • merges from feature branch allowed
    • merges require actions_dev_branch pass from GitHub actions. See GitHub actions #3 for more information testing requirements for merge
  3. Feature (named feature/unique_feature_name)
    • branch to develop new features that branches off the develop branch
    • recommended usages of git flow feature start unique_feature_name followed by git flow feature publish unique_feature_name
    • no merges into this branch are expected
  4. Hotfix (named unique_hotfix_name)
    • branches arise from a bug that has been discovered and must be resolved; it enables developers to keep working on their own changes on the develop branch while the bug is being fixed
    • recommended usage of git flow hotfix start unique_hotfix_name
    • no merges into this branch are expected

NOTE: While the git flow feature start command is recommended for feature branch merging, the git flow feature finish is not. Using the finish command will automatically merge the feature branch into the dev branch, without any testing, and regardless of divergence that may have occured during feature development.

General Workflow (Steps)

  1. Assuming that you have already cloned the repo and initiated git flow with git flow init
  2. Create a new feature and publish it git flow feature start unique_feature_name and then git flow feature publish unique_feature_name. The unique_feature_name will be created from the develop branch.
  3. Code normally, make frequent commits, push frequently to remote. These commits are added to the unique_feature_name branch.
  4. When you are ready to add your feature enhancements back to the develop branch, you may have to make sure that the develop branch has not marched forward while you were working on the unique_feature_name feature (This is possible as other may have added their PRs in the interim). If it has, then you may have to pull in changes made to develop branch into your unique_feature_name feature branch. This can be achieved using the GitHub web interface... merge developunique_feature_name. Resolve conflicts if any.
  5. Retest your unique_feature_name branch.
  6. Now send in a pull request using the GitHub web interface to pull your unique_feature_name into develop branch.
  7. Occasionally, we may create a new release branch from the develop branch and perform thorough E2E testing with fixes. Once, everything is working as expected, we pull the release branch back into develop and also push it to main with a version tag.

Release, Tagged Nomenclature

  • The following format of versioning should be followed:

    v.X.Y.Z
    +
  • The following rules should be applies when determining the version release:

    • X is major; non-backward compatible (dependent on the amount of changes; from dev)
    • Y is minor; backwards compatible (dependent on the amount of changes; from dev)
    • Z is patches; backwards compatible (bugs; hot fixes)
  • Other notes:

    • X,Y,Z must be numeric only
    • All updates to the main (master) branch must be tagged and versioned using the parameters above
    • Updates to the dev branch can be tagged, but should not be versioned
    • If the pipeline is available locally (IE on Biowulf), version changes should be added for use

Pipelines Test Data

The following information is meant to outline test_data requirements for all pipelines, however, should be altered to fit the needs of the specific pipeline or project developed.

Requirements

  1. Location of data
    • Test data sets should be stored within a .test directory, as found in all templates.
  2. Documentation
    • Review information on the documentation page, which will provide basic information on test data used within the project/pipeline.
    • A README file should be created under the .test directory, to include the following information:
      • Date of implementation
      • Information on species (IE Homo Sapiens) and data type (IE RNA-Seq)
      • Information on the references to be used (IE hg38)
      • Metadata manifests required by the pipeline
      • The source of the files
      • Link to scripts used in created the partial test data
  3. Choosing a test data set
    • At a minimum three test sets should be available:

      1) Should include sub-sampled inputs, to test the pipelines functionality, and to be used as the tutorial test set. 2) Should include full-sample inputs, of high quality, to test the robustness of the pipelines resources 3) Should include full-sample inputs, of expected project-level quality, to test the robustness of the pipelines error handling - Test data should come from a CCBR project or a a publicly available source. Care should be taken when choosing test data sets, to ensure that the robustness of the pipeline will be tested, as well as the ability of the pipeline to handle both high and low quality data. Multiple test sets may need to be created to meet these goals.


Last update: 2024-01-08
\ No newline at end of file diff --git a/GitHub/sop_techdev/index.html b/GitHub/sop_techdev/index.html new file mode 100644 index 0000000..624a2a8 --- /dev/null +++ b/GitHub/sop_techdev/index.html @@ -0,0 +1 @@ + Best Practices - CCBR How Tos
Skip to content

GitHub Best Practices

TechDev Documentation

  • All pipelines should provide users with:

    • documentation for usage
    • test data
    • expected outputs and reports
    • troubleshooting information

    Markdown pages can be hosted directly within the repo using GH Pages. Mkdocs is the recommended tool to perform this action, however, other tools may be utilized. The templates (TechDev) template's (written for mkdocs) provided have basic yaml markdown files provided for this use, and should be edited according to the pipelines function and user needs. Also, track blockers/hurdles using GitHub Issues.

    1. Overview
      • Information on the goal of the TechDev project.
    2. Analysis
      2.1. Background

      • Provide any relaxant background to the project to be completed. This might include information on: - problem that was encountered leadings to this techdev - new feature or tool developed to be benchmarked - relevant biological or statistical information needed to perform this analysis

      2.2. Resources - This page should include any relevant tools that were used for testing. If these tools were loaded via Biowulf, include all version numbers. If they were installed locally, provide information on installation, source location, and any reference documents used.

      2.3. Test Data - This will include information on the test data included within the project. Species information, source information, and references should be included. Any manipulation performed on the source samples should also be included. Manifest information should also be outlined. Provide location to toy dataset or real dataset or both. It is best to park these datasets at a commonly accessible location on Biowulf and share that location here. Also, make the location read-only to prevent accidental edits by other users.

      2.4. Analysis Plan - Provide a summary of the plan of action. - If benchmarking tools, include the dataset used, where the source material was obtained, and all relevant metadata. - Include the location of any relevant config / data files used in this analysis - Provide information on the limits of the analysis - IE this was only tested on Biowulf, this was only performed in human samples, etc.

      2.5. Results - What were the findings of this TechDev exercise? Include links to where intermediate files may be located. Include tables, plots, etc. This will serve as a permanent record of the TechDev efforts to be shared within the team and beyond.

      2.6 Conclusions - Provide brief, concise conclusion drawn from the analysis, including any alterations being made to pipelines or analysis.

    3. Contributions

      • Provide any names that contributed to this work.

TechDev Repository Management

Security settings

  • Two members of CCBR (creator and one manager) should be granted full administrative privileges to the repository to ensure the source code can be accessed by other members, as needed
  • Both the develop and master branch must be protected (IE have to have a PR to be changed)

CCBR Branch Strategy

Branch Naming

Branch Overview

  • All repositories should include a minimum of two branches at any time:
    • main (master)
    • dev
  • Utilization of these branches should follow the documentation below.

Branch Strategy

  • We encourage the use of the Git Flow tools for some actions, available on Biowulf. Our current branching strategy is based off of the Git Flow strategy shown below :

    Image title

  • Master (named main or master)

    • branch that contains the current release / tagged version of the pipeline
    • merges from Dev branch or hotfix branch allowed
    • merges require actions_master_branch pass from GitHub actions. See GitHub actions #4 for more information testing requirements for merge
  • Develop (named dev or activeDev)
    • branch that contains current dev
    • merges from feature branch allowed
    • merges require actions_dev_branch pass from GitHub actions. See GitHub actions #3 for more information testing requirements for merge

TechDev Test Data

Requirements

  1. Location of data
    • Test data sets should be stored within a .test directory, as found in all templates.
  2. Documentation
    • Review information on the documentation page, which will provide basic information on test data used within the project/pipeline.
    • A README file should be created under the .test directory, to include the following information:
      • Date of implementation
      • Information on species (IE Homo Sapiens) and data type (IE RNA-Seq)
      • Information on the references to be used (IE hg38)
      • Metadata manifests required by the pipeline
      • The source of the files
      • Link to scripts used in created the partial test data
  3. Choosing a test data set
    • Test data should come from a CCBR project or a a publicly available source. Care should be taken when choosing test data sets, to ensure that the data matches the goals of the techdev effort.

Last update: 2024-01-08
\ No newline at end of file diff --git a/HPCDME/setup/index.html b/HPCDME/setup/index.html new file mode 100644 index 0000000..d17e330 --- /dev/null +++ b/HPCDME/setup/index.html @@ -0,0 +1,81 @@ + Setup - CCBR How Tos
Skip to content

Setup

Background

HPC_DME_APIs provides command line utilities or CLUs to interface with HPCDME. This document describes some of the initial setup steps to get the CLUs working on Biowulf.

Setup steps:

Clone repo:

The repo can be cloned at a location accessible to you:

cd /data/$USER/
+git clone https://github.com/CBIIT/HPC_DME_APIs.git
+

Create dirs, log files needed for HPCMDE

mkdir -p /data/$USER/HPCDMELOG/tmp
+touch /data/$USER/HPCDMELOG/tmp/hpc-cli.log
+

Copy properties template

hpcdme.properties is the file that all CLUs look into for various parameters like authentication password, file size limits, number of CPUs, etc. Make a copy of the template provided and prepare it for customization.

cd /data/$USER/HPC_DME_APIs/utils
+cp hpcdme.properties-sample hpcdme.properties
+

Customize properties file

Some of the parameters in this file have become obsolete over the course of time and are commmented out. Change paths and default values, as needed

#HPC DME Server URL
+#Production server settings
+hpc.server.url=https://hpcdmeapi.nci.nih.gov:8080
+hpc.ssl.keystore.path=hpc-client/keystore/keystore-prod.jks
+#hpc.ssl.keystore.password=hpcdmncif
+hpc.ssl.keystore.password=changeit
+
+#UAT server settings
+#hpc.server.url=https://fr-s-hpcdm-uat-p.ncifcrf.gov:7738/hpc-server
+#hpc.ssl.keystore.path=hpc-client/keystore/keystore-uat.jks
+#hpc.ssl.keystore.password=hpc-server-store-pwd
+
+#Proxy Settings
+hpc.server.proxy.url=10.1.200.240
+hpc.server.proxy.port=3128
+
+hpc.user=$USER
+
+#Globus settings
+#default globus endpoint to be used in registration and download
+hpc.globus.user=$USER
+hpc.default.globus.endpoint=ea6c8fd6-4810-11e8-8ee3-0a6d4e044368
+
+#Log files directory
+hpc.error-log.dir=/data/$USER/HPCDMELOG/tmp
+
+###HPC CLI Logging START####
+#ERROR, WARN, INFO, DEBUG
+hpc.log.level=ERROR
+hpc.log.file=/data/$USER/HPCDMELOG/tmp/hpc-cli.log
+###HPC CLI Logging END####
+
+#############################################################################
+# Please use caution changing following properties. They don't change usually
+#############################################################################
+#hpc.collection.service=collection
+#hpc.dataobject.service=dataObject
+#Log files directory
+#hpc.error-log.dir=.
+
+#Number of thread to run data file import from a CSV file
+hpc.job.thread.count=1
+
+upload.buffer.size=10000000
+
+#Retry count and backoff period for registerFromFilePath (Fixed backoff)
+hpc.retry.max.attempts=3
+#hpc.retry.backoff.period=5000
+
+#Multi-part upload thread pool, threshold and part size configuration
+#hpc.multipart.threadpoolsize=10
+#hpc.multipart.threshold=1074790400
+#hpc.multipart.chunksize=1073741824
+
+#globus.nexus.url=nexus.api.globusonline.org
+#globus.url=www.globusonline.org
+
+#HPC DME Login token file location
+hpc.login.token=tokens/hpcdme-auth.txt
+
+#Globus Login token file location
+#hpc.globus.login.token=tokens/globus-auth.txt
+#validate.md5.checksum=false
+
+# JAR version
+#hpc.jar.version=hpc-cli-1.4.0.jar
+

NOTE: The current java version used is: bash java -version openjdk version "1.8.0_181" OpenJDK Runtime Environment (build 1.8.0_181-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

Edit ~/.bashrc

Add the CLUs to PATH by adding the following to ~/.bashrc file

# export environment variable HPC_DM_UTILS pointing to directory where 
+# HPC DME client utilities are, then source functions script in there 
+export HPC_DM_UTILS=/data/$USER/HPC_DME_APIs/utils
+source $HPC_DM_UTILS/functions
+

Next, source it

source ~/.bashrc
+

Generate token

Now, you are all set to generate a token. This prevents from re-entering your password everytime.

dm_generate_token
+

If the token generation takes longer than 45 seconds, check the connection:

ping hpcdmeapi.nci.nih.gov
+

If the connection responds, try to export the following proxy, and then re-run the dm_generate_tokens command:

export https_proxy=http://dtn01-e0:3128
+

Done! You are now all set to use CLUs.


Last update: 2024-01-08
\ No newline at end of file diff --git a/HPCDME/transfer/index.html b/HPCDME/transfer/index.html new file mode 100644 index 0000000..ab6cb28 --- /dev/null +++ b/HPCDME/transfer/index.html @@ -0,0 +1,93 @@ + Biowulf2HPCDME - CCBR How Tos
Skip to content

Biowulf2HPCDME

Background

Rawdata or Project folders from Biowulf can be parked at a secure location after the analysis has reached a endpoint. Traditionally, CCBR analysts had access to the GridFTP Globus Archive for doing this. But, this Globus Archive has been running past 95% full lately.

This document outlines how a projects folder can be directly parked on HPCDME as a single "tar.gz" ball. It is assumed that HPC DME API CLUs are already setup as per these instructions.

Here are the steps:

Create tarball

Once you have a list of files that you want to include in the tarball, create the tarball. This may take a while and should be submitted as a slurm job.

% cd /data/CCBR/projects
+% du -hs /data/CCBR/projects/ccbr796
+440G    /data/CCBR/projects/ccbr796
+% echo "tar czvf ccbr796.tar.gz /data/CCBR/projects/ccbr796" > do_tar_gz
+% swarm -f do_tar_gz --partition=ccr,norm --time=24:00:00 -t 2 -g 100
+41985209
+

Create filelist

Sometime you just want to know what files are in the tarball. Hence, it is important to upload a filelist along with the tarball.

% tar tzvf ccbr796.tar.gz > ccbr796.tar.gz.filelist
+

Create Project

If the Project collection does not exist in HPCDME (verify using the web interface), then you may need to create it.

% cd /data/kopardevn/SandBox/parkit
+% bash create_empty_project_collection.sh /CCBR_Archive/GRIDFTP/Project_CCBR-796 CCBR-796 CCBR-796
+{
+    "metadataEntries": [
+        {
+         "attribute": "collection_type",
+         "value": "Project"
+        },
+        {
+         "attribute": "project_start_date",
+         "value": "20220616",
+         "dateFormat": "yyyyMMdd"
+        },
+        {
+         "attribute": "access",
+         "value": "Open Access"
+        },
+        {
+         "attribute": "method",
+         "value": "NGS"
+        },
+        {
+         "attribute": "origin",
+         "value": "CCBR"
+        },
+        {
+         "attribute": "project_affiliation",
+         "value": "CCBR"
+        },
+        {
+         "attribute": "project_description",
+         "value": "CCBR-796"
+        },
+        {
+         "attribute": "project_status",
+         "value": "Completed"
+        },
+        {
+         "attribute": "retention_years",
+         "value": "7"
+        },
+        {
+         "attribute": "project_title",
+         "value": "CCBR-796"
+        },
+        {
+         "attribute": "summary_of_samples",
+         "value": "Unknown"
+        },
+        {
+         "attribute": "organism",
+         "value": "Unknown"
+        }
+    ]
+}
+dm_register_collection /dev/shm/Project_CCBR-796.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796
+

Error: Have encountered this error message:

Error during registration, HTTP_CODE: 503
+Cannot find the response message file
+collection-registration-response-message.json.tmp
+
503 error means that the API is down!

Create Analysis

If the Analysis collection does not exist in HPCDME (verify using the web interface) under the Project collection, then you may need to create it.

% cd /data/kopardevn/SandBox/parkit
+% bash create_empty_analysis_collection.sh /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis
+dm_register_collection /dev/shm/Analysis.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis
+

Done! Now you have a location ready for the the tarball to be parked.

Create metadata

Using meta script from pyrkit, we can then generate the required .metadata.json file for the tarball. Analysis collection /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis should already exist in the HPCDME vault.

% echo "/data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis" > do_get_metadata
+% swarm -f do_get_metadata --partition=ccr,norm --time=24:00:00 -t 2 -g 100
+

If the file is large (100s of GB), then this may take a while as the md5sum of the file is being calculated. Hence, this should be submitted to the slurm.

Metadata also needs to be created for the filelist file. These files are generally small (few MBs) and the following command can be directly run on an interactive node.

% /data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz.filelist --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis
+

The above command, when run sucessfully, will create /data/CCBR/projects/ccbr796.tar.gz.filelist.metadata.json

Transfer

dm_register_dataobject cannot be used for large files (>10GB), but it can be replaced by dm_register_dataobject_multipart

% dm_register_dataobject_multipart /data/CCBR/projects/ccbr796.tar.gz.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz /data/CCBR/projects/ccbr796.tar.gz
+Reading properties from /data/kopardevn/SandBox/HPC_DME_APIs/utils/hpcdme.properties
+Registering file: /data/CCBR/projects/ccbr796.tar.gz
+Destination archive path: /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz
+Cmd process Completed
+Jun 16, 2022 10:55:25 AM org.springframework.shell.core.AbstractShell handleExecutionResult
+INFO: CLI_SUCCESS
+

Depending on the size of the file, this step can be done in a reasonable amount of time (<1hr) and can be run in an interactive node.

Remember, the filelist file also needs to be registered separately like this:

% dm_register_dataobject /data/CCBR/projects/ccbr796.tar.gz.filelist.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz.filelist /data/CCBR/projects/ccbr796.tar.gz.filelist
+

As filelist files are smaller (few MBs), we can run dm_register_dataobject in place of dm_register_dataobject_multipart.

Cleanup

Once the tarball is successfully transferred over the HPCDME, it can be deleted from the local filesystem.

% rm -f /data/CCBR/projects/ccbr796.tar.gz
+

The contents of the local analysis folder can also be deleted.

% cd /data/CCBR/projects/ccbr796 && rm -rf *
+

A note can be added to the recently emptied folder stating where the contents are currently parked.

% cd /data/CCBR/projects/ccbr796
+% echo "This folder was converted to a tarball (tar.gz) and pushed to HPCDME. Its new location is \`/CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz\` in HPCDME" > README.md
+

Done!

NOTE FOR LARGE FILES: It is recommended by HPCDME staff that files to be transferred should not be too large (1TB or smaller). Hence, if the file to be transferred is larger than 1TB, it should be split into 1TB-size chunks and upload those. Splitting can be done like this:

split -b 1T ccbr796.tar.gz "ccbr796.tar.gz.part_"
+
Metadata needs to be individidually created for each of the parts, namely, ccbr796.tar.gz.part_aa, ccbr796.tar.gz.part_ab, etc
% /data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz.part_aa --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis
+% /data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz.part_ab --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis
+...
+
Next each 1TB part can be registered like so:
% dm_register_dataobject_multipart /data/CCBR/projects/ccbr796.tar.gz.part_aa.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz.part_aa /data/CCBR/projects/ccbr796.tar.gz.part_aa
+% dm_register_dataobject_multipart /data/CCBR/projects/ccbr796.tar.gz.part_ab.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz.part_ab /data/CCBR/projects/ccbr796.tar.gz.part_ab
+...
+
Once these files are downloaded then can be joined together using the cat command before ungzipping/untaring.
% cat ccbr796.tar.gz.part_* > ccbr796.tar.gz
+


Last update: 2024-01-08
\ No newline at end of file diff --git a/OtherHowTos/datashare/index.html b/OtherHowTos/datashare/index.html new file mode 100644 index 0000000..b252d0b --- /dev/null +++ b/OtherHowTos/datashare/index.html @@ -0,0 +1,19 @@ + Datashare - CCBR How Tos
Skip to content

Datashare

Host data on Helix or Biowulf, that is publicly accessible through a URL

Setup


Access Login

# Helix
+ssh -Y username@helix.nih.gov
+
+# Biowulf
+ssh -Y username@biowulf.nih.gov
+

Create a new dir (tutorial) in the datashare path:

cd /data/CCBR/datashare/
+mkdir tutorial
+

Processing


Make a directory in the datashare folder

NOTE: For all steps below, an example is shown for Helix, but the same process is applicable for Biowulf, after changing the helix.nih.gov to biowulf.nih.gov

Now you can transfer your data to the new directory. One method is to use scp to copy data from your local machine to Helix.

Here is an example of using scp to copy the file file.txt from a local directory to Helix.

scp /data/$USER/file.txt username@helix.nih.gov:/data/CCBR/datashare/tutorial/
+

To copy multiple directories recursively, you can also include the -r command with scp and from the top level directory:

scp -r /data/$USER/ username@helix.nih.gov:/data/CCBR/datashare/tutorial/
+

Create public permissions for data

When the data has been successully copied, we need to open the permissions.

NOTE: This will give open access to anyone with the link. Ensure this is appropriate for the data type

# cd to the shared dir
+cd /data/CCBR/datashare/
+
+# run CHMOD, twice
+chmod -R 777 tutorial
+chmod -R 777 tutorial/*
+
+# run SETFACL
+setfacl -m u:webcpu:r-x tutorial/*
+

Public Access


NOTE: You must be logged into HPC in order to access these files from a web browser.

Files will be available for access through a browser, via tools like wget and UCSC genome track browser via the following format:

http://hpc.nih.gov/~CCBR/tutorial/file.txt

For more information and a tutorial for creating UCSC tracks, visit the CCBR HowTo Page.


Last update: 2024-01-08
\ No newline at end of file diff --git a/OtherHowTos/zenodo/index.html b/OtherHowTos/zenodo/index.html new file mode 100644 index 0000000..d1e318e --- /dev/null +++ b/OtherHowTos/zenodo/index.html @@ -0,0 +1 @@ + Zenodo - CCBR How Tos
Skip to content

Zenodo

Submit a pipeline to Zenodo in order to create a DOI for publication.

Use the link for full information, summarized below: https://www.youtube.com/watch?v=A9FGAU9S9Ow

Prepare GitHub Repository

The GitHub repository should include the following:

  1. README page
  2. Documentation page, such as mkdocs, with usage and contact information
  3. A citation CITATION.cff; Example here
  4. Tagged and versioned, stable repository
  1. Go to Zenodo

  2. Select username in the top right >> Profile. Select `GitHub``

  3. Click Sync Now (top right) to update repos. NOTE: You may have to refresh the page

  4. Toggle the On button on the repo you wish to publish. This will move the pipeline to the Enable Repositories list.

Prepare GitHub Repo

  1. Go to GitHub and find the repository page.

  2. Select Releases >> Draft a new release

  3. Create a tag, following naming semantics described here

  4. Describe the tag with the following: "Connecting pipeline to Zenodo"

Update Zenodo Information

  1. Go to Zenodo

  2. Select My dashboard >> Edit

  3. Update the following information:

    • Resource Type: Software
    • Title: Full Pipeline Name (ShorthandName) (IE Mouse nEoanTigen pRedictOr (METRO)
    • Creators: Add creators, including ORCID's whenever possible
    • Description: A short description of the main features of the pipeline
    • Additional Description: If you use this software, please cite it as below.
    • Keywords and subjects: Add several keywords related to the pipeline
    • Version: add the version used in GitHub
    • Publisher: Zenodo
    • Related works: "Is original form of" "github website" URL

Add DOI, citation to GitHub

  1. Go to Zenodo

  2. Select username in the top right >> Profile. Select `GitHub``

  3. Click Sync Now (top right) to update repos. NOTE: You may have to refresh the page

  4. Copy the DOI for the repository

  5. Return to the GitHub repository and edit the README of the GitHub repo, adding the DOI link.

  6. Update the CITATION.cff as needed.

  7. Create a new tagged version.


Last update: 2024-01-08
\ No newline at end of file diff --git a/Rpackage/build_pkg/index.html b/Rpackage/build_pkg/index.html new file mode 100644 index 0000000..97aa598 --- /dev/null +++ b/Rpackage/build_pkg/index.html @@ -0,0 +1,118 @@ + Creating the package - CCBR How Tos
Skip to content

Creating a Conda Package from an R Package

Overview

To create a package with Conda, you first need to make a new release and tag in the github repo of the R package you would like to create into a Conda Package.

For more information on best practices in R package creation, review this documentation.

Before creating the release on github, please check for proper dependencies listed in the files NAMESPACE and DESCRIPTION.

These files should have the same list of dependencies, and the version numbers for dependencies can be specified in the DESCRIPTION file. The DESCRIPTION file must be edited manually, while the NAMESPACE file should not be edited manually, but rather created automatically using the document() function.

The DESCRIPTION file must also be correctly formatted. For more information, see the following website.

Download the R package release from Github

To download the most recent release from the most recent tag on Github, activate Conda then use Conda skeleton to pull the correct URL. In the example below, replace $githubURL with the URL to your R package's github repo.

conda activate 
+
+conda skeleton cran $githubURL
+

A folder is then created for the downloaded release. Ror example running the following:

conda skeleton cran https://github.com/NIDAP-Community/DSPWorkflow
+

Creates the folder

r-dspworkflow
+

Within this newly created folder is a file named meta.yaml. You will need to edit this file to include the channels and edit any information on the the package version number or dependency version numbers.

Here is an example of the top of the meta.yaml file with the channels section added:

{% set version = '0.9.5.2' %}
+
+{% set posix = 'm2-' if win else '' %}
+{% set native = 'm2w64-' if win else '' %}
+
+package:
+  name: r-dspworkflow
+  version: {{ version|replace("-", "_") }}
+
+channels:
+  - conda-forge
+  - bioconda
+  - default
+  - file://rstudio-files/RH/ccbr-projects/Conda_package_tutorial/local_channel/channel
+
+source:
+
+  git_url: https://github.com/NIDAP-Community/DSPWorkflow
+  git_tag: 0.9.5
+
+build:
+  merge_build_host: True  # [win]
+  # If this is a new build for the same version, increment the build number.
+  number: 0
+  # no skip
+
+  # This is required to make R link correctly on Linux.
+  rpaths:
+    - lib/R/lib/
+    - lib/
+
+    # Suggests: testthat (== 3.1.4)
+requirements:
+  build:
+    - {{ posix }}filesystem        # [win]
+    - {{ posix }}git
+    - {{ posix }}zip               # [win]
+

Here is an example of the sections for specifying dependency versions from the meta.yaml file:

  host:
+    - r-base =4.1.3=h2f963a2_5
+    - bioconductor-biobase =2.54.0=r41hc0cfd56_2
+    - bioconductor-biocgenerics =0.40.0=r41hdfd78af_0
+    - bioconductor-geomxtools =3.1.1=r41hdfd78af_0
+    - bioconductor-nanostringnctools =1.2.0
+    - bioconductor-spatialdecon =1.4.3
+    - bioconductor-complexheatmap =2.10.0=r41hdfd78af_0
+    - r-cowplot =1.1.1=r41hc72bb7e_1
+    - r-dplyr =1.0.9=r41h7525677_0
+    - r-ggforce =0.3.4=r41h7525677_0
+    - r-ggplot2 =3.3.6=r41hc72bb7e_1
+    - r-gridextra =2.3=r41hc72bb7e_1004
+    - r-gtable =0.3.0=r41hc72bb7e_3
+    - r-knitr =1.40=r41hc72bb7e_1
+    - r-patchwork =1.1.2=r41hc72bb7e_1
+    - r-reshape2 =1.4.4=r41h7525677_2
+    - r-scales =1.2.1=r41hc72bb7e_1
+    - r-tibble =3.1.8=r41h06615bd_1
+    - r-tidyr =1.2.1=r41h7525677_1
+    - r-umap =0.2.9.0=r41h7525677_1
+    - r-rtsne =0.16=r41h37cf8d7_1
+    - r-magrittr =2.0.3=r41h06615bd_1
+    - r-rlang =1.1.0=r41h38f115c_0
+
+  run:
+    - r-base =4.1.3=h2f963a2_5
+    - bioconductor-biobase =2.54.0=r41hc0cfd56_2
+    - bioconductor-biocgenerics =0.40.0=r41hdfd78af_0
+    - bioconductor-geomxtools =3.1.1=r41hdfd78af_0
+    - bioconductor-nanostringnctools =1.2.0
+    - bioconductor-spatialdecon =1.4.3
+    - bioconductor-complexheatmap =2.10.0=r41hdfd78af_0
+    - r-cowplot =1.1.1=r41hc72bb7e_1
+    - r-dplyr =1.0.9=r41h7525677_0
+    - r-ggforce =0.3.4=r41h7525677_0
+    - r-ggplot2 =3.3.6=r41hc72bb7e_1
+    - r-gridextra =2.3=r41hc72bb7e_1004
+    - r-gtable =0.3.0=r41hc72bb7e_3
+    - r-knitr =1.40=r41hc72bb7e_1
+    - r-patchwork =1.1.2=r41hc72bb7e_1
+    - r-reshape2 =1.4.4=r41h7525677_2
+    - r-scales =1.2.1=r41hc72bb7e_1
+    - r-tibble =3.1.8=r41h06615bd_1
+    - r-tidyr =1.2.1=r41h7525677_1
+    - r-umap =0.2.9.0=r41h7525677_1
+    - r-rtsne =0.16=r41h37cf8d7_1
+    - r-magrittr =2.0.3=r41h06615bd_1
+    - r-rlang =1.1.0=r41h38f115c_0
+

In the above example, each of the dependencies has been assigned a conda build string, so that when conda builds a conda package, it will only use that specific build of the dependency from the listed conda channels. The above example is very restrictive, the dependencies can also be listed in the "meta.yaml" file to be more open--it will choose a conda build string that fits in with the other resolved dependency build strings based on what is available in the channels.

Also note that the "host" section matches the "run" section.

Here is some examples of a more open setup for these dependencies:

  host:
+    - r-base >=4.1.3
+    - bioconductor-biobase >=2.54.0
+    - bioconductor-biocgenerics >=0.40.0
+    - bioconductor-geomxtools >=3.1.1
+    - bioconductor-nanostringnctools >=1.2.0
+    - bioconductor-spatialdecon =1.4.3
+    - bioconductor-complexheatmap >=2.10.0
+    - r-cowplot >=1.1.1
+    - r-dplyr >=1.0.9
+    - r-ggforce >=0.3.4
+    - r-ggplot2 >=3.3.6
+    - r-gridextra >=2.3
+    - r-gtable >=0.3.0
+    - r-knitr >=1.40
+    - r-patchwork >=1.1.2
+    - r-reshape2 >=1.4.4
+    - r-scales >=1.2.1
+    - r-tibble >=3.1.8
+    - r-tidyr >=1.2.1
+    - r-umap >=0.2.9.0
+    - r-rtsne >=0.16
+    - r-magrittr >=2.0.3
+    - r-rlang >=1.1.0
+

Build the Conda package

When the meta.yaml has been prepared, you can now build the Conda package. To do so, run the command, replacing

  • $r-package with the name of the R package folder that was created after running conda skeleton (the folder where the meta.yaml is located).
  • $build_log_name.log with the name for the log file, such as the date, time, and initials.
conda-build $r-package 2>&1|tee $build_log_name.log
+

Example

conda-build r-dspworkflow 2>&1|tee 05_12_23_330_nc.log
+

The log file will list how conda has built the package, including what dependencies version numbers and corresponding build strings were used to resolve the conda environment. These dependencies are what we specified in the "meta.yaml" file. The log file will be useful troubleshooting a failed build.

Be aware, the build can take anywhere from several minutes to an hour to complete, depending on the size of the package and the number of dependencies.

The conda package will be built as a tar.bz2 file.


Last update: 2024-01-08
\ No newline at end of file diff --git a/Rpackage/common_issues/index.html b/Rpackage/common_issues/index.html new file mode 100644 index 0000000..724975c --- /dev/null +++ b/Rpackage/common_issues/index.html @@ -0,0 +1,14 @@ + Troubleshooting - CCBR How Tos
Skip to content

Creating a Conda Package from an R Package

Package Dependency Issues

An important consideration for Conda builds is the list of dependencies, specified versions, and compatibility with each of the other dependencies.

If the meta.yaml and DESCRIPTION file specify specific package versions, Conda's ability to resolve the Conda environment also becomes more limited.

For example, if the Conda package we are building has the following requirements:

Dependency A version == 1.0
+Dependency B version >= 2.5
+

And the Dependencies located in our Conda channel have the following dependencies:

Dependency A version 1.0
+  - Dependency C version == 0.5
+
+Dependency A version 1.2
+- Dependency C version >= 0.7
+
+Dependency B version 2.7
+  - Dependency C version >= 0.7
+

As you can see, the Conda build will not be able to resolve the environment because Dependency A version 1.0 needs an old version of Dependency C, while Dependency B version 2.7 needs a newer version.

In this case, if we changed our package's DESCRIPTION and meta.yaml file to be:

Dependency A version >= 1.0
+Dependency B version >= 2.5
+

The conda build will be able to resolve. This is a simplified version of a what are more often complex dependency structures, but it is an important concept in conda package building that will inevitably arise as a package's dependencies become more specific.

To check on the versions of packages that are available in a Conda channel, use the command:

conda search $dependency
+

Replace $dependency with the name of package you would like to investigate. There are more optional commands for this function which can be found here

To check the dependencies of packages that exist in your Conda cache, go to the folder specified for your conda cache (that we specified earlier). In case you need to find that path you can use:

conda info

Here there will be a folder for each of the packages that has been used in a conda build (including the dependencies). In each folder is another folder called "info" and a file called "index.json" that lists information, such as depends for the package.

Here is an example:

``` cat /rstudio-files/ccbr-data/users/Ned/conda-cache/r-ggplot2-3.3.6-r41hc72bb7e_1/info/index.json

{ "arch": null, "build": "r41hc72bb7e_1", "build_number": 1, "depends": [ "r-base >=4.1,<4.2.0a0", "r-digest", "r-glue", "r-gtable >=0.1.1", "r-isoband", "r-mass", "r-mgcv", "r-rlang >=0.3.0", "r-scales >=0.5.0", "r-tibble", "r-withr >=2.0.0" ], "license": "GPL-2.0-only", "license_family": "GPL2", "name": "r-ggplot2", "noarch": "generic", "platform": null, "subdir": "noarch", "timestamp": 1665515494942, "version": "3.3.6" } ```

If you would like to specify an exact package to use in a conda channel for your conda build, specify the build string in your "meta.yaml" file. In the above example for ggplot version 3.3.6, the build string is listed in the folder name for package as well as in the index.json file for "build: "r41hc72bb7e_1".


Last update: 2024-01-08
\ No newline at end of file diff --git a/Rpackage/setup/index.html b/Rpackage/setup/index.html new file mode 100644 index 0000000..9b51b8f --- /dev/null +++ b/Rpackage/setup/index.html @@ -0,0 +1,19 @@ + Set-Up - CCBR How Tos
Skip to content

Creating a Conda Package from an R Package

Set up Conda Tools, installation (if needed)

  • You will first need to set up Conda in order to use the Conda tools for creating your Conda package.

  • The documentation for getting started can be found here, including installation guidelines.

Set up Conda cache

In a space shared with other users that may use Conda, your personal Conda cache needs to be specified. To edit how your cache is saved perform the following steps:

1) Create a new directory where you would like to store the conda cache called 'conda-cache'

mkdir conda/conda-cache
+

2) In your home directory, create the file .condarc

touch ~/.condarc
+

3) Open the new file .condarc and add the following sections:

  • pkgs_dirs

  • envs_dirs

  • conda-build

  • channels

In each section you will add the path to the directories you would like to use for each section.

Example:

kgs_dirs:<br>
+  - /rstudio-files/ccbr-data/users/Ned/conda-cache<br>
+envs_dirs:<br>
+  - /rstudio-files/ccbr-data/users/Ned/conda-envs<br>
+conda-build:<br>
+    root-dir: /rstudio-files/ccbr-data/users/Ned/conda-bld<br>
+    build_folder: /rstudio-files/ccbr-data/users/Ned/conda-bld
+    conda-build<br>
+  output_folder: /rstudio-files/ccbr-data/users/Ned/conda-bld/conda-output<br>
+channels:<br>
+  - file://rstudio-files/RH/ccbr-projects/Conda_package_tutorial/local_channel/channel<br>
+  - conda-forge<br>
+  - bioconda<br>
+  - defaults<br>
+

Check Conda setup

To check that conda has been setup with the specified paths from .condarc start conda:

conda activate
+

Then check the conda info:

conda info
+

Last update: 2024-01-08
\ No newline at end of file diff --git a/Tutorials/snakemake/index.html b/Tutorials/snakemake/index.html new file mode 100644 index 0000000..cf58c89 --- /dev/null +++ b/Tutorials/snakemake/index.html @@ -0,0 +1 @@ + Snakemake - CCBR How Tos
Skip to content
\ No newline at end of file diff --git a/UCSC/creating_inputs/index.html b/UCSC/creating_inputs/index.html new file mode 100644 index 0000000..6925cfb --- /dev/null +++ b/UCSC/creating_inputs/index.html @@ -0,0 +1,49 @@ + Creating Inputs - CCBR How Tos
Skip to content

Creating Inputs

Generating Inputs

In order to use the genomic broswer features, sample files must be created.

Individual sample files

For individual samples, where peak density is to be observed, bigwig formatted files must be generated. If using the CCBR pipelines these are automatically generated as outputs of the pipeline (WORKDIR/results/bigwig). In many cases, scaling or normalization of bigwig is required to visualize multiple samples in comparison with each other. See various deeptools options for details/ideas. If not using CCBR pipelines, example code is provided below for the file generation.

modue load ucsc
+
+fragments_bed="/path/to/sample1.fragments.bed"
+bw="/path/to/sample1.bigwig"
+genome_len="numeric_genome_length"
+bg="/path/to/sample1.bedgraph"
+bw="/path/to/sample2.bigwig"
+
+# if using a spike-in scale, the scaling factor should be applied
+# while not required, it is recommended for CUT&RUN experiements
+spikein_scale="spike_in_value"
+
+# create bed file
+bedtools genomecov -bg -scale $spikein_scale -i $fragments_bed -g $genome_len > $bg
+
+# create bigwig file
+bedGraphToBigWig $bg $genome_len $bw
+

Contrasts between samples

For contrasts, where peak differences are to be observed, bigbed formatted files must be generated. If using the CCBR/CARLISLE pipeline these are automatically generated as outputs of the pipeline (WORKDIR/results/peaks/contrasts/contrast_id/). If not using this pipeline, example code is provided below for the file generation.

module load ucsc
+
+bed="/path/to/sample1_vs_sample2_fragmentsbased_diffresults.bed"
+bigbed="/path/to/output/sample1_vs_sample2_fragmentsbased_diffresults.bigbed"
+genome_len="numeric_genome_length"
+
+# create bigbed file
+bedToBigBed -type=bed9 $bed $genome_len $bigbed
+

Sharing data

For all sample types, data must be stored on a shared directory. It is recommended that symlnks be created from the source location to this shared directory to ensure that minial disc space is being used. Example code for creating symlinks is provided below.

single sample

# single sample
+## set source file location
+source_loc="/WORKDIR/results/bigwig/sample1.bigwig "
+
+## set destination link location
+link_loc="/SHAREDDIR/bigwig/sample1.bigwig"
+
+## create hard links
+ln $source_loc $link_loc
+

contrast sample

# contrast
+## set source file location
+source_loc="WORKDIR/results/peaks/contrasts/sample1_vs_sample2/sample1_vs_sample2_fragmentsbased_diffresults.bigbed "
+
+## set destination link location
+link_loc="/SHAREDDIR/bigbed/sample1_vs_sample2.bigbed"
+
+## create hard links
+ln $source_loc $link_loc
+

Once the links have been generated, the data folder must be open to read and write access.

## set destination link location
+link_loc="/SHAREDDIR/bigbed/"
+
+# open dir
+chmod -R a+rX $link_loc
+


Last update: 2024-01-08
\ No newline at end of file diff --git a/UCSC/creating_track_info/index.html b/UCSC/creating_track_info/index.html new file mode 100644 index 0000000..a63acda --- /dev/null +++ b/UCSC/creating_track_info/index.html @@ -0,0 +1,77 @@ + Creating Tracks Info - CCBR How Tos
Skip to content

Generating Track information

Single samples

It's recommended to create a text file of all sample track information to ease in editing and submission to the UCSC browser website. A single line of code is needed for each sample which will provide the track location, sample name, description of the sample, whether to autoscale the samples, max height of the samples, view limits, and color. An example is provided below.

track type=bigWig bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigwig/${complete_sample_id}.bigwig name=${sample_id} description=${sample_id} visibility=full autoScale=off maxHeightPixels=128:30:1 viewLimits=1:120 color=65,105,225
+

Users may find it helpful to create a single script which would create this text file for all samples. An example of this is listed below, which assumes that input files were generated using the CARLISLE pipeline. It can be edited to adapt to other output files, as needed.

Generally, each "track" line should have at least the following key value pairs: - name : label for the track - description : defines the center lable displayed - type : BAM, BED, bigBed, bigWig, etc. - bigDataUrl : URL of the data file - for other options see here

Inputs

  • samples_list.txt: a single column text file with sampleID's
  • track_dir: path to the linked files
  • track_output: path to output file
  • peak_list: all peak types to be included
  • method_list: what method to be included
  • dedupe_list: type of duplication to be included
# input arguments
+sample_list_input=/"path/to/samples.txt"
+track_dir="/path/to/shared/dir/"
+track_output="/path/to/output/file/tracks.txt
+peak_list=("norm.relaxed.bed" "narrowPeak" "broadGo_peaks.bed" "narrowGo_peaks.bed")
+method_list=("fragmentsbased")
+dedup_list=("dedup")
+
+# read sample file
+IFS=$'\n' read -d '' -r -a sample_list < $sample_list_input
+
+run_sample_tracks (){
+    sample_id=$1
+    dedup_id=$2
+
+    # sample name
+    # eg siNC_H3K27Ac_1.dedup.bigwig
+    complete_sample_id="${sample_id}.${dedup_id}"
+
+    # set link location
+    link_loc="${track_dir}/bigwig/${complete_sample_id}.bigwig"
+
+    # echo track info
+    echo "track type=bigWig bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigwig/${complete_sample_id}.bigwig name=${sample_id} description=${sample_id} visibility=full autoScale=off maxHeightPixels=128:30:1 viewLimits=1:120 color=65,105,225" >> $track_output
+}
+
+# iterate through samples
+# at the sample level only DEDUP matters
+for sample_id in ${sample_list[@]}; do
+    for dedup_id in ${dedup_list[@]}; do
+        run_sample_tracks $sample_id $dedup_id
+    done
+done
+

Contrast samples

It's recommended to create a text file of all sample track information to ease in editing and submission to the UCSC browser website. A single line of code is needed for each contrast which will provide the track location, contrast name, file type, and whether to color the sample. An example is provided below.

track name=${sample_id}_${peak_type} bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigbed/${complete_sample_id}_fragmentsbased_diffresults.bigbed type=bigBed itemRgb=On
+

Users may find it helpful to create a single script which would create this text file for all contrasts. An example of this is listed below, which assumes that input files were generated using the CARLISLE pipeline. It can be edited to adapt to other output files, as needed.

Inputs

  • samples_list.txt: a single column text file with sampleID's
  • track_dir: path to the linked files
  • track_output: path to output file
  • peak_list: all peak types to be included
  • method_list: what method to be included
  • dedupe_list: type of duplication to be included
# input arguments
+sample_list_input=/"path/to/samples.txt"
+track_dir="/path/to/shared/dir/"
+track_output="/path/to/output/file/tracks.txt
+peak_list=("norm.relaxed.bed" "narrowPeak" "broadGo_peaks.bed" "narrowGo_peaks.bed")
+method_list=("fragmentsbased")
+dedup_list=("dedup")
+
+# read sample file
+IFS=$'\n' read -d '' -r -a deg_list < $deg_list_input
+
+run_comparison_tracks (){
+    peak_type=$1
+    method_type=$2
+    dedup_type=$3
+    sample_id=$4
+
+    # sample name
+    # eg siSmyd3_2m_Smyd3_0.25HCHO_500K_vs_siNC_2m_Smyd3_0.25HCHO_500K__no_dedup__norm.relaxed
+    complete_sample_id="${sample_id}__${dedup_type}__${peak_type}"
+
+    # set link location
+    link_loc="${track_dir}/bigbed/${complete_sample_id}_${method_type}_diffresults.bigbed"
+
+    # echo track info
+    echo "track name=${sample_id}_${peak_type} bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigbed/${complete_sample_id}_fragmentsbased_diffresults.bigbed type=bigBed itemRgb=On" >> $track_info
+}
+
+# iterate through samples / peaks / methods / dedup
+for sample_id in ${deg_list[@]}; do
+    for peak_id in ${peak_list[@]}; do
+        for method_id in ${method_list[@]}; do
+            for dedup_id in ${dedup_list[@]}; do
+                run_comparison_tracks $peak_id $method_id $dedup_id $sample_id
+            done
+        done
+    done
+done
+

Other tips

Users can also change the colors of the tracks using standard HTML color features. Common colors used are provided below:

Red=205,92,92
+Blue=65,105,225
+Black=0,0,0
+


Last update: 2024-01-08
\ No newline at end of file diff --git a/UCSC/creating_tracks/index.html b/UCSC/creating_tracks/index.html new file mode 100644 index 0000000..646f6c4 --- /dev/null +++ b/UCSC/creating_tracks/index.html @@ -0,0 +1 @@ + Creating Tracks - CCBR How Tos
Skip to content

Biowulf/Helix hosts its own instance of the UCSC Genome Browser which is behind the NIH firewall.

Generating New Tracks

  1. Login to VPN
  2. Login to the UCSC Browser website
  3. Select "My Data > Custom Tracks"
  4. Select "Add Custom Tracks"
  5. Paste the track data generated in Creating Track Info into the text box
  6. Select "Submit"
  7. Review the track information. The column "Error" should be empty. If there is an error then a hyperlink will display "Show" although this often does not contain helpful error information.
  8. After troubleshooting any errors select "Go"
  9. Use the features at the bottom of the page to alter views and/or add additional track information
  10. Select "My Data > My Sessions"
  11. Under "Save current settings as named session:" enter a descriptive name of the session
  12. Select "Submit"
  13. This will move the descriptive name entered into the "session name" list
  14. Select the descriptve name, view your track information as saved
  15. Copy the hyperlink for this session and share as needed

Editing a Previous Tracks

  1. Login to VPN
  2. Login to the UCSC Browser website
  3. Select "My Data > My Sessions"
  4. Select the descriptve name of the session you'd like to edit
  5. Edit the tracks as needed:
    • If wanting to remove or add tracks, then select "My Data > Custom Tracks"; follow steps 5-8 above.
    • If wanting to edit the view of the tracks, follow step 9 above.
  6. Select "My Data > My Sessions"
  7. Under "Save current settings as named session:" enter a new descriptive name OR the previous name of the session if you'd like to overwrite it
  8. Select "Submit"
  9. This will move the descriptive name entered into the "session name" list
  10. Select the descriptve name, view your track information as saved
  11. Copy the hyperlink for this session and share as needed

TIP: Unindexed file formats like bed and gtf take significantly longer to load in the genome Browser and it is recommended to convert them to indexed formats like bigBed and bigWig prior to adding them to your session.


Last update: 2024-01-08
\ No newline at end of file diff --git a/UCSC/overview/index.html b/UCSC/overview/index.html new file mode 100644 index 0000000..383c087 --- /dev/null +++ b/UCSC/overview/index.html @@ -0,0 +1 @@ + Overview - CCBR How Tos
Skip to content

Overview

The UCSC Genome Browser allows for visualization of genomic data in an interactive and shareable format. User's must create accounts with their NIH credentials, and have an active Biowulf account to create the tracks. In addition users have to be connect to VPN in order to view and create the tracks. Once bigwig files are generated and stored in a shared data location, genomic tracks can be edited, and permanent links created, accessible for collaborators to view.


Last update: 2024-01-08
\ No newline at end of file diff --git a/assets/images/doc-book.svg b/assets/images/doc-book.svg new file mode 100644 index 0000000..10ced62 --- /dev/null +++ b/assets/images/doc-book.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/assets/javascripts/bundle.51d95adb.min.js b/assets/javascripts/bundle.51d95adb.min.js new file mode 100644 index 0000000..b20ec68 --- /dev/null +++ b/assets/javascripts/bundle.51d95adb.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(kt)for(var r of kt(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&an.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Ht((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,We=T.tagName;return!!(We==="INPUT"&&a[Ke]&&!T.readOnly||We==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function re(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,re())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),B(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var un=Ht(Sr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(re,z){d.append(z,re)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+c+" due to "+T)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,B=!0,re=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,re.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr)});var Qr=Ht((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},re=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=re;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},We=Ke;function Ie(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(w){return typeof w}:Ie=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Ie(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Ie(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",Rt=We({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Le,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(Rt){Le=Le&&!!document.queryCommandSupported(Rt)}),Le}}]),w}(s()),ki=Ri},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Xe?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof xe=="function"?xe(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function De(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)dn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&De(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&De(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Or=Fe.EMPTY;function It(e){return e instanceof Fe||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new Fe(function(){n.currentObservers=null,De(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Or},t}(E);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,a=o._buffer,s=a.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var On=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var we=new On(Tn);var R=new U(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Dt(kr(e))?e.pop():void 0}function Vt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ki();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return ln(this,arguments,function(){var r,n,o,i;return Pt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Xe(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Xe(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Xe(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(Nt(e))return Qi(e);if(pt(e))return Yi(e);if(zt(e))return Gi(e);if(qt(e))return _n(e);if(Yt(e))return Bi(e);if(Bt(e))return Ji(e)}throw Kt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):me,Oe(1),r?He(t):zn(function(){return new Xt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function fe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},re=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;re(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var We=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),We.subscribe(Ke),!u&&d>0&&(u=new et({next:function(Ie){return We.next(Ie)},error:function(Ie){v=!0,B(),p=jr(re,o,Ie),We.error(Ie)},complete:function(){h=!0,B(),p=jr(re,a),We.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(e,t=document){let r=se(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function se(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),Y())}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,we),l(()=>Be(e)),N(Be(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,we),l(()=>rr(e)),N(rr(e)))}var Bn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!zr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ya.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>de(e)))),N(de(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function sr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=de(e),o=bt(e);return r>=o.height-n.height-t}),Y())}var cr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return cr[e].checked}function qe(e,t){cr[e].checked!==t&&cr[e].click()}function je(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),fe());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)co(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)co(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>se(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function ur(e,t={credentials:"same-origin"}){return ve(fetch(`${e}`,t)).pipe(ce(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function Ue(e,t){return ur(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return ur(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Be(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(`
\ No newline at end of file diff --git a/images/gitmodel.png b/images/gitmodel.png new file mode 100644 index 0000000000000000000000000000000000000000..5b96426c76e9b59f162331cf2c8eb5bd1446b8f6 GIT binary patch literal 124925 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�QQpl!FqPohLNfFE1 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

Kh5V?q&1SWLKGwoIdmjHtQyKHxgywu0?&pf* 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

|W@eX7X<*f|U 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 E57MRp_5c6? literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..2d50924 --- /dev/null +++ b/index.html @@ -0,0 +1,8 @@ + CCBR How Tos

This page is designed to share knowledge between analysts within CCBR.

You'll find how-to-guides, best practices and tutorials under the following pages:

- How To, Best Practices: GitHub, TechDev
+- How To: Setup and use HPCDME
+- How To: Create UCSC Tracks
+- How To: Create an R package
+- How To: use Datashare
+- How To: Create a Zenodo DOI Link
+- Tutorials: Snakemake
+

This page was created through the contributions of several members within CCBR. If you would like to contribute to it's development, please email Samantha Sevilla.


Last update: 2024-01-08
\ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dbb4365 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +#https://pypi.org/project/mkdocs-git-revision-date-localized-plugin/ +mkdocs-git-revision-date-localized-plugin==1.2.0 +#https://pypi.org/project/mkdocs-minify-plugin/ +mkdocs-minify-plugin==0.6.4 +#https://pypi.org/project/mkdocs-git-revision-date-plugin/ +mkdocs-git-revision-date-plugin==0.3.2 \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..bbb92e5 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Intro","text":"

This page is designed to share knowledge between analysts within CCBR.

You'll find how-to-guides, best practices and tutorials under the following pages:

- How To, Best Practices: GitHub, TechDev\n- How To: Setup and use HPCDME\n- How To: Create UCSC Tracks\n- How To: Create an R package\n- How To: use Datashare\n- How To: Create a Zenodo DOI Link\n- Tutorials: Snakemake\n

This page was created through the contributions of several members within CCBR. If you would like to contribute to it's development, please email Samantha Sevilla.

"},{"location":"contributions/","title":"Contributions","text":"

The following individuals were the main contributors to these HowTo manuals:

  • GitHub: Samantha Sevilla & Vishal Koparde
  • TechDev: Samantha Sevilla
  • HPCDME: Vishal Koparde
  • USCS Tracks: Samantha Sevilla
  • Rpackage: Ned Cauley
  • Other How To's: Ned Cauley
  • Tutorials: Samantha Sevilla
"},{"location":"GitHub/basic_actions/","title":"GitHub Basics: GitHub Actions","text":"

The following describe the minimum GitHub actions that should be deployed with any production pipeline. The actions are automatically provided via the cookiecutter templates: NextFlow and Snakemake.

  1. Documentation (assumes mkdocs build; required for all repos)

    • These rules will automatically update any documentation built with mkdocs for all PR's.
    • Rule Name(s): mkdocs_build \u2192 pages-build-and-deployment
  2. Lintr (required for CCBR projects and new pipelines)

    • This rule will automatically perform a lintr with the data provided in the .test folder of the pipeline. Review the GitHub Best Practices - Test Data page for more information.
  3. Dry-run with test sample data for any PR to dev branch (required for CCBR projects and new pipelines)

    • This rule will automatically perform a dry-run with the data provided in the .test folder of the pipeline. Review the GitHub Best Practices - Test Data page for more information.
  4. Full-run with full sample data for any PR to main branch (required for CCBR projects and new pipelines)

    • This rule will automatically perform a full-run with the data provided in the .test folder of the pipeline. Review the GitHub Best Practices - Test Data page for more information.
  5. Auto pull/push from source (if applicable for CCBR projects and new pipelines)

    • If the pipeline is forked from another location and updating this forked pipeline is required, an action will automatically perform a pull from the source location at least once a week.
"},{"location":"GitHub/basic_docs/","title":"GitHub Basics: Documentation","text":"

GitHub Pages is quick and easy way to build static websites for your GitHub repositories. Essentially, you write pages in Markdown which are then rendered to HTML and hosted on GitHub, free of cost!

CCBR has used GitHub pages to provide extensive, legible and organized documentation for our pipelines. Examples are included below:

  • CARLISLE
  • Pipeliner
  • RNA-seek

Mkdocs is the with documentation tool preferred, with the Material theme, for most of the CCBR GitHub Pages websites.

"},{"location":"GitHub/basic_docs/#install-mkdocs-themes","title":"Install MkDocs, themes","text":"

mkdocs and the Material for mkdocs theme can be installed using the following:

pip install --upgrade pip\npip install mkdocs\npip install mkdocs-material\n

Also install other common dependencies:

pip install mkdocs-pymdownx-material-extras\npip install mkdocs-git-revision-date-localized-plugin\npip install mkdocs-git-revision-date-plugin\npip install mkdocs-minify-plugin\n
"},{"location":"GitHub/basic_docs/#conventions","title":"Conventions","text":"

Generally, for GitHub repos with GitHub pages:

  • The repository needs to be public (not private)
  • The main/master branch has the markdown documents under a docs folder at the root level
  • Rendered HTMLs are hosted under a gh-pages branch at root level
"},{"location":"GitHub/basic_docs/#create-website","title":"Create website","text":"

The following steps can be followed to build your first website

"},{"location":"GitHub/basic_docs/#add-mkdocsyaml","title":"Add mkdocs.yaml","text":"

mkdocs.yaml needs to be added to the root of the master branch. A template of this file is available in the cookiecutter template.

git clone https://github.com/CCBR/xyz.git\ncd xyz\nvi mkdocs.yaml\ngit add mkdocs.yaml\ngit commit -m \"adding mkdocs.yaml\"\ngit push\n

Here is a sample mkdocs.yaml:

# Project Information\nsite_name: CCBR How Tos\nsite_author: Vishal Koparde, Ph.D.\nsite_description: >-\nThe **DEVIL** is in the **DETAILS**. Step-by-step detailed How To Guides for data management and other CCBR-relevant tasks.\n\n# Repository\nrepo_name: CCBR/HowTos\nrepo_url: https://github.com/CCBR/HowTos\nedit_uri: https://github.com/CCBR/HowTos/edit/main/docs/\n\n# Copyright\ncopyright: Copyright &copy; 2023 CCBR\n\n# Configuration\ntheme:\nname: material\nfeatures:\n- navigation.tabs\n- navigation.top\n- navigation.indexes\n- toc.integrate palette:\n- scheme: default\nprimary: indigo\naccent: indigo\ntoggle:\nicon: material/toggle-switch-off-outline\nname: Switch to dark mode\n- scheme: slate\nprimary: red\naccent: red\ntoggle:\nicon: material/toggle-switch\nname: Switch to light mode\nlogo: assets/images/doc-book.svg\nfavicon: assets/images/favicon.png\n\n# Plugins\nplugins:\n- search\n- git-revision-date\n- minify:\nminify_html: true\n\n\n# Customization\nextra:\nsocial:\n- icon: fontawesome/solid/users\nlink: http://bioinformatics.cancer.gov\n- icon: fontawesome/brands/github\nlink: https://github.com/CCRGeneticsBranch\n- icon: fontawesome/brands/docker\nlink: https://hub.docker.com/orgs/nciccbr/repositories\nversion:\nprovider: mike\n\n\n# Extensions\nmarkdown_extensions:\n- markdown.extensions.admonition\n- markdown.extensions.attr_list\n- markdown.extensions.def_list\n- markdown.extensions.footnotes\n- markdown.extensions.meta\n- markdown.extensions.toc:\npermalink: true\n- pymdownx.arithmatex:\ngeneric: true\n- pymdownx.betterem:\nsmart_enable: all\n- pymdownx.caret\n- pymdownx.critic\n- pymdownx.details\n- pymdownx.emoji:\nemoji_index: !!python/name:materialx.emoji.twemoji\nemoji_generator: !!python/name:materialx.emoji.to_svg\n- pymdownx.highlight\n- pymdownx.inlinehilite\n- pymdownx.keys\n- pymdownx.magiclink:\nrepo_url_shorthand: true\nuser: squidfunk\nrepo: mkdocs-material\n- pymdownx.mark\n- pymdownx.smartsymbols\n- pymdownx.snippets:\ncheck_paths: true\n- pymdownx.superfences\n- pymdownx.tabbed\n- pymdownx.tasklist:\ncustom_checkbox: true\n- pymdownx.tilde\n\n# Page Tree\nnav:\n- Intro : index.md\n
"},{"location":"GitHub/basic_docs/#create-indexmd","title":"Create index.md","text":"

Create docs folder, add your index.md there.

mkdir docs\necho \"### Testing\" > docs/index.md\ngit add docs/index.md\ngit commit -m \"adding landing page\"\ngit push\n
"},{"location":"GitHub/basic_docs/#build-site","title":"Build site","text":"

mkdocs can now be used to render .md to HTML

mkdocs build\nINFO     -  Cleaning site directory\nINFO     -  Building documentation to directory: /Users/$USER/Documents/GitRepos/parkit/site\nINFO     -  Documentation built in 0.32 seconds\n

The above command creates a local site folder which is the root of your \"to-be-hosted\" website. You can now open the HTMLs in the site folder locally to ensure that that HTML is as per you liking. If not, then you can make edits to the .md files and rebuild the site.

NOTE: You do not want to push the site folder back to GH and hence it needs to be added to .gitignore file:

echo \"**/site/*\" > .gitignore\ngit add .gitignore\ngit commit -m \"adding .gitignore\"\ngit push\n
"},{"location":"GitHub/basic_docs/#deploy-site","title":"Deploy site","text":"

The following command with auto-create a gh-pages branch (if it does not exist) and copy the contents of the site folder to the root of that branch. It will also provide you the URL to your newly created website.

mkdocs gh-deploy\nINFO     -  Cleaning site directory\nINFO     -  Building documentation to directory: /Users/kopardevn/Documents/GitRepos/xyz/site\nINFO     -  Documentation built in 0.34 seconds\nWARNING  -  Version check skipped: No version specified in previous deployment.\nINFO     -  Copying '/Users/kopardevn/Documents/GitRepos/xyz/site' to 'gh-pages' branch and pushing to\n            GitHub.\nEnumerating objects: 51, done.\nCounting objects: 100(51/51), done.\nDelta compression using up to 16 threads\nCompressing objects: 100(47/47), done.\nWriting objects: 100(51/51), 441.71 KiB | 4.29 MiB/s, done.\nTotal 51 (delta 4), reused 0 (delta 0), pack-reused 0\nremote: Resolving deltas: 100(4/4), done.\nremote:\nremote: Create a pull request for 'gh-pages' on GitHub by visiting:\nremote:      https://github.com/CCBR/xyz/pull/new/gh-pages\nremote:\nTo https://github.com/CCBR/xyz.git\n * [new branch]      gh-pages -> gh-pages\nINFO     -  Your documentation should shortly be available at: https://CCBR.github.io/xyz/\n

Now if you point your web browser to the URL from gh-deploy command (IE https://CCBR.github.io/xyz/) you will see your HTML hosted on GitHub. After creating your docs, the cookiecutter template includes a GitHub action which will automatically perform the above tasks whenever a push is performed to the main branch.

"},{"location":"GitHub/basic_docs/#add-to-the-github-page","title":"Add to the GitHub page","text":"
  1. Go to the main GitHub page of your repository
  2. On the top right select the gear icon next to About
  3. Under Website, select Use your GitHub Pages website.
  4. Select Save Changes
"},{"location":"GitHub/basic_repo/","title":"GitHub Basics: Repository","text":""},{"location":"GitHub/basic_repo/#repository-location","title":"Repository Location","text":"

All CCBR developed pipelines, and techdev efforts should be created under CCBR's GitHub Org Account and all CCBR team members should have a minimal of read-only permission to the repository.

"},{"location":"GitHub/basic_repo/#use-of-cookiecutter-templates","title":"Use of CookieCutter Templates","text":"
  • All CCBR developed pipelines should be created from the appropriate templates:
    • Nextflow Pipelines: https://github.com/CCBR/CCBR_NextflowTemplate
    • Snakemake Pipelines: https://github.com/CCBR/CCBR_SnakemakeTemplate
    • TechDev Projects: https://github.com/CCBR/CCBR_TechDevTemplate

Note: The above templates are themselves under active development! As we continue building a multitude of analysis pipelines, we keep expanding on the list of \"commonalities\" between these analysis pipelines which need to be added to the template itself. Hence, templates are updated from time-to-time.

"},{"location":"GitHub/basic_repo/#creating-a-new-repository","title":"Creating a new repository","text":"

To create a new repository on Github using gh cli, you can run the following command on Biowulf after you update the new repository name (<ADD NEW REPO NAME>) and the repository description (<ADD REPO DESCRIPTION>) commands below.

Naming Nomenclature: - All Repositories: Do not remove the CCBR/ leading the repository name, as this will correctly place the repository under the CCBR organization account. - CCBR Projects: These should be named with the CCBR#. IE CCBR/CCBR1155 - CCBR Pipelines: These should be descriptive of the pipelines main process; acronyms are encouraged. IE CCBR/CARLISLE - TechDev projects: These should be descriptive of the techDev project to be performed and should begin with techdev_. IE CCBR/techdev_peakcall_benchmarking

"},{"location":"GitHub/basic_repo/#1-creating-a-new-project-or-new-pipeline-repository","title":"1) Creating a new project OR new pipeline repository","text":"

gh repo create CCBR/<ADD NEW REPO NAME> \\\n--template CCBR/CCBR_NextflowTemplate \\\n--description \"<ADD REPO DESCRIPTION>\" \\\n--public \\\n--confirm\n
gh repo create CCBR/<ADD NEW REPO NAME> \\\n--template CCBR/CCBR_SnakemakeTemplate \\\n--description \"<ADD REPO DESCRIPTION>\" \\\n--public \\\n--confirm\n

"},{"location":"GitHub/basic_repo/#2-creating-a-new-techdev","title":"2) Creating a new techDev","text":"
gh repo create CCBR/techdev_<ADD NEW REPO NAME> \\\n--template CCBR/CCBR_TechDevTemplate \\\n--description \"<ADD REPO DESCRIPTION>\" \\\n--public \\\n--confirm\n

Once the repo is created, then you can clone a local copy of the new repository:

gh repo clone CCBR/<reponame>.git\n
"},{"location":"GitHub/howto_functions/","title":"GitHub HowTo: Basic Functions","text":"

The following outlines basic GitHub function to push and pull from your repository. It also includes information on creating a new branch and deleting a branch. These commands should be used in line with guidance on GitHub Repo Management.

"},{"location":"GitHub/howto_functions/#pushing-local-changes-to-remote","title":"Pushing local changes to remote","text":"

Check which files have been changed.

git status\n

Stage files that need to be pushed

git add <thisfile>\ngit add <thatfile>\n

Push changes to branch named new_feature

git push origin new_feature\n

"},{"location":"GitHub/howto_functions/#pulling-remote-changes-to-local","title":"Pulling remote changes to local","text":"

Pull changes from branch new_feature into your branch old_feature

git checkout old_feature\ngit pull new_feature\n

If you have non-compatible changes in the old_feature branch, there are two options: 1) ignore local changes and pull remote anyways. This will delete the changes you've made to your remote respository.

git reset --hard\ngit pull\n
2) temporarily stash changes away, pull and reapply changes after.
git stash\ngit pull\ngit stash pop\n

"},{"location":"GitHub/howto_functions/#creating-a-new-branch","title":"Creating a new branch","text":"

This is a two step process.

  • Create the branch locally

    git checkout -b <newbranch>\n

  • Push the branch to remote

    git push -u origin <newbranch>\n
    OR
    git push -u origin HEAD\n
    This is a shortcut to push the current branch to a branch of the same name on origin and track it so that you don't need to specify origin HEAD in the future.

"},{"location":"GitHub/howto_functions/#deleting-branches","title":"Deleting branches","text":""},{"location":"GitHub/howto_functions/#locally","title":"Locally","text":"
git branch -d <BranchName>\n
"},{"location":"GitHub/howto_functions/#on-github","title":"on GitHub","text":"
git push origin --delete <BranchName>\n
"},{"location":"GitHub/howto_precommit/","title":"GitHub HowTo: Pre-Commit","text":"

Pre-commit should be added to all GitHub repositories on Biowulf and any clones created elsewhere to ensure cohesive and informative commit messages. After the creating the repository the following commands should be run in order to initialize the pre-commit hook, and establish the following requirements for all commit messages:

"},{"location":"GitHub/howto_precommit/#using-precommit","title":"Using Precommit","text":"

Pre-commit has been installed as a module on Biowulf. Set up an interactive session, and follow the steps below. A pre-commit configuration file is needed, and can be copied from the CCBR template repo.

# load module on biowulf\nmodule load precommit\n\n# CD into the GitHub repo\ncd <repo_name>\n\n# install precommit in the repo - this is the only time you need to do this, per local repo location\npre-commit install\n\n# copy and update the precommit config\ntouch .pre-commit.config\n

"},{"location":"GitHub/howto_precommit/#structure-of-commit-messages","title":"Structure of Commit Messages","text":"

Commits must follow the format listed below, as designated by Angular:

<type>(<scope>): <subject>\n<body>\n<BLANK LINE>\n<footer>\n

"},{"location":"GitHub/howto_precommit/#type-required","title":"Type (REQUIRED)","text":"

The type must be one of the following options:

  • build: Changes that affect the build system or external dependencies
  • ci: Changes to our CI configuration files and scripts
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • test: Adding missing tests or correcting existing tests
"},{"location":"GitHub/howto_precommit/#scope-optional","title":"Scope (OPTIONAL)","text":"

The scope must be one of the following options:

  • animations
  • common
  • compiler
  • compiler-cli
  • core
  • elements
  • forms
  • http
  • language-service
  • platform-browser
  • platform-browser-dynamic
  • platform-server
  • platform-webworker
  • platform-webworker-dynamic
  • router
  • service-worker
  • upgrade
"},{"location":"GitHub/howto_precommit/#subject-required","title":"Subject (REQUIRED)","text":"

The subject must be a succinct description of the change. It should follow the following rules:

  • use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"
  • don't capitalize the first letter
  • no dot (.) at the end
"},{"location":"GitHub/howto_precommit/#body-optional","title":"Body (OPTIONAL)","text":"

The body should include the motivation for the change and contrast this with previous behavior. It should follow the following rule:

  • use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"
"},{"location":"GitHub/howto_precommit/#footer-optional","title":"Footer (OPTIONAL)","text":"

The footer should contain any information about Breaking Changes and is also the place to reference GitHub issues that this commit Closes.

  • Breaking Changes should start with the word BREAKING CHANGE: with a space or two newlines. The rest of the commit message is then used for this.
  • Closed bugs should be listed on a separate line in the footer from Breaking Changes, prefixed with \"Closes\" keyword (Closes #234 or Closes #123, #245, #992).
"},{"location":"GitHub/howto_precommit/#examples","title":"Examples","text":"

Below are some examples of properly formatted commit messages

# example\ndocs(changelog): update changelog to beta.5\n\n# example\nfix(release): need to depend on latest rxjs and zone.js\n\n# example\nfeat($browser): onUrlChange event (popstate/hashchange/polling)\nAdded new event to $browser:\n- forward popstate event if available\n- forward hashchange event if popstate not available\n- do polling when neither popstate nor hashchange available\n\nBreaks $browser.onHashChange, which was removed (use onUrlChange instead)\n\n# example\nfix($compile): couple of unit tests for IE9\nOlder IEs serialize html uppercased, but IE9 does not...\nWould be better to expect case insensitive, unfortunately jasmine does\nnot allow to user regexps for throw expectations.\n\nCloses #392\nBreaks foo.bar api, foo.baz should be used instead\n

"},{"location":"GitHub/howto_setup/","title":"GitHub Setup: Preparing the Environment","text":""},{"location":"GitHub/howto_setup/#using-github-cli","title":"Using GitHub CLI","text":"

The gh is installed on Biowulf at /data/CCBR_Pipeliner/db/PipeDB/bin/gh_1.7.0_linux_amd64/bin/gh. You can run the following lines to edit your ~/.bashrc file to add gh to your $PATH:

echo \"export PATH=$PATH:/data/CCBR_Pipeliner/db/PipeDB/bin/gh_1.7.0_linux_amd64/bin\" >> ~/.bashrc\nsource ~/.bashrc\n

Alternatively, you can use the git commands provided through a Biowulf module

module load git\n

"},{"location":"GitHub/howto_setup/#creating-pat-for-gh","title":"Creating PAT for GH","text":"

Personal Access Token (PAT) is required to access GitHub (GH) without having to authenticate by other means (like password) every single time. You will need gh cli installed on your laptop or use /data/CCBR_Pipeliner/db/PipeDB/bin/gh_1.7.0_linux_amd64/bin/gh on Biowulf, as described above. You can create a PAT by going here. Then you can copy the PAT and save it into a file on Biowulf (say ~/gh_token). Next, you can run the following command to set everything up correctly on Biowulf (or your laptop)

gh auth login --with-token < ~/git_token\n

"},{"location":"GitHub/howto_setup/#password-less-login","title":"Password-less Login","text":"

If you hate to re-enter (username and) password every time you push/pull to/from github (or mkdocs gh-deploy), then it is totally worthwhile to spend a couple minutes to set up SSH keys for auto-authentication. The instructions to do this are available here.

"},{"location":"GitHub/overview/","title":"Overview of GitHub Topics","text":""},{"location":"GitHub/overview/#getting-set-up-and-familiar-with-github","title":"Getting set-up and familiar with GitHub","text":"
  1. Preparing your environment:
    • Describes how to create a PAT, add GH to your bash profile and use password-less login features
  2. Basic Commands:
    • Describes basic functions to be used with this SOP
"},{"location":"GitHub/overview/#basics","title":"Basics","text":"
  1. Creating your GitHub repo:
    • Provides information on how to setup a GitHub repository under CCBR and the use of templates
  2. Creating your Documentation:
    • Provides information on how to setup documentation under your repository; provided with all template repos
  3. GitHub Actions:
    • Provides information for using GitHub Actions under your repository; provided with all template repos
"},{"location":"GitHub/overview/#best-practices","title":"Best Practices","text":"
  1. CCBR Projects, new Pipelines
  2. TechDev
"},{"location":"GitHub/sop_projpipes/","title":"GitHub Best Practices: Projects and Pipelines","text":"
  • Users should follow these links to learn more about setting up the repository, before reviewing the best practices below:

    • Preparing your environment
    • Basic Commands
    • Creating your GitHub repo
    • Creating your Documentation
    • GitHub Actions
"},{"location":"GitHub/sop_projpipes/#pipeline-documentation","title":"Pipeline Documentation","text":"
  • All pipelines should provide users with documentation for usage, test data, expected outputs, and troubleshooting information. Mkdocs is the recommended tool to perform this action, however, other tools may be utilized. The template's (NextFlow, Snakemake) were written for mkdocs, and provide basic yaml markdown files provided for this use. They should be edited according to the pipelines function and user needs. Examples of the requirements for each page are provided in the templates.

    1. Background
      • Information on who the pipeline was developed for, and a statement if it's only been tested on Biowulf.
      • Also include a workflow image to summarize the pipeline.
    2. Getting Started
      • This should set the stage for all of the pipeline requirements. This should include the following pages:
        • Introduction
        • Setup Dependencies
        • Login to the cluster
        • Load an interactive session
    3. Preparing Files
      • This should include the following pages:
        • Configs
          • Cluster Config
          • Tools Config
          • Config YAML
            • User Parameters
            • References
        • Preparing Manifests
          • Samples Manifest
    4. Running the Pipeline
      • This should include all information about the various run commands provided within the pipeline. This should include the following pages:
        • Pipeline Overview
        • Commands explained
        • Typical Workflow
    5. Expected Output
      • This should include all pertinent information about output files, including extensions that differentiate files.
    6. Running Test Data
      • This should walk the user through the steps of running the pipeline using test data. This should include the following pages:
        • Getting Started
        • About the test data
        • Submit the test data
        • Review outputs
"},{"location":"GitHub/sop_projpipes/#repository-management","title":"Repository Management","text":""},{"location":"GitHub/sop_projpipes/#security-settings","title":"Security settings","text":"
  • Two members of CCBR (creator and one manager) should be granted full administrative privileges to the repository to ensure the source code can be accessed by other members, as needed
  • Both the develop and master branch must be protected (IE have to have a PR to be changed)
"},{"location":"GitHub/sop_projpipes/#ccbr-branch-strategy","title":"CCBR Branch Strategy","text":""},{"location":"GitHub/sop_projpipes/#branch-naming","title":"Branch Naming","text":"
  • All repositories should follow the strategy outlined in the Creating your GitHub repo
"},{"location":"GitHub/sop_projpipes/#branch-overview","title":"Branch Overview","text":"
  • All repositories should include a minimum of two branches at any time:
    • main (master)
    • dev
  • Additional branches should be created as needed. These would include feature branches, developed using individual, feature specific addition and hotfix branches, developed using individual, bug specific fixes.
  • Utilization of these branches should follow the documentation below.
"},{"location":"GitHub/sop_projpipes/#strategy-outline","title":"Strategy Outline","text":"
  • We encourage the use of the Git Flow tools for some actions, available on Biowulf (module load gitflow). Our current branching strategy is based off of the Git Flow strategy shown below :

ref:https://nvie.com/posts/a-successful-git-branching-model/

  1. Master (named main or master)
    • branch that contains the current release / tagged version of the pipeline
    • merges from Dev branch or hotfix branch allowed
    • merges require actions_master_branch pass from GitHub actions. See GitHub actions #4 for more information testing requirements for merge
  2. Develop (named dev or activeDev)
    • branch that contains current dev
    • merges from feature branch allowed
    • merges require actions_dev_branch pass from GitHub actions. See GitHub actions #3 for more information testing requirements for merge
  3. Feature (named feature/unique_feature_name)
    • branch to develop new features that branches off the develop branch
    • recommended usages of git flow feature start unique_feature_name followed by git flow feature publish unique_feature_name
    • no merges into this branch are expected
  4. Hotfix (named unique_hotfix_name)
    • branches arise from a bug that has been discovered and must be resolved; it enables developers to keep working on their own changes on the develop branch while the bug is being fixed
    • recommended usage of git flow hotfix start unique_hotfix_name
    • no merges into this branch are expected

NOTE: While the git flow feature start command is recommended for feature branch merging, the git flow feature finish is not. Using the finish command will automatically merge the feature branch into the dev branch, without any testing, and regardless of divergence that may have occured during feature development.

"},{"location":"GitHub/sop_projpipes/#general-workflow-steps","title":"General Workflow (Steps)","text":"
  1. Assuming that you have already cloned the repo and initiated git flow with git flow init
  2. Create a new feature and publish it git flow feature start unique_feature_name and then git flow feature publish unique_feature_name. The unique_feature_name will be created from the develop branch.
  3. Code normally, make frequent commits, push frequently to remote. These commits are added to the unique_feature_name branch.
  4. When you are ready to add your feature enhancements back to the develop branch, you may have to make sure that the develop branch has not marched forward while you were working on the unique_feature_name feature (This is possible as other may have added their PRs in the interim). If it has, then you may have to pull in changes made to develop branch into your unique_feature_name feature branch. This can be achieved using the GitHub web interface... merge develop \u2190 unique_feature_name. Resolve conflicts if any.
  5. Retest your unique_feature_name branch.
  6. Now send in a pull request using the GitHub web interface to pull your unique_feature_name into develop branch.
  7. Occasionally, we may create a new release branch from the develop branch and perform thorough E2E testing with fixes. Once, everything is working as expected, we pull the release branch back into develop and also push it to main with a version tag.
"},{"location":"GitHub/sop_projpipes/#release-tagged-nomenclature","title":"Release, Tagged Nomenclature","text":"
  • The following format of versioning should be followed:

    v.X.Y.Z\n
  • The following rules should be applies when determining the version release:

    • X is major; non-backward compatible (dependent on the amount of changes; from dev)
    • Y is minor; backwards compatible (dependent on the amount of changes; from dev)
    • Z is patches; backwards compatible (bugs; hot fixes)
  • Other notes:

    • X,Y,Z must be numeric only
    • All updates to the main (master) branch must be tagged and versioned using the parameters above
    • Updates to the dev branch can be tagged, but should not be versioned
    • If the pipeline is available locally (IE on Biowulf), version changes should be added for use
"},{"location":"GitHub/sop_projpipes/#pipelines-test-data","title":"Pipelines Test Data","text":"

The following information is meant to outline test_data requirements for all pipelines, however, should be altered to fit the needs of the specific pipeline or project developed.

"},{"location":"GitHub/sop_projpipes/#requirements","title":"Requirements","text":"
  1. Location of data
    • Test data sets should be stored within a .test directory, as found in all templates.
  2. Documentation
    • Review information on the documentation page, which will provide basic information on test data used within the project/pipeline.
    • A README file should be created under the .test directory, to include the following information:
      • Date of implementation
      • Information on species (IE Homo Sapiens) and data type (IE RNA-Seq)
      • Information on the references to be used (IE hg38)
      • Metadata manifests required by the pipeline
      • The source of the files
      • Link to scripts used in created the partial test data
  3. Choosing a test data set
    • At a minimum three test sets should be available:

      1) Should include sub-sampled inputs, to test the pipelines functionality, and to be used as the tutorial test set. 2) Should include full-sample inputs, of high quality, to test the robustness of the pipelines resources 3) Should include full-sample inputs, of expected project-level quality, to test the robustness of the pipelines error handling - Test data should come from a CCBR project or a a publicly available source. Care should be taken when choosing test data sets, to ensure that the robustness of the pipeline will be tested, as well as the ability of the pipeline to handle both high and low quality data. Multiple test sets may need to be created to meet these goals.

"},{"location":"GitHub/sop_techdev/","title":"GitHub Best Practices","text":"
  • Users should follow these links to learn more about setting up the repository, before reviewing the best practices below:

    • Preparing your environment
    • Basic Commands
    • Creating your GitHub repo
    • Creating your Documentation
    • GitHub Actions
"},{"location":"GitHub/sop_techdev/#techdev-documentation","title":"TechDev Documentation","text":"
  • All pipelines should provide users with:

    • documentation for usage
    • test data
    • expected outputs and reports
    • troubleshooting information

    Markdown pages can be hosted directly within the repo using GH Pages. Mkdocs is the recommended tool to perform this action, however, other tools may be utilized. The templates (TechDev) template's (written for mkdocs) provided have basic yaml markdown files provided for this use, and should be edited according to the pipelines function and user needs. Also, track blockers/hurdles using GitHub Issues.

    1. Overview
      • Information on the goal of the TechDev project.
    2. Analysis 2.1. Background

      • Provide any relaxant background to the project to be completed. This might include information on: - problem that was encountered leadings to this techdev - new feature or tool developed to be benchmarked - relevant biological or statistical information needed to perform this analysis

      2.2. Resources - This page should include any relevant tools that were used for testing. If these tools were loaded via Biowulf, include all version numbers. If they were installed locally, provide information on installation, source location, and any reference documents used.

      2.3. Test Data - This will include information on the test data included within the project. Species information, source information, and references should be included. Any manipulation performed on the source samples should also be included. Manifest information should also be outlined. Provide location to toy dataset or real dataset or both. It is best to park these datasets at a commonly accessible location on Biowulf and share that location here. Also, make the location read-only to prevent accidental edits by other users.

      2.4. Analysis Plan - Provide a summary of the plan of action. - If benchmarking tools, include the dataset used, where the source material was obtained, and all relevant metadata. - Include the location of any relevant config / data files used in this analysis - Provide information on the limits of the analysis - IE this was only tested on Biowulf, this was only performed in human samples, etc.

      2.5. Results - What were the findings of this TechDev exercise? Include links to where intermediate files may be located. Include tables, plots, etc. This will serve as a permanent record of the TechDev efforts to be shared within the team and beyond.

      2.6 Conclusions - Provide brief, concise conclusion drawn from the analysis, including any alterations being made to pipelines or analysis.

    3. Contributions

      • Provide any names that contributed to this work.
"},{"location":"GitHub/sop_techdev/#techdev-repository-management","title":"TechDev Repository Management","text":""},{"location":"GitHub/sop_techdev/#security-settings","title":"Security settings","text":"
  • Two members of CCBR (creator and one manager) should be granted full administrative privileges to the repository to ensure the source code can be accessed by other members, as needed
  • Both the develop and master branch must be protected (IE have to have a PR to be changed)
"},{"location":"GitHub/sop_techdev/#ccbr-branch-strategy","title":"CCBR Branch Strategy","text":""},{"location":"GitHub/sop_techdev/#branch-naming","title":"Branch Naming","text":"
  • All repositories should follow the strategy outlined in the Creating your GitHub repo
"},{"location":"GitHub/sop_techdev/#branch-overview","title":"Branch Overview","text":"
  • All repositories should include a minimum of two branches at any time:
    • main (master)
    • dev
  • Utilization of these branches should follow the documentation below.
"},{"location":"GitHub/sop_techdev/#branch-strategy","title":"Branch Strategy","text":"
  • We encourage the use of the Git Flow tools for some actions, available on Biowulf. Our current branching strategy is based off of the Git Flow strategy shown below :

  • Master (named main or master)

    • branch that contains the current release / tagged version of the pipeline
    • merges from Dev branch or hotfix branch allowed
    • merges require actions_master_branch pass from GitHub actions. See GitHub actions #4 for more information testing requirements for merge
  • Develop (named dev or activeDev)
    • branch that contains current dev
    • merges from feature branch allowed
    • merges require actions_dev_branch pass from GitHub actions. See GitHub actions #3 for more information testing requirements for merge
"},{"location":"GitHub/sop_techdev/#techdev-test-data","title":"TechDev Test Data","text":""},{"location":"GitHub/sop_techdev/#requirements","title":"Requirements","text":"
  1. Location of data
    • Test data sets should be stored within a .test directory, as found in all templates.
  2. Documentation
    • Review information on the documentation page, which will provide basic information on test data used within the project/pipeline.
    • A README file should be created under the .test directory, to include the following information:
      • Date of implementation
      • Information on species (IE Homo Sapiens) and data type (IE RNA-Seq)
      • Information on the references to be used (IE hg38)
      • Metadata manifests required by the pipeline
      • The source of the files
      • Link to scripts used in created the partial test data
  3. Choosing a test data set
    • Test data should come from a CCBR project or a a publicly available source. Care should be taken when choosing test data sets, to ensure that the data matches the goals of the techdev effort.
"},{"location":"HPCDME/setup/","title":"Setup","text":""},{"location":"HPCDME/setup/#background","title":"Background","text":"

HPC_DME_APIs provides command line utilities or CLUs to interface with HPCDME. This document describes some of the initial setup steps to get the CLUs working on Biowulf.

"},{"location":"HPCDME/setup/#setup-steps","title":"Setup steps:","text":""},{"location":"HPCDME/setup/#clone-repo","title":"Clone repo:","text":"

The repo can be cloned at a location accessible to you:

cd /data/$USER/\ngit clone https://github.com/CBIIT/HPC_DME_APIs.git\n
"},{"location":"HPCDME/setup/#create-dirs-log-files-needed-for-hpcmde","title":"Create dirs, log files needed for HPCMDE","text":"
mkdir -p /data/$USER/HPCDMELOG/tmp\ntouch /data/$USER/HPCDMELOG/tmp/hpc-cli.log\n
"},{"location":"HPCDME/setup/#copy-properties-template","title":"Copy properties template","text":"

hpcdme.properties is the file that all CLUs look into for various parameters like authentication password, file size limits, number of CPUs, etc. Make a copy of the template provided and prepare it for customization.

cd /data/$USER/HPC_DME_APIs/utils\ncp hpcdme.properties-sample hpcdme.properties\n
"},{"location":"HPCDME/setup/#customize-properties-file","title":"Customize properties file","text":"

Some of the parameters in this file have become obsolete over the course of time and are commmented out. Change paths and default values, as needed

#HPC DME Server URL\n#Production server settings\nhpc.server.url=https://hpcdmeapi.nci.nih.gov:8080\nhpc.ssl.keystore.path=hpc-client/keystore/keystore-prod.jks\n#hpc.ssl.keystore.password=hpcdmncif\nhpc.ssl.keystore.password=changeit\n\n#UAT server settings\n#hpc.server.url=https://fr-s-hpcdm-uat-p.ncifcrf.gov:7738/hpc-server\n#hpc.ssl.keystore.path=hpc-client/keystore/keystore-uat.jks\n#hpc.ssl.keystore.password=hpc-server-store-pwd\n\n#Proxy Settings\nhpc.server.proxy.url=10.1.200.240\nhpc.server.proxy.port=3128\n\nhpc.user=$USER\n\n#Globus settings\n#default globus endpoint to be used in registration and download\nhpc.globus.user=$USER\nhpc.default.globus.endpoint=ea6c8fd6-4810-11e8-8ee3-0a6d4e044368\n\n#Log files directory\nhpc.error-log.dir=/data/$USER/HPCDMELOG/tmp\n\n###HPC CLI Logging START####\n#ERROR, WARN, INFO, DEBUG\nhpc.log.level=ERROR\nhpc.log.file=/data/$USER/HPCDMELOG/tmp/hpc-cli.log\n###HPC CLI Logging END####\n\n#############################################################################\n# Please use caution changing following properties. They don't change usually\n#############################################################################\n#hpc.collection.service=collection\n#hpc.dataobject.service=dataObject\n#Log files directory\n#hpc.error-log.dir=.\n\n#Number of thread to run data file import from a CSV file\nhpc.job.thread.count=1\n\nupload.buffer.size=10000000\n\n#Retry count and backoff period for registerFromFilePath (Fixed backoff)\nhpc.retry.max.attempts=3\n#hpc.retry.backoff.period=5000\n\n#Multi-part upload thread pool, threshold and part size configuration\n#hpc.multipart.threadpoolsize=10\n#hpc.multipart.threshold=1074790400\n#hpc.multipart.chunksize=1073741824\n\n#globus.nexus.url=nexus.api.globusonline.org\n#globus.url=www.globusonline.org\n\n#HPC DME Login token file location\nhpc.login.token=tokens/hpcdme-auth.txt\n\n#Globus Login token file location\n#hpc.globus.login.token=tokens/globus-auth.txt\n#validate.md5.checksum=false\n\n# JAR version\n#hpc.jar.version=hpc-cli-1.4.0.jar\n

NOTE: The current java version used is: bash java -version openjdk version \"1.8.0_181\" OpenJDK Runtime Environment (build 1.8.0_181-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

"},{"location":"HPCDME/setup/#edit-bashrc","title":"Edit ~/.bashrc","text":"

Add the CLUs to PATH by adding the following to ~/.bashrc file

# export environment variable HPC_DM_UTILS pointing to directory where \n# HPC DME client utilities are, then source functions script in there \nexport HPC_DM_UTILS=/data/$USER/HPC_DME_APIs/utils\nsource $HPC_DM_UTILS/functions\n

Next, source it

source ~/.bashrc\n
"},{"location":"HPCDME/setup/#generate-token","title":"Generate token","text":"

Now, you are all set to generate a token. This prevents from re-entering your password everytime.

dm_generate_token\n

If the token generation takes longer than 45 seconds, check the connection:

ping hpcdmeapi.nci.nih.gov\n

If the connection responds, try to export the following proxy, and then re-run the dm_generate_tokens command:

export https_proxy=http://dtn01-e0:3128\n

Done! You are now all set to use CLUs.

"},{"location":"HPCDME/setup/#references-and-links","title":"References and Links","text":"
  • HPC_DME_APIs repo
  • User guides
  • Wiki pages
  • Yuri Dinh
"},{"location":"HPCDME/transfer/","title":"Biowulf2HPCDME","text":""},{"location":"HPCDME/transfer/#background","title":"Background","text":"

Rawdata or Project folders from Biowulf can be parked at a secure location after the analysis has reached a endpoint. Traditionally, CCBR analysts had access to the GridFTP Globus Archive for doing this. But, this Globus Archive has been running past 95% full lately.

This document outlines how a projects folder can be directly parked on HPCDME as a single \"tar.gz\" ball. It is assumed that HPC DME API CLUs are already setup as per these instructions.

Here are the steps:

"},{"location":"HPCDME/transfer/#create-tarball","title":"Create tarball","text":"

Once you have a list of files that you want to include in the tarball, create the tarball. This may take a while and should be submitted as a slurm job.

% cd /data/CCBR/projects\n% du -hs /data/CCBR/projects/ccbr796\n440G    /data/CCBR/projects/ccbr796\n% echo \"tar czvf ccbr796.tar.gz /data/CCBR/projects/ccbr796\" > do_tar_gz\n% swarm -f do_tar_gz --partition=ccr,norm --time=24:00:00 -t 2 -g 100\n41985209\n
"},{"location":"HPCDME/transfer/#create-filelist","title":"Create filelist","text":"

Sometime you just want to know what files are in the tarball. Hence, it is important to upload a filelist along with the tarball.

% tar tzvf ccbr796.tar.gz > ccbr796.tar.gz.filelist\n
"},{"location":"HPCDME/transfer/#create-project","title":"Create Project","text":"

If the Project collection does not exist in HPCDME (verify using the web interface), then you may need to create it.

% cd /data/kopardevn/SandBox/parkit\n% bash create_empty_project_collection.sh /CCBR_Archive/GRIDFTP/Project_CCBR-796 CCBR-796 CCBR-796\n{\n\"metadataEntries\": [\n{\n\"attribute\": \"collection_type\",\n         \"value\": \"Project\"\n},\n        {\n\"attribute\": \"project_start_date\",\n         \"value\": \"20220616\",\n         \"dateFormat\": \"yyyyMMdd\"\n},\n        {\n\"attribute\": \"access\",\n         \"value\": \"Open Access\"\n},\n        {\n\"attribute\": \"method\",\n         \"value\": \"NGS\"\n},\n        {\n\"attribute\": \"origin\",\n         \"value\": \"CCBR\"\n},\n        {\n\"attribute\": \"project_affiliation\",\n         \"value\": \"CCBR\"\n},\n        {\n\"attribute\": \"project_description\",\n         \"value\": \"CCBR-796\"\n},\n        {\n\"attribute\": \"project_status\",\n         \"value\": \"Completed\"\n},\n        {\n\"attribute\": \"retention_years\",\n         \"value\": \"7\"\n},\n        {\n\"attribute\": \"project_title\",\n         \"value\": \"CCBR-796\"\n},\n        {\n\"attribute\": \"summary_of_samples\",\n         \"value\": \"Unknown\"\n},\n        {\n\"attribute\": \"organism\",\n         \"value\": \"Unknown\"\n}\n]\n}\ndm_register_collection /dev/shm/Project_CCBR-796.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796\n

Error: Have encountered this error message:

Error during registration, HTTP_CODE: 503\nCannot find the response message file\ncollection-registration-response-message.json.tmp\n
503 error means that the API is down!

"},{"location":"HPCDME/transfer/#create-analysis","title":"Create Analysis","text":"

If the Analysis collection does not exist in HPCDME (verify using the web interface) under the Project collection, then you may need to create it.

% cd /data/kopardevn/SandBox/parkit\n% bash create_empty_analysis_collection.sh /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis\ndm_register_collection /dev/shm/Analysis.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis\n

Done! Now you have a location ready for the the tarball to be parked.

"},{"location":"HPCDME/transfer/#create-metadata","title":"Create metadata","text":"

Using meta script from pyrkit, we can then generate the required .metadata.json file for the tarball. Analysis collection /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis should already exist in the HPCDME vault.

% echo \"/data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis\" > do_get_metadata\n% swarm -f do_get_metadata --partition=ccr,norm --time=24:00:00 -t 2 -g 100\n

If the file is large (100s of GB), then this may take a while as the md5sum of the file is being calculated. Hence, this should be submitted to the slurm.

Metadata also needs to be created for the filelist file. These files are generally small (few MBs) and the following command can be directly run on an interactive node.

% /data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz.filelist --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis\n

The above command, when run sucessfully, will create /data/CCBR/projects/ccbr796.tar.gz.filelist.metadata.json

"},{"location":"HPCDME/transfer/#transfer","title":"Transfer","text":"

dm_register_dataobject cannot be used for large files (>10GB), but it can be replaced by dm_register_dataobject_multipart

% dm_register_dataobject_multipart /data/CCBR/projects/ccbr796.tar.gz.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz /data/CCBR/projects/ccbr796.tar.gz\nReading properties from /data/kopardevn/SandBox/HPC_DME_APIs/utils/hpcdme.properties\nRegistering file: /data/CCBR/projects/ccbr796.tar.gz\nDestination archive path: /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz\nCmd process Completed\nJun 16, 2022 10:55:25 AM org.springframework.shell.core.AbstractShell handleExecutionResult\nINFO: CLI_SUCCESS\n

Depending on the size of the file, this step can be done in a reasonable amount of time (<1hr) and can be run in an interactive node.

Remember, the filelist file also needs to be registered separately like this:

% dm_register_dataobject /data/CCBR/projects/ccbr796.tar.gz.filelist.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz.filelist /data/CCBR/projects/ccbr796.tar.gz.filelist\n

As filelist files are smaller (few MBs), we can run dm_register_dataobject in place of dm_register_dataobject_multipart.

"},{"location":"HPCDME/transfer/#cleanup","title":"Cleanup","text":"

Once the tarball is successfully transferred over the HPCDME, it can be deleted from the local filesystem.

% rm -f /data/CCBR/projects/ccbr796.tar.gz\n

The contents of the local analysis folder can also be deleted.

% cd /data/CCBR/projects/ccbr796 && rm -rf *\n

A note can be added to the recently emptied folder stating where the contents are currently parked.

% cd /data/CCBR/projects/ccbr796\n% echo \"This folder was converted to a tarball (tar.gz) and pushed to HPCDME. Its new location is \\`/CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz\\` in HPCDME\" > README.md\n

Done!

NOTE FOR LARGE FILES: It is recommended by HPCDME staff that files to be transferred should not be too large (1TB or smaller). Hence, if the file to be transferred is larger than 1TB, it should be split into 1TB-size chunks and upload those. Splitting can be done like this:

split -b 1T ccbr796.tar.gz \"ccbr796.tar.gz.part_\"\n
Metadata needs to be individidually created for each of the parts, namely, ccbr796.tar.gz.part_aa, ccbr796.tar.gz.part_ab, etc
% /data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz.part_aa --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis\n% /data/kopardevn/SandBox/pyrkit/src/meta combined --input /data/CCBR/projects/ccbr796.tar.gz.part_ab --output /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis\n...\n
Next each 1TB part can be registered like so:
% dm_register_dataobject_multipart /data/CCBR/projects/ccbr796.tar.gz.part_aa.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz.part_aa /data/CCBR/projects/ccbr796.tar.gz.part_aa\n% dm_register_dataobject_multipart /data/CCBR/projects/ccbr796.tar.gz.part_ab.metadata.json /CCBR_Archive/GRIDFTP/Project_CCBR-796/Analysis/ccbr796.tar.gz.part_ab /data/CCBR/projects/ccbr796.tar.gz.part_ab\n...\n
Once these files are downloaded then can be joined together using the cat command before ungzipping/untaring.
% cat ccbr796.tar.gz.part_* > ccbr796.tar.gz\n

"},{"location":"OtherHowTos/datashare/","title":"Datashare","text":"

Host data on Helix or Biowulf, that is publicly accessible through a URL

"},{"location":"OtherHowTos/datashare/#setup","title":"Setup","text":""},{"location":"OtherHowTos/datashare/#access-login","title":"Access Login","text":"
# Helix\nssh -Y username@helix.nih.gov\n\n# Biowulf\nssh -Y username@biowulf.nih.gov\n

Create a new dir (tutorial) in the datashare path:

cd /data/CCBR/datashare/\nmkdir tutorial\n
"},{"location":"OtherHowTos/datashare/#processing","title":"Processing","text":""},{"location":"OtherHowTos/datashare/#make-a-directory-in-the-datashare-folder","title":"Make a directory in the datashare folder","text":"

NOTE: For all steps below, an example is shown for Helix, but the same process is applicable for Biowulf, after changing the helix.nih.gov to biowulf.nih.gov

Now you can transfer your data to the new directory. One method is to use scp to copy data from your local machine to Helix.

Here is an example of using scp to copy the file file.txt from a local directory to Helix.

scp /data/$USER/file.txt username@helix.nih.gov:/data/CCBR/datashare/tutorial/\n

To copy multiple directories recursively, you can also include the -r command with scp and from the top level directory:

scp -r /data/$USER/ username@helix.nih.gov:/data/CCBR/datashare/tutorial/\n
"},{"location":"OtherHowTos/datashare/#create-public-permissions-for-data","title":"Create public permissions for data","text":"

When the data has been successully copied, we need to open the permissions.

NOTE: This will give open access to anyone with the link. Ensure this is appropriate for the data type

# cd to the shared dir\ncd /data/CCBR/datashare/\n\n# run CHMOD, twice\nchmod -R 777 tutorial\nchmod -R 777 tutorial/*\n\n# run SETFACL\nsetfacl -m u:webcpu:r-x tutorial/*\n
"},{"location":"OtherHowTos/datashare/#public-access","title":"Public Access","text":"

NOTE: You must be logged into HPC in order to access these files from a web browser.

Files will be available for access through a browser, via tools like wget and UCSC genome track browser via the following format:

http://hpc.nih.gov/~CCBR/tutorial/file.txt

For more information and a tutorial for creating UCSC tracks, visit the CCBR HowTo Page.

"},{"location":"OtherHowTos/zenodo/","title":"Zenodo","text":"

Submit a pipeline to Zenodo in order to create a DOI for publication.

"},{"location":"OtherHowTos/zenodo/#reference-link","title":"Reference link","text":"

Use the link for full information, summarized below: https://www.youtube.com/watch?v=A9FGAU9S9Ow

"},{"location":"OtherHowTos/zenodo/#prepare-github-repository","title":"Prepare GitHub Repository","text":"

The GitHub repository should include the following:

  1. README page
  2. Documentation page, such as mkdocs, with usage and contact information
  3. A citation CITATION.cff; Example here
  4. Tagged and versioned, stable repository
"},{"location":"OtherHowTos/zenodo/#link-github-account-to-zenodo","title":"Link GitHub account to Zenodo","text":"
  1. Go to Zenodo

  2. Select username in the top right >> Profile. Select `GitHub``

  3. Click Sync Now (top right) to update repos. NOTE: You may have to refresh the page

  4. Toggle the On button on the repo you wish to publish. This will move the pipeline to the Enable Repositories list.

"},{"location":"OtherHowTos/zenodo/#prepare-github-repo","title":"Prepare GitHub Repo","text":"
  1. Go to GitHub and find the repository page.

  2. Select Releases >> Draft a new release

  3. Create a tag, following naming semantics described here

  4. Describe the tag with the following: \"Connecting pipeline to Zenodo\"

"},{"location":"OtherHowTos/zenodo/#update-zenodo-information","title":"Update Zenodo Information","text":"
  1. Go to Zenodo

  2. Select My dashboard >> Edit

  3. Update the following information:

    • Resource Type: Software
    • Title: Full Pipeline Name (ShorthandName) (IE Mouse nEoanTigen pRedictOr (METRO)
    • Creators: Add creators, including ORCID's whenever possible
    • Description: A short description of the main features of the pipeline
    • Additional Description: If you use this software, please cite it as below.
    • Keywords and subjects: Add several keywords related to the pipeline
    • Version: add the version used in GitHub
    • Publisher: Zenodo
    • Related works: \"Is original form of\" \"github website\" URL
"},{"location":"OtherHowTos/zenodo/#add-doi-citation-to-github","title":"Add DOI, citation to GitHub","text":"
  1. Go to Zenodo

  2. Select username in the top right >> Profile. Select `GitHub``

  3. Click Sync Now (top right) to update repos. NOTE: You may have to refresh the page

  4. Copy the DOI for the repository

  5. Return to the GitHub repository and edit the README of the GitHub repo, adding the DOI link.

  6. Update the CITATION.cff as needed.

  7. Create a new tagged version.

"},{"location":"Rpackage/build_pkg/","title":"Creating a Conda Package from an R Package","text":""},{"location":"Rpackage/build_pkg/#overview","title":"Overview","text":"

To create a package with Conda, you first need to make a new release and tag in the github repo of the R package you would like to create into a Conda Package.

For more information on best practices in R package creation, review this documentation.

Before creating the release on github, please check for proper dependencies listed in the files NAMESPACE and DESCRIPTION.

These files should have the same list of dependencies, and the version numbers for dependencies can be specified in the DESCRIPTION file. The DESCRIPTION file must be edited manually, while the NAMESPACE file should not be edited manually, but rather created automatically using the document() function.

The DESCRIPTION file must also be correctly formatted. For more information, see the following website.

"},{"location":"Rpackage/build_pkg/#download-the-r-package-release-from-github","title":"Download the R package release from Github","text":"

To download the most recent release from the most recent tag on Github, activate Conda then use Conda skeleton to pull the correct URL. In the example below, replace $githubURL with the URL to your R package's github repo.

conda activate \n\nconda skeleton cran $githubURL\n

A folder is then created for the downloaded release. Ror example running the following:

conda skeleton cran https://github.com/NIDAP-Community/DSPWorkflow\n

Creates the folder

r-dspworkflow\n

Within this newly created folder is a file named meta.yaml. You will need to edit this file to include the channels and edit any information on the the package version number or dependency version numbers.

Here is an example of the top of the meta.yaml file with the channels section added:

{% set version = '0.9.5.2' %}\n\n{% set posix = 'm2-' if win else '' %}\n{% set native = 'm2w64-' if win else '' %}\n\npackage:\n  name: r-dspworkflow\n  version: {{ version|replace(\"-\", \"_\") }}\n\nchannels:\n  - conda-forge\n  - bioconda\n  - default\n  - file://rstudio-files/RH/ccbr-projects/Conda_package_tutorial/local_channel/channel\n\nsource:\n\n  git_url: https://github.com/NIDAP-Community/DSPWorkflow\n  git_tag: 0.9.5\n\nbuild:\n  merge_build_host: True  # [win]\n  # If this is a new build for the same version, increment the build number.\n  number: 0\n  # no skip\n\n  # This is required to make R link correctly on Linux.\n  rpaths:\n    - lib/R/lib/\n    - lib/\n\n    # Suggests: testthat (== 3.1.4)\nrequirements:\n  build:\n    - {{ posix }}filesystem        # [win]\n    - {{ posix }}git\n    - {{ posix }}zip               # [win]\n

Here is an example of the sections for specifying dependency versions from the meta.yaml file:

  host:\n    - r-base =4.1.3=h2f963a2_5\n    - bioconductor-biobase =2.54.0=r41hc0cfd56_2\n    - bioconductor-biocgenerics =0.40.0=r41hdfd78af_0\n    - bioconductor-geomxtools =3.1.1=r41hdfd78af_0\n    - bioconductor-nanostringnctools =1.2.0\n    - bioconductor-spatialdecon =1.4.3\n    - bioconductor-complexheatmap =2.10.0=r41hdfd78af_0\n    - r-cowplot =1.1.1=r41hc72bb7e_1\n    - r-dplyr =1.0.9=r41h7525677_0\n    - r-ggforce =0.3.4=r41h7525677_0\n    - r-ggplot2 =3.3.6=r41hc72bb7e_1\n    - r-gridextra =2.3=r41hc72bb7e_1004\n    - r-gtable =0.3.0=r41hc72bb7e_3\n    - r-knitr =1.40=r41hc72bb7e_1\n    - r-patchwork =1.1.2=r41hc72bb7e_1\n    - r-reshape2 =1.4.4=r41h7525677_2\n    - r-scales =1.2.1=r41hc72bb7e_1\n    - r-tibble =3.1.8=r41h06615bd_1\n    - r-tidyr =1.2.1=r41h7525677_1\n    - r-umap =0.2.9.0=r41h7525677_1\n    - r-rtsne =0.16=r41h37cf8d7_1\n    - r-magrittr =2.0.3=r41h06615bd_1\n    - r-rlang =1.1.0=r41h38f115c_0\n\n  run:\n    - r-base =4.1.3=h2f963a2_5\n    - bioconductor-biobase =2.54.0=r41hc0cfd56_2\n    - bioconductor-biocgenerics =0.40.0=r41hdfd78af_0\n    - bioconductor-geomxtools =3.1.1=r41hdfd78af_0\n    - bioconductor-nanostringnctools =1.2.0\n    - bioconductor-spatialdecon =1.4.3\n    - bioconductor-complexheatmap =2.10.0=r41hdfd78af_0\n    - r-cowplot =1.1.1=r41hc72bb7e_1\n    - r-dplyr =1.0.9=r41h7525677_0\n    - r-ggforce =0.3.4=r41h7525677_0\n    - r-ggplot2 =3.3.6=r41hc72bb7e_1\n    - r-gridextra =2.3=r41hc72bb7e_1004\n    - r-gtable =0.3.0=r41hc72bb7e_3\n    - r-knitr =1.40=r41hc72bb7e_1\n    - r-patchwork =1.1.2=r41hc72bb7e_1\n    - r-reshape2 =1.4.4=r41h7525677_2\n    - r-scales =1.2.1=r41hc72bb7e_1\n    - r-tibble =3.1.8=r41h06615bd_1\n    - r-tidyr =1.2.1=r41h7525677_1\n    - r-umap =0.2.9.0=r41h7525677_1\n    - r-rtsne =0.16=r41h37cf8d7_1\n    - r-magrittr =2.0.3=r41h06615bd_1\n    - r-rlang =1.1.0=r41h38f115c_0\n

In the above example, each of the dependencies has been assigned a conda build string, so that when conda builds a conda package, it will only use that specific build of the dependency from the listed conda channels. The above example is very restrictive, the dependencies can also be listed in the \"meta.yaml\" file to be more open--it will choose a conda build string that fits in with the other resolved dependency build strings based on what is available in the channels.

Also note that the \"host\" section matches the \"run\" section.

Here is some examples of a more open setup for these dependencies:

  host:\n    - r-base >=4.1.3\n    - bioconductor-biobase >=2.54.0\n    - bioconductor-biocgenerics >=0.40.0\n    - bioconductor-geomxtools >=3.1.1\n    - bioconductor-nanostringnctools >=1.2.0\n    - bioconductor-spatialdecon =1.4.3\n    - bioconductor-complexheatmap >=2.10.0\n    - r-cowplot >=1.1.1\n    - r-dplyr >=1.0.9\n    - r-ggforce >=0.3.4\n    - r-ggplot2 >=3.3.6\n    - r-gridextra >=2.3\n    - r-gtable >=0.3.0\n    - r-knitr >=1.40\n    - r-patchwork >=1.1.2\n    - r-reshape2 >=1.4.4\n    - r-scales >=1.2.1\n    - r-tibble >=3.1.8\n    - r-tidyr >=1.2.1\n    - r-umap >=0.2.9.0\n    - r-rtsne >=0.16\n    - r-magrittr >=2.0.3\n    - r-rlang >=1.1.0\n
"},{"location":"Rpackage/build_pkg/#build-the-conda-package","title":"Build the Conda package","text":"

When the meta.yaml has been prepared, you can now build the Conda package. To do so, run the command, replacing

  • $r-package with the name of the R package folder that was created after running conda skeleton (the folder where the meta.yaml is located).
  • $build_log_name.log with the name for the log file, such as the date, time, and initials.
conda-build $r-package 2>&1|tee $build_log_name.log\n

Example

conda-build r-dspworkflow 2>&1|tee 05_12_23_330_nc.log\n

The log file will list how conda has built the package, including what dependencies version numbers and corresponding build strings were used to resolve the conda environment. These dependencies are what we specified in the \"meta.yaml\" file. The log file will be useful troubleshooting a failed build.

Be aware, the build can take anywhere from several minutes to an hour to complete, depending on the size of the package and the number of dependencies.

The conda package will be built as a tar.bz2 file.

"},{"location":"Rpackage/common_issues/","title":"Creating a Conda Package from an R Package","text":""},{"location":"Rpackage/common_issues/#package-dependency-issues","title":"Package Dependency Issues","text":"

An important consideration for Conda builds is the list of dependencies, specified versions, and compatibility with each of the other dependencies.

If the meta.yaml and DESCRIPTION file specify specific package versions, Conda's ability to resolve the Conda environment also becomes more limited.

For example, if the Conda package we are building has the following requirements:

Dependency A version == 1.0\nDependency B version >= 2.5\n

And the Dependencies located in our Conda channel have the following dependencies:

Dependency A version 1.0\n  - Dependency C version == 0.5\n\nDependency A version 1.2\n- Dependency C version >= 0.7\n\nDependency B version 2.7\n  - Dependency C version >= 0.7\n

As you can see, the Conda build will not be able to resolve the environment because Dependency A version 1.0 needs an old version of Dependency C, while Dependency B version 2.7 needs a newer version.

In this case, if we changed our package's DESCRIPTION and meta.yaml file to be:

Dependency A version >= 1.0\nDependency B version >= 2.5\n

The conda build will be able to resolve. This is a simplified version of a what are more often complex dependency structures, but it is an important concept in conda package building that will inevitably arise as a package's dependencies become more specific.

To check on the versions of packages that are available in a Conda channel, use the command:

conda search $dependency\n

Replace $dependency with the name of package you would like to investigate. There are more optional commands for this function which can be found here

To check the dependencies of packages that exist in your Conda cache, go to the folder specified for your conda cache (that we specified earlier). In case you need to find that path you can use:

conda info

Here there will be a folder for each of the packages that has been used in a conda build (including the dependencies). In each folder is another folder called \"info\" and a file called \"index.json\" that lists information, such as depends for the package.

Here is an example:

``` cat /rstudio-files/ccbr-data/users/Ned/conda-cache/r-ggplot2-3.3.6-r41hc72bb7e_1/info/index.json

{ \"arch\": null, \"build\": \"r41hc72bb7e_1\", \"build_number\": 1, \"depends\": [ \"r-base >=4.1,<4.2.0a0\", \"r-digest\", \"r-glue\", \"r-gtable >=0.1.1\", \"r-isoband\", \"r-mass\", \"r-mgcv\", \"r-rlang >=0.3.0\", \"r-scales >=0.5.0\", \"r-tibble\", \"r-withr >=2.0.0\" ], \"license\": \"GPL-2.0-only\", \"license_family\": \"GPL2\", \"name\": \"r-ggplot2\", \"noarch\": \"generic\", \"platform\": null, \"subdir\": \"noarch\", \"timestamp\": 1665515494942, \"version\": \"3.3.6\" } ```

If you would like to specify an exact package to use in a conda channel for your conda build, specify the build string in your \"meta.yaml\" file. In the above example for ggplot version 3.3.6, the build string is listed in the folder name for package as well as in the index.json file for \"build: \"r41hc72bb7e_1\".

"},{"location":"Rpackage/setup/","title":"Creating a Conda Package from an R Package","text":""},{"location":"Rpackage/setup/#set-up-conda-tools-installation-if-needed","title":"Set up Conda Tools, installation (if needed)","text":"
  • You will first need to set up Conda in order to use the Conda tools for creating your Conda package.

  • The documentation for getting started can be found here, including installation guidelines.

"},{"location":"Rpackage/setup/#set-up-conda-cache","title":"Set up Conda cache","text":"

In a space shared with other users that may use Conda, your personal Conda cache needs to be specified. To edit how your cache is saved perform the following steps:

1) Create a new directory where you would like to store the conda cache called 'conda-cache'

mkdir conda/conda-cache\n

2) In your home directory, create the file .condarc

touch ~/.condarc\n

3) Open the new file .condarc and add the following sections:

  • pkgs_dirs

  • envs_dirs

  • conda-build

  • channels

In each section you will add the path to the directories you would like to use for each section.

Example:

kgs_dirs:<br>\n  - /rstudio-files/ccbr-data/users/Ned/conda-cache<br>\nenvs_dirs:<br>\n  - /rstudio-files/ccbr-data/users/Ned/conda-envs<br>\nconda-build:<br>\n    root-dir: /rstudio-files/ccbr-data/users/Ned/conda-bld<br>\n    build_folder: /rstudio-files/ccbr-data/users/Ned/conda-bld\n    conda-build<br>\n  output_folder: /rstudio-files/ccbr-data/users/Ned/conda-bld/conda-output<br>\nchannels:<br>\n  - file://rstudio-files/RH/ccbr-projects/Conda_package_tutorial/local_channel/channel<br>\n  - conda-forge<br>\n  - bioconda<br>\n  - defaults<br>\n
"},{"location":"Rpackage/setup/#check-conda-setup","title":"Check Conda setup","text":"

To check that conda has been setup with the specified paths from .condarc start conda:

conda activate\n

Then check the conda info:

conda info\n
"},{"location":"Tutorials/snakemake/","title":"Snakemake","text":"

Step-by-step guide for setting up and learning to use Snakemake, with examples and use cases

  • https://CCBR.github.io/snakemake_tutorial/
"},{"location":"UCSC/creating_inputs/","title":"Creating Inputs","text":""},{"location":"UCSC/creating_inputs/#generating-inputs","title":"Generating Inputs","text":"

In order to use the genomic broswer features, sample files must be created.

"},{"location":"UCSC/creating_inputs/#individual-sample-files","title":"Individual sample files","text":"

For individual samples, where peak density is to be observed, bigwig formatted files must be generated. If using the CCBR pipelines these are automatically generated as outputs of the pipeline (WORKDIR/results/bigwig). In many cases, scaling or normalization of bigwig is required to visualize multiple samples in comparison with each other. See various deeptools options for details/ideas. If not using CCBR pipelines, example code is provided below for the file generation.

modue load ucsc\n\nfragments_bed=\"/path/to/sample1.fragments.bed\"\nbw=\"/path/to/sample1.bigwig\"\ngenome_len=\"numeric_genome_length\"\nbg=\"/path/to/sample1.bedgraph\"\nbw=\"/path/to/sample2.bigwig\"\n\n# if using a spike-in scale, the scaling factor should be applied\n# while not required, it is recommended for CUT&RUN experiements\nspikein_scale=\"spike_in_value\"\n\n# create bed file\nbedtools genomecov -bg -scale $spikein_scale -i $fragments_bed -g $genome_len > $bg\n\n# create bigwig file\nbedGraphToBigWig $bg $genome_len $bw\n

"},{"location":"UCSC/creating_inputs/#contrasts-between-samples","title":"Contrasts between samples","text":"

For contrasts, where peak differences are to be observed, bigbed formatted files must be generated. If using the CCBR/CARLISLE pipeline these are automatically generated as outputs of the pipeline (WORKDIR/results/peaks/contrasts/contrast_id/). If not using this pipeline, example code is provided below for the file generation.

module load ucsc\n\nbed=\"/path/to/sample1_vs_sample2_fragmentsbased_diffresults.bed\"\nbigbed=\"/path/to/output/sample1_vs_sample2_fragmentsbased_diffresults.bigbed\"\ngenome_len=\"numeric_genome_length\"\n\n# create bigbed file\nbedToBigBed -type=bed9 $bed $genome_len $bigbed\n

"},{"location":"UCSC/creating_inputs/#sharing-data","title":"Sharing data","text":"

For all sample types, data must be stored on a shared directory. It is recommended that symlnks be created from the source location to this shared directory to ensure that minial disc space is being used. Example code for creating symlinks is provided below.

"},{"location":"UCSC/creating_inputs/#single-sample","title":"single sample","text":"
# single sample\n## set source file location\nsource_loc=\"/WORKDIR/results/bigwig/sample1.bigwig \"\n\n## set destination link location\nlink_loc=\"/SHAREDDIR/bigwig/sample1.bigwig\"\n\n## create hard links\nln $source_loc $link_loc\n
"},{"location":"UCSC/creating_inputs/#contrast-sample","title":"contrast sample","text":"
# contrast\n## set source file location\nsource_loc=\"WORKDIR/results/peaks/contrasts/sample1_vs_sample2/sample1_vs_sample2_fragmentsbased_diffresults.bigbed \"\n\n## set destination link location\nlink_loc=\"/SHAREDDIR/bigbed/sample1_vs_sample2.bigbed\"\n\n## create hard links\nln $source_loc $link_loc\n

Once the links have been generated, the data folder must be open to read and write access.

## set destination link location\nlink_loc=\"/SHAREDDIR/bigbed/\"\n\n# open dir\nchmod -R a+rX $link_loc\n

"},{"location":"UCSC/creating_track_info/","title":"Generating Track information","text":""},{"location":"UCSC/creating_track_info/#single-samples","title":"Single samples","text":"

It's recommended to create a text file of all sample track information to ease in editing and submission to the UCSC browser website. A single line of code is needed for each sample which will provide the track location, sample name, description of the sample, whether to autoscale the samples, max height of the samples, view limits, and color. An example is provided below.

track type=bigWig bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigwig/${complete_sample_id}.bigwig name=${sample_id} description=${sample_id} visibility=full autoScale=off maxHeightPixels=128:30:1 viewLimits=1:120 color=65,105,225\n

Users may find it helpful to create a single script which would create this text file for all samples. An example of this is listed below, which assumes that input files were generated using the CARLISLE pipeline. It can be edited to adapt to other output files, as needed.

Generally, each \"track\" line should have at least the following key value pairs: - name : label for the track - description : defines the center lable displayed - type : BAM, BED, bigBed, bigWig, etc. - bigDataUrl : URL of the data file - for other options see here

"},{"location":"UCSC/creating_track_info/#inputs","title":"Inputs","text":"
  • samples_list.txt: a single column text file with sampleID's
  • track_dir: path to the linked files
  • track_output: path to output file
  • peak_list: all peak types to be included
  • method_list: what method to be included
  • dedupe_list: type of duplication to be included
# input arguments\nsample_list_input=/\"path/to/samples.txt\"\ntrack_dir=\"/path/to/shared/dir/\"\ntrack_output=\"/path/to/output/file/tracks.txt\npeak_list=(\"norm.relaxed.bed\" \"narrowPeak\" \"broadGo_peaks.bed\" \"narrowGo_peaks.bed\")\nmethod_list=(\"fragmentsbased\")\ndedup_list=(\"dedup\")\n\n# read sample file\nIFS=$'\\n' read -d '' -r -a sample_list < $sample_list_input\n\nrun_sample_tracks (){\n    sample_id=$1\n    dedup_id=$2\n\n    # sample name\n    # eg siNC_H3K27Ac_1.dedup.bigwig\n    complete_sample_id=\"${sample_id}.${dedup_id}\"\n\n    # set link location\n    link_loc=\"${track_dir}/bigwig/${complete_sample_id}.bigwig\"\n\n    # echo track info\n    echo \"track type=bigWig bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigwig/${complete_sample_id}.bigwig name=${sample_id} description=${sample_id} visibility=full autoScale=off maxHeightPixels=128:30:1 viewLimits=1:120 color=65,105,225\" >> $track_output\n}\n\n# iterate through samples\n# at the sample level only DEDUP matters\nfor sample_id in ${sample_list[@]}; do\n    for dedup_id in ${dedup_list[@]}; do\n        run_sample_tracks $sample_id $dedup_id\n    done\ndone\n
"},{"location":"UCSC/creating_track_info/#contrast-samples","title":"Contrast samples","text":"

It's recommended to create a text file of all sample track information to ease in editing and submission to the UCSC browser website. A single line of code is needed for each contrast which will provide the track location, contrast name, file type, and whether to color the sample. An example is provided below.

track name=${sample_id}_${peak_type} bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigbed/${complete_sample_id}_fragmentsbased_diffresults.bigbed type=bigBed itemRgb=On\n

Users may find it helpful to create a single script which would create this text file for all contrasts. An example of this is listed below, which assumes that input files were generated using the CARLISLE pipeline. It can be edited to adapt to other output files, as needed.

"},{"location":"UCSC/creating_track_info/#inputs_1","title":"Inputs","text":"
  • samples_list.txt: a single column text file with sampleID's
  • track_dir: path to the linked files
  • track_output: path to output file
  • peak_list: all peak types to be included
  • method_list: what method to be included
  • dedupe_list: type of duplication to be included
# input arguments\nsample_list_input=/\"path/to/samples.txt\"\ntrack_dir=\"/path/to/shared/dir/\"\ntrack_output=\"/path/to/output/file/tracks.txt\npeak_list=(\"norm.relaxed.bed\" \"narrowPeak\" \"broadGo_peaks.bed\" \"narrowGo_peaks.bed\")\nmethod_list=(\"fragmentsbased\")\ndedup_list=(\"dedup\")\n\n# read sample file\nIFS=$'\\n' read -d '' -r -a deg_list < $deg_list_input\n\nrun_comparison_tracks (){\n    peak_type=$1\n    method_type=$2\n    dedup_type=$3\n    sample_id=$4\n\n    # sample name\n    # eg siSmyd3_2m_Smyd3_0.25HCHO_500K_vs_siNC_2m_Smyd3_0.25HCHO_500K__no_dedup__norm.relaxed\n    complete_sample_id=\"${sample_id}__${dedup_type}__${peak_type}\"\n\n    # set link location\n    link_loc=\"${track_dir}/bigbed/${complete_sample_id}_${method_type}_diffresults.bigbed\"\n\n    # echo track info\n    echo \"track name=${sample_id}_${peak_type} bigDataUrl=https://hpc.nih.gov/~CCBR/ccbr1155/${dir_loc}/bigbed/${complete_sample_id}_fragmentsbased_diffresults.bigbed type=bigBed itemRgb=On\" >> $track_info\n}\n\n# iterate through samples / peaks / methods / dedup\nfor sample_id in ${deg_list[@]}; do\n    for peak_id in ${peak_list[@]}; do\n        for method_id in ${method_list[@]}; do\n            for dedup_id in ${dedup_list[@]}; do\n                run_comparison_tracks $peak_id $method_id $dedup_id $sample_id\n            done\n        done\n    done\ndone\n
"},{"location":"UCSC/creating_track_info/#other-tips","title":"Other tips","text":"

Users can also change the colors of the tracks using standard HTML color features. Common colors used are provided below:

Red=205,92,92\nBlue=65,105,225\nBlack=0,0,0\n

"},{"location":"UCSC/creating_tracks/","title":"Creating Tracks","text":"

Biowulf/Helix hosts its own instance of the UCSC Genome Browser which is behind the NIH firewall.

"},{"location":"UCSC/creating_tracks/#generating-new-tracks","title":"Generating New Tracks","text":"
  1. Login to VPN
  2. Login to the UCSC Browser website
  3. Select \"My Data > Custom Tracks\"
  4. Select \"Add Custom Tracks\"
  5. Paste the track data generated in Creating Track Info into the text box
  6. Select \"Submit\"
  7. Review the track information. The column \"Error\" should be empty. If there is an error then a hyperlink will display \"Show\" although this often does not contain helpful error information.
  8. After troubleshooting any errors select \"Go\"
  9. Use the features at the bottom of the page to alter views and/or add additional track information
  10. Select \"My Data > My Sessions\"
  11. Under \"Save current settings as named session:\" enter a descriptive name of the session
  12. Select \"Submit\"
  13. This will move the descriptive name entered into the \"session name\" list
  14. Select the descriptve name, view your track information as saved
  15. Copy the hyperlink for this session and share as needed
"},{"location":"UCSC/creating_tracks/#editing-a-previous-tracks","title":"Editing a Previous Tracks","text":"
  1. Login to VPN
  2. Login to the UCSC Browser website
  3. Select \"My Data > My Sessions\"
  4. Select the descriptve name of the session you'd like to edit
  5. Edit the tracks as needed:
    • If wanting to remove or add tracks, then select \"My Data > Custom Tracks\"; follow steps 5-8 above.
    • If wanting to edit the view of the tracks, follow step 9 above.
  6. Select \"My Data > My Sessions\"
  7. Under \"Save current settings as named session:\" enter a new descriptive name OR the previous name of the session if you'd like to overwrite it
  8. Select \"Submit\"
  9. This will move the descriptive name entered into the \"session name\" list
  10. Select the descriptve name, view your track information as saved
  11. Copy the hyperlink for this session and share as needed

TIP: Unindexed file formats like bed and gtf take significantly longer to load in the genome Browser and it is recommended to convert them to indexed formats like bigBed and bigWig prior to adding them to your session.

"},{"location":"UCSC/overview/","title":"Overview","text":"

The UCSC Genome Browser allows for visualization of genomic data in an interactive and shareable format. User's must create accounts with their NIH credentials, and have an active Biowulf account to create the tracks. In addition users have to be connect to VPN in order to view and create the tracks. Once bigwig files are generated and stored in a shared data location, genomic tracks can be edited, and permanent links created, accessible for collaborators to view.

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..ed7cfd5 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,118 @@ + + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + + None + 2024-01-08 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..094eb559544daac218be1eb2ff9e53984eaf510b GIT binary patch literal 213 zcmV;`04o0N2k_meAnXd74z@wuI(BLw zz$jG`1nbe-zJ2i{jjzz;ZsGWIx!;N?-@PF(HG+1wplQM>QMPuCwrxRg*K?fHQbyuA z8c?2uVG9NAydO@CP1BTs_NuQ2NZi;msJn0hwuOu*M=B!{YF@B*O9|s@d2v<=Hh24n z3ViPxneprp^EBpp7}>JjSlv~&RrgUnWK(JL5p0*NBKwhuBaS%Yh$D_T;)o;uANX>F PkGK2+@u61~s0#o9uq9