From 473a54bf1dd6b5f32d881d72e55438294d474e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alba=20Refoyo=20Mart=C3=ADnez?= Date: Fri, 3 May 2024 15:02:29 +0200 Subject: [PATCH] updates practical --- _quarto.yml | 3 + _site/develop/03_DOD.html | 5 +- _site/develop/04_metadata.html | 291 +++--- _site/develop/05_VC.html | 23 +- _site/develop/06_pipelines.html | 3 +- _site/develop/examples/NGS_OS_FAIR.html | 38 +- _site/develop/examples/mkdocs_pages.html | 832 ++++++++++++++++++ _site/develop/images/github_pages_quarto.png | Bin 0 -> 183828 bytes _site/develop/practical_workshop.html | 583 +++++++++--- _site/develop/scripts/shiny_sqlite_advanced.r | 169 ++++ _site/index.html | 15 +- _site/practical_workflows.html | 10 +- _site/search.json | 59 +- develop/03_DOD.qmd | 4 +- develop/04_metadata.qmd | 246 ++---- develop/05_VC.qmd | 19 +- develop/06_pipelines.qmd | 1 + develop/assets/other_metadata.txt | 34 - develop/examples/mkdocs_pages.qmd | 45 + develop/images/github_pages_quarto.png | Bin 0 -> 183828 bytes develop/practical_workshop.qmd | 342 +++++-- develop/scripts/shiny_sqlite_advanced.R | 169 ++++ index.qmd | 3 + practical_workflows.qmd | 6 +- 24 files changed, 2304 insertions(+), 596 deletions(-) create mode 100644 _site/develop/examples/mkdocs_pages.html create mode 100644 _site/develop/images/github_pages_quarto.png create mode 100644 _site/develop/scripts/shiny_sqlite_advanced.r delete mode 100644 develop/assets/other_metadata.txt create mode 100644 develop/examples/mkdocs_pages.qmd create mode 100644 develop/images/github_pages_quarto.png create mode 100644 develop/scripts/shiny_sqlite_advanced.R diff --git a/_quarto.yml b/_quarto.yml index 03108dcf..f99557b5 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -42,6 +42,9 @@ website: - title: "Use cases" contents: - use_cases.qmd + - section: "General" + contents: + - develop/examples/mkdocs_pages.qmd - section: "NGS data" contents: - develop/examples/NGS_OS_FAIR.qmd diff --git a/_site/develop/03_DOD.html b/_site/develop/03_DOD.html index 17ee3c63..0ac0ee6d 100644 --- a/_site/develop/03_DOD.html +++ b/_site/develop/03_DOD.html @@ -311,7 +311,7 @@

3. Data organization and storage

Modified
-

April 26, 2024

+

April 29, 2024

@@ -724,6 +724,8 @@

Template engine

@@ -742,7 +744,6 @@

Quick tutor

Learn how to create your own template here.

-

We offer workshops on practical RDM for biodata. Keep an eye on the upcoming events on the Sandbox website.

diff --git a/_site/develop/04_metadata.html b/_site/develop/04_metadata.html index 9449ee2d..ae625f14 100644 --- a/_site/develop/04_metadata.html +++ b/_site/develop/04_metadata.html @@ -305,7 +305,7 @@

4. Documentation for biodata

Modified
-

April 26, 2024

+

May 3, 2024

@@ -552,14 +552,26 @@

Con @@ -613,6 +625,7 @@

Tables as databasesYAML metadata files associated with each project

Click on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration.

+

You can find a thorough guided exercise in the practical material - Exercise 4.

  • Commit and push changes when you are done with your modifications

    • @@ -934,9 +960,9 @@

      3. Naming conventions

      4. Create a catalog of your data folder

      -

      The next step is to collect all the NGS datasets that you have created in the manner explained above. Since your folders all should contain the metadata.yml file in the same place with the same metadata, it should be very easy to iteratively go through all the folders and merge all the metadata.yml files into a one single table. This table can be then browsed easily with Microsoft Excel, for example. If you are interested in making a Shiny app or Python Panel tool to interactively browse the catalog, check out this lesson.

      +

      The next step is to collect all the datasets that you have created in the manner explained above. Since your folders all should contain the metadata.yml file in the same place with the same metadata, it should be very easy to iteratively go through all the folders and merge all the metadata.yml files into a one single table. he table can be easily viewed in your terminal or even with Microsoft Excel.

      -
      +
      @@ -945,65 +971,357 @@

      4. Cr

      -
      +
      -

      We will make a small script in R (or you can make one with Python) that recursively goes through all the folders inside an input path (like your Assays folder), fetches all the metadata.yml files, and merges them. Finally, it will write a TSV file as an output.

      +

      We will make a small script in R (or you can make one with Python) that recursively goes through all the folders inside an input path (like your Assays folder), fetches all the metadata.yml files, merges them and writes a TSV file as an output.

      1. Create a folder called dataset and change directory cd dataset
      2. -
      3. Fork this repository: a Cookiecutter template designed for NGS datasets. While you are welcome to create your own template from scratch, we recommend using this one to save time.
      4. -
      5. Run the cookiecutter cc-data-template command at least twice to create multiple datasets or projects. Use different values each time to simulate various scenarios (do this in the dataset directory that you have previously created). Execute the script below using R (or create your own script in Python). Adjust the folder_path variable so that it matches the path to the Assays folder. The resulting table will be saved in the same folder_path.
      6. +
      7. Fork this repository: a Cookiecutter template designed for NGS datasets.While you are welcome to create your own template from scratch, we recommend using this one to save time.
      8. +
      9. Run the cookiecutter cc-data-template command at least twice to create multiple datasets or projects. Use different values each time to simulate various scenarios (do this in the dataset directory that you have previously created).
      10. +
      11. Execute the script below using R (or create your own script in Python). Adjust the folder_path variable so that it matches the path to the Assays folder. The resulting table will be saved in the same folder_path.
      12. Open your database_YYYYMMDD.tsv table in a text editor from the command-line, or view it in Excel for better visualization.
      -
      
      -library(yaml)
      -library(dplyr)
      -library(lubridate)
      -
      -# Function to read a YAML file and transform it into a dataframe format.
      -read_yaml <- function(file_path) {
      -  # Read the YAML file and convert it to a data frame
      -  df <- yaml::yaml.load_file(file_path) %>% as.data.frame(stringsAsFactors = FALSE)
      -  
      -  # Return the data frame
      -  return(df)
      +
        +
      • Solution A. From a TSV
      • +
      +
      + +
      +
      +
      +
      +
      # R version 4.3.2
      +# RScript to read all yaml files in directory and save the metadata into a dataframe
      +quiet <- function(package_name) {
      +  # Suppress warnings and messages while checking and installing the package
      +  suppressMessages(suppressWarnings({
      +    # Check if the package is available and load it
      +    if (!requireNamespace(package_name, quietly = TRUE)) {
      +      install.packages(package_name)
      +    }
      +    # Load the package
      +    library(package_name, character.only = TRUE)
      +  }))
       }
       
      -# Function to recursively fetch metadata.yml files
      -get_metadata <- function(folder_path) {
      -  file_list <- list.files(path = folder_path, pattern = "metadata\\.yml$", recursive = TRUE, full.names = TRUE)
      -
      -  metadata_list <- lapply(file_list, read_yaml)
      -  
      -  # Combine the list of data frames into a single data frame using dplyr::bind_rows()
      -  combined_metadata <- bind_rows(metadata_list)
      -
      -  return(combined_metadata)
      -}
      -
      -# Specify the folder path
      -folder_path <- "/path/to/your/folder"
      -
      -# Fetch metadata from the specified folder
      -metadata <- get_metadata(folder_path)
      +# Check and install necessary libraries
      +quiet("yaml")
      +quiet("dplyr")
      +quiet("lubridate")
      +
      +
      +read_yaml <- function(file_path) {
      +  # Read the YAML file and convert it to a data frame
      +  df <- yaml::yaml.load_file(file_path) %>% as.data.frame(stringsAsFactors = FALSE)
      +  
      +  # Return the data frame
      +  return(df)
      +}
      +
      +# Function to recursively fetch metadata.yml files
      +get_metadata <- function(folder_path) {
      +  file_list <- list.files(path = folder_path, pattern = "metadata\\.yml$", recursive = TRUE, full.names = TRUE)
       
      -# Save the data frame as a TSV file
      -output_file <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".tsv")
      -write.table(metadata, file = output_file, sep = "\t", quote = FALSE, row.names = FALSE)
      -
      -# Print confirmation message
      -cat("Database saved as", output_file, "\n")
      + metadata_list <- lapply(file_list, read_yaml) + + # Combine the list of data frames into a single data frame using dplyr::bind_rows() + combined_metadata <- bind_rows(metadata_list) + + return(combined_metadata) +} + +# Specify the folder path +folder_path <- "./" #/path/to/your/folder + +# Fetch metadata from the specified folder +df <- get_metadata(folder_path) + +# Save the data frame as a TSV file +output_file <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".tsv") +write.table(df, file = output_file, sep = "\t", quote = FALSE, row.names = FALSE) + +# Print confirmation message +cat("Database saved as", output_file, "\n")
      +
      +
      +
      +
      +
      +

      Exercise 4, option B: create a SQLite database

      +

      Alternatively, create a SQLite database from a metadata. If you opt for this option in the exercise, you must still complete the first three steps outlined above. Read more from the RSQLite documentation.

      +
        +
      • Solution B. SQLite database
      • +
      +
      + +
      +
      +
      +
      +
      print("Assuming the libraries from Exercise 4 are already loaded and a dataframe has been generated from the YAML files...")
      +
      +# check_and_install() form Exercise 4, and load the other packages. 
      +quiet("DBI")
      +quiet("RSQLite")
      +
      +# Initialize a temporary in memory database and copy the data.frame into it
      +
      +db_file_path <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".sqlite")
      +con <- dbConnect(RSQLite::SQLite(), db_file_path)
      +
      +dbWriteTable(con, "metadata", df,  overwrite=TRUE) #row.names = FALSE,append =
      +
      +# Print confirmation message
      +cat("Database saved as", db_file_path, "\n")
      +
      +# Close the database connection
      +dbDisconnect(con)
      +
      +
      +
      +
      +
      +
      +

    + + + +
    +

    Shiny apps

    +

    To get the most out of your metadata file and the ones from other colleagues, you can combine them and explore them by creating an interactive catalog browser. You can create interactive web apps straight from R or Python. Whether you have generated a tabulated-file or a sqlite database, browse through the metadata using Shiny. Shiny apps are perfect for researchers because they enable you to create interactive visualizations and dashboards with dynamic data inputs and outputs without needing extensive web development knowledge. Shiny provides a variety of user interface components such as forms, tables, graphs, and maps to help you organize and present your data effectively. It also allows you to filter, sort, and segment data for deeper insights.

    +
    +
    +
    + +
    +
    +Tip +
    +
    +
    +
      +
    • For R Enthusiasts
    • +
    +

    Explore demos from the R Shiny community to kickstart your projects or for inspiration.

    +
      +
    • For python Enthusiasts
    • +
    +

    Shiny for Python provides live, interactive code throughout its entire tutorial. Additionally, it offers a great tool called Playground, where you can code and test your own app to explore how different features render.

    +
    +
    +
    +
    +
    + +
    +
    +Exercise 5: Skill Booster, build an interactive catalog browser +
    +
    +
    +
    +
    +
    +
    +

    Build an interactive web app straight from R or Python. Below, you will find an example of an R shiny app. In either case, you will need to define a user interface (UI) and a server function. The UI specifies the layout and appearance of the app, including input controls and output displays. The server function contains the app’s logic, handling data manipulation, and responding to user interactions. Once you set up the UI and server, you can launch the app!

    +

    Here’s the UI and server function structure for an R Shiny app:

    +
    # Don't forget to load shiny and DT libraries!
    +
    +# Specify the layout
    +ui <- fluidPage(
    +    titlePanel(...)
    +    # Define the appearance of the app
    +    sidebarLayout(
    +        sidebarPanel(...)
    +        mainPanel(...)
    +    )
    +)
    +
    +server <- function(input, output, session) {
    +    # Define a reactive expression for data based on user inputs
    +    data <- reactive({
    +        req(input$dataInput)  # Ensure data input is available
    +        # Load or manipulate data here
    +    })
    +
    +    # Define an output table based on data
    +    output$dataTable <- renderTable({
    +        data()  # Render the data as a table
    +    })
    +
    +    # Observe a button click event and perform an action
    +    observeEvent(input$actionButton, {
    +        # Perform an action when the button is clicked
    +    })
    +
    +    # Define cleanup tasks when the app stops
    +    onStop(function() {
    +        # Close connections or save state if necessary
    +    })
    +}
    +# Run the app
    +shinyApp(ui, server)
    +

    If you need more assistance, take a look at the code below (Hint).

    +
    + +
    +
    +
    +
    +
    # R version 4.3.2
    +print("Assuming the libraries from Exercise 4 are already loaded and a dataframe has been generated from the YAML files...")
    +
    +# check_and_install() form Exercise 4. 
    +quiet("shiny")
    +quiet("DT")
    +
    +# UI
    +ui <- fluidPage(
    +  titlePanel("TSV File Viewer"),
    +  
    +  sidebarLayout(
    +    sidebarPanel(
    +      fileInput("file", "Choose a TSV file", accept = c(".tsv")),
    +      selectInput("filter_column", "Filter by Column:", choices = c("n_samples", "technology"), selected = "technology"),
    +      textInput("filter_value", "Filter Value:", value = ""),
    +      # if only numbers, numericInput()
    +      radioButtons("sort_order", "Sort Order:", choices = c("Ascending", "Descending"), selected = "Ascending")
    +    ),
    +    
    +    mainPanel(
    +      DTOutput("table")
    +    )
    +  )
    +)
    +
    +# Server
    +server <- function(input, output) {
    +  
    +  data <- reactive({
    +    req(input$file)
    +    df <- read.delim(input$file$datapath, sep = "\t")
    +    print(str(df))
    +
    +    # Filter the DataFrame based on user input
    +    if (input$filter_column != "" && input$filter_value != "") {
    +      # Check if the column is numeric, and filter for value
    +      if (is.numeric(df[[input$filter_column]])) {
    +        df <- df[df[[input$filter_column]] >= as.numeric(input$filter_value), ]
    +      }
    +      # Check if the column is a string
    +      else if (is.character(df[[input$filter_column]])) {
    +        df <- df[df[[input$filter_column]] == input$filter_value, ]
    +      }
    +    }
    +    
    +    # Sort the DataFrame based on user input
    +    sort_order <- if (input$sort_order == "Ascending") TRUE else FALSE
    +    df <- df[order(df[[input$filter_column]], decreasing = !sort_order), ]
    +    df
    +  })
    +  
    +  output$table <- renderDT({
    +    datatable(data())
    +  })
    +}
    +
    +# Run the app
    +shinyApp(ui, server)
    +
    +
    +
    +
    +
    +

    In the optional exercise below, you’ll find a code example for using an SQLite database as input instead of a tabulated file.

    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +Exercise (optional) +
    +
    +
    +
    +
    +
    +
    +

    Once you’ve finished the previous exercise, consider implementing these additional ideas to maximize the utility of your catalog browser.

    +
      +
    • Use SQLite databases as input
    • +
    • Add a functionality to only select certain columns uiOutput("column_select")
    • +
    • Filter columns by value using column_filter_select()
    • +
    • Add multiple tabs using tabsetPanel()
    • +
    • Add buttons to order numeric columns ascending or descending using radioButtons()
    • +
    • Use SQL aggregation functions (e.g., SUM, COUNT, AVG) to perform custom data summaries and calculations.
    • +
    • Add a tab tabPanel() to create a project directory interactively (and fill up the metadata fields), tips: dir.create(), data.frame(), write.table()
    • +
    • Modify existing entries
    • +
    • Visualize results using Cirrocumulus, an interactive visualization tool for large-scale single-cell genomics data.
    • +
    +

    If you need some assistance, take a look at the code below (Hint).

    +
    + +
    +
    +
    +
    +

    Explore an example with advanced features such as a two-tab layout, filtering by numeric values and matching strings, and a color-customized dashboard here.

    +
    +
    +
    +
    +
    -
    -

    5. Version control of your data analysis using Git and GitHub

    -

    Version control is a systematic approach to tracking changes made to a project over time. It provides a structured means of documenting alterations, allowing you to revisit and understand the evolution of your work. In research data management and data analytics, version control is very important and gives you a lot of advantages.

    -

    Git is a distributed version control system that enables developers and researchers to efficiently manage their project’s history, collaborate seamlessly, and ensure data integrity. At its core, Git operates through the following principles and mechanisms: On the other hand, GitHub is a web-based platform that enhances Git’s capabilities by providing a collaborative and centralized hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects.

    +
    +
    +

    5. Version control using Git and GitHub

    +

    Version control involves systematically tracking changes to a project over time, offering a structured way to document revisions and understand the progression of your work. In research data management and data analytics, it plays a critical role and provides numerous benefits.

    +

    Git is a distributed version control system that helps developers and researchers efficiently manage project history, collaborate seamlessly, and maintain data integrity. On the other hand, GitHub is a web-based platform that builds on Git’s functionality by providing a centralized, collaborative hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects.

    @@ -1014,15 +1332,40 @@

    -

    GitHub allows users to create organizations and teams that will collaborate or create repositories under the same umbrella organization. If you would like to create an educational organization in GitHub, you can do so for free! For example, you could create a GitHub account for your lab.

    -

    To create a GitHub organization, follow these instructions

    -

    After you have created the GitHub organization, make sure that you create your repositories under the organization space and not your user!

    +

    GitHub users can create organizations, allowing groups to collaborate or create repositories under the same organization umbrella. You can create an educational organization on Github for free, by setting up a Github account for your lab.

    +

    Follow these instructions to create a GitHub organization.

    +

    Once you’ve established your GitHub organization, be sure to create your repositories within the organization’s space rather than under your personal user account. This keeps your projects centralized and accessible to the entire group. Best practices for managing an organization on GitHub include setting clear access permissions, regularly reviewing roles and memberships, and organizing repositories effectively to keep your projects structured and easy to navigate.

    +

    +
    +
    +

    Setting up a GitHub repository for your project folder

    +

    Version controlling your data analysis folders becomes straightforward once you’ve established your Cookiecutter templates. After you’ve created several folder structures and metadata using your Cookiecutter template, you can manage version control by either converting those folders into Git repositories or copying a folder into an existing Git repository. Both approaches are explained in Lesson 5.

    +
    +
    +
    + +
    +
    +Exercise 6: initialize a repository from an existing folder: +
    +
    +
    +
    +
    +
    +
    +
      +
    1. Initialize the repository: Begin by running the command git init in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See (git init) for more details.
    2. +
    3. Create a remote repository: Once the local repository is initialized, create an empty new repository on GitHub (website or Github Desktop).
    4. +
    5. Connect the remote repository: Add the GitHub repository URL to your local repository using the command git remote add origin <URL>. This associates the remote repository with the name “origin.”
    6. +
    7. Commit changes: If you have files you want to add to your repository, stage them using git add ., then create a commit to save a snapshot of your changes with git commit -m "add local folder".
    8. +
    9. Push to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using git push -u origin main.
    10. +
    +
    +
    +
    -
    -

    Creating a git repo online and copying your project folder

    -

    Version controlling your data analysis folders, a.k.a. Project folder, is very easy once you have set up your Cookiecutter templates. The simplest way of doing this is to first create a remote GitHub repository from the webpage (or from the Desktop app, if you are using it) with a proper project name. Then git clone that repository you just made into your Projects main folder. Then, use cookiecutter to create a project folder template and copy-paste the contents of the folder template to your cloned repo. Remember to fill up your metadata and description files! If you wish, you could already git add, commit, and push the first changes to the folders and continue from there on.

    -

    Go back to the course material lesson 5 and read the differences between converting folders to git repositories and cloning a folder to an existing git repository.

    @@ -1039,48 +1382,80 @@

    GitHub Pages

    -

    Once you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, Rmarkdowns, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we really recommend that you follow the nice tutorial that GitHub has put for you. Nonetheless, we will see the main steps in the exercise below.

    -

    There are many different ways to create your web pages. We recommend using Mkdocs and Mkdocs materials as a framework to create a nice webpage simply. The folder templates that we used as an example in the previous exercise already contain everything you need to start a webpage. Nonetheless, you will need to understand the basics of MkDocs and MkDocs materials to design a webpage to your liking. MkDocs is a static webpage generator that is very easy to use, while MkDocs materials is an extension of the tool that gives you many more options to customize your website. Check out their web pages to get started!

    +

    After creating your repository and hosting it on GitHub, you can now add your data analysis reports—such as Jupyter Notebooks, R Markdown files, or HTML reports—to a GitHub Page website. Setting up a GitHub Page is straightforward, and we recommend following GitHub’s helpful tutorial. However, we will go through the key steps in the exercise below. There are several ways to create your web pages, but we suggest using Quarto as a framework to build a sleek, professional-looking website with ease. The folder templates from the previous exercise already contain the necessary elements to launch a webpage. Familiarizing yourself with the basics of Quarto will help you design a webpage that suits your preferences. Other common options include MkDocs. If you want to use MkDocs instead, click here and follow the instructions.

    +
    +
    +
    + +
    +
    +Tip +
    +
    +
    +

    Here are some useful links to get started with Github Pages:

    + +
    +
    -
    +
    -Exercise 5: make a project folder and publish a data analysis webpage +Exercise 7: Create a Github Page using Quarto
    -
    +
      -
    1. Configure your main GitHub Page and its repo

      -

      The first step is to set up the main GitHub Page site and the repository that will host it. This is very simple, as you will only need to follow these steps. In a Markdown document, outline the primary objectives of the organization and provide an overview of ongoing research projects. After you have created the organization/usernamegithub.io, it is time to configure your Project repository webpage using MkDocs!

    2. -
    3. Start a new project from Cookiecutter or use one from the previous exercise.

      -

      If you use a Project repo from the first exercise, go to the next paragraph. Using Cookiecutter, create a new data analysis project. Remember to fill up your metadata and description files! After you have created the folder, it would be best to initialize a Git repo following the instructions from the previous section.

      -

      Next, link your data of interest (or create a small fake dataset) and make an example of a data analysis notebook/report (this could be just a scatter plot of a random matrix of values). Depending on your setup, you might be using Jupyter Notebooks or Rmarkdowns. The extensions that we have installed using pip allow you to directly add a Jupyter Notebook file to the mkdocs.yml navigation section. On the other hand, if you are using Rmarkdown, you will have to knit your document into either an HTML page or a GitHub document.

      -

      For the purposes of this exercise, we have already included a basic index.md markdown file that can serve as the intro page of your repo, and a jupyter_example.ipynb with some code in it. You are welcome to modify them further to test them out!

    4. -
    5. Use MkDocs to create your webpage

      -

      When you are happy with your files and are ready to publish them, make sure to add, commit, and push the changes to the remote. Then, build up your webpage using MkDocs and the mkdocs gh-deploy command from the same directory where the mkdocs.yml file is. For example, if your mkdocs.yml for your Project folder is in /Users/JARH/Projects/project1_JARH_20231010/mkdocs.yml, do cd /Users/JARH/Projects/project1_JARH_20231010/ and then mkdocs gh-deploy. This requires a couple of changes in your GitHub organization settings.

      -

      Remember to make sure that your markdowns, images, reports, etc., are included in the docs folder and properly set up in the navigation section of your mkdocs.yml file.

      -

      Finally, we only need to set up the GitHub Project repo settings.

    6. -
    7. Publishing your GitHub Page

      -

      Go to your GitHub repo settings and configure the Page section. Since you are using the mkdocs gh-deploy command to publish your site in the gh-pages branch (as explained the the mkdocs documentation), we need to change where GitHub is fetching the website. You will need to configure the settings of this repository in GitHub so that the Page is taken from the gh-pages branch and the root folder.

      -
      -
      -

      -
      GitHub Pages setup
      -
      -
      -
        -
      • Branch should be gh-pages
      • -
      • Folder should be root
      • -
      -

      After a couple of minutes, your webpage should be ready! You should be able to see your webpage through the link provided in the Page section!

    8. +
    9. Head over to GitHub and create a new public repository named username.github.io, where username is your username (or organization name) on GitHub. If the first part of the repository doesn’t exactly match your username, it won’t work, so make sure to get it right.

    10. +
    11. Go to the folder where you want to store your project, and clone the new repository: git clone https://github.com/username/username.github.io (or use Github Desktop)

    12. +
    13. Create a new file named _quarto.yml

      +
      +
      +
      _quarto.yml
      +
      +
      project:
      +    type: website
      +
    14. +
    15. Open the terminal ```{.bash filename=“Terminal”} # Add a .nojekyll file to the root of the repository not to do additional processing of your published site touch .nojekyll #copy NUL .nojekyll for windows

      +

      # Render and push it to Github quarto render git commit -m “Publish site to docs/” git push ```

    16. +
    17. If you do not have a gh-pages, you can create one as follows

      +
      +
      +
      Terminal
      +
      +
      git checkout --orphan gh-pages
      +git reset --hard # make sure all changes are committed before running this!
      +git commit --allow-empty -m "Initialising gh-pages branch"
      +git push origin gh-pages
      +
    18. +
    19. Before attempting to publish you should ensure that the Source branch for your repository is gh-pages and that the site directory is set to the repository root (/)

      +

    20. +
    21. It is important to not check your _site directory into version control, add the output directory of your project to .gitignore

      +
      +
      +
      .gitignore
      +
      +
      /.quarto/
      +/_site/
      +
    22. +
    23. Now is time to publish your website

      +
      +
      +
      .Terminal
      +
      +
      quarto publish gh-pages
      +
    24. +
    25. Once you’ve completed a local publish, add a publish.yml GitHub Action to your project by creating this YAML file and saving it to .github/workflows/publish.yml. Read how to do it here

    -

    Now it is also possible to include this repository webpage in your main webpage organizationgithub.io by including the link of the repo website (https://organizationgithub.io/repo-name) in the navigation section of the mkdocs.yml file in the main organizationgithub.io repo.

    @@ -1110,7 +1485,7 @@

    Zenodo

    Zenodo[https://zenodo.org/] is an open-access digital repository designed to facilitate the archiving of scientific research outputs. It operates under the umbrella of the European Organization for Nuclear Research (CERN) and is supported by the European Commission. Zenodo accommodates a broad spectrum of research outputs, including datasets, papers, software, and multimedia files. This versatility makes it an invaluable resource for researchers across a wide array of domains, promoting transparency, collaboration, and the advancement of knowledge on a global scale.

    Operating on a user-friendly web platform, Zenodo allows researchers to easily upload, share, and preserve their research data and related materials. Upon deposit, each item is assigned a unique Digital Object Identifier (DOI), granting it a citable status and ensuring its long-term accessibility. Additionally, Zenodo provides robust metadata capabilities, enabling researchers to enrich their submissions with detailed contextual information. In addition, it allows you to link your GitHub account, providing a streamlined way to archive a specific release of your GitHub repository directly into Zenodo. This integration simplifies the process of preserving a snapshot of your project’s progress for long-term accessibility and citation.

    -
    +
    @@ -1119,7 +1494,7 @@

    Zenodo

    -
    +
    diff --git a/_site/develop/scripts/shiny_sqlite_advanced.r b/_site/develop/scripts/shiny_sqlite_advanced.r new file mode 100644 index 00000000..99946538 --- /dev/null +++ b/_site/develop/scripts/shiny_sqlite_advanced.r @@ -0,0 +1,169 @@ +#!/usr/bin/env Rscript + +# Author: Alba Refoyo Martinez +# Copyright: Copyright 2024, University of Copenhagen +# Email: gsd818@ku.dk +# License: MIT +# R version: 4.3.2 + +# Define the UI +ui <- fluidPage( + titlePanel("SQLite R Shiny App"), + + # Use tabsetPanel to add multiple tabs + tabsetPanel( + # Existing tab for browsing the SQLite database + tabPanel("Browse Database", + sidebarLayout( + sidebarPanel( + fileInput("db_file", "Select SQLite Database File", accept = c(".sqlite")), + uiOutput("table_select"), + uiOutput("column_filter_select"), + textInput("filter_value", "Find by value", ""), + actionButton("refresh", "Refresh Tables") + # UI output for selecting columns (populated based on the selected table) + # uiOutput("column_select"), + ), + mainPanel( + DTOutput("tableData") + ) + )), + + # New tab for creating a project directory and filling metadata fields + tabPanel("Create Project Directory", + sidebarLayout( + sidebarPanel( + textInput("project_name", "Project Name:", value = "MyProject"), + textInput("metadata_field1", "Metadata Field 1:", value = ""), + textInput("metadata_field2", "Metadata Field 2:", value = ""), + actionButton("create_project", "Create Project") + ), + mainPanel( + textOutput("message") # To display feedback messages + ) + ) + ) + ) +) + +# Define the server +server <- function(input, output, session) { + # Reactive value to hold the database connection + db_conn <- reactiveVal(NULL) + + # Observe changes in the file input + observeEvent(input$db_file, { + # Check if a file is uploaded + if (!is.null(input$db_file)) { + # Get the path to the uploaded file + db_path <- input$db_file$datapath + + # Disconnect any existing connection + if (!is.null(db_conn())) { + dbDisconnect(db_conn()) + } + + # Establish a new connection to the SQLite database + conn <- dbConnect(RSQLite::SQLite(), dbname = db_path) + db_conn(conn) + + # Update the list of tables + updateTableChoices() + } + }) + + # Function to update the list of tables in the database + updateTableChoices <- function() { + # Ensure there's a database connection + if (!is.null(db_conn())) { + # Retrieve the list of tables in the database + tables <- dbListTables(db_conn()) + # Update the choices in the select input + updateSelectInput(session, "table", choices = tables) + } + } + + # Observe the refresh button + observeEvent(input$refresh, { + updateTableChoices() + }) + + # Render the select input for tables + output$table_select <- renderUI({ + selectInput("table", "Select a table", choices = character(0)) + }) + + # Render the select input for columns (choices populated based on the selected table) + # output$column_select <- renderUI({ + # req(input$table) + # # Read data from the selected table + # data <- dbReadTable(db_conn(), input$table) + # # Get the column names from the data + # columns <- names(data) + # # Create a select input for the column choices + # selectInput("columns", "Select columns", choices = columns, multiple = TRUE) + # }) + + + # Render the select input for columns to filter by + output$column_filter_select <- renderUI({ + req(input$table) + data <- dbReadTable(db_conn(), input$table) + columns <- names(data) + selectInput("column_filter", "Filter by column", choices = columns) + }) + + # Display data from the selected table + output$tableData <- renderDT({ + req(input$table) + data <- dbReadTable(db_conn(), input$table) + + # If filtering by columns, ensure they are selected + # req(input$columns) + #filtered_data <- data[, input$columns, drop = FALSE] + + if (!is.null(input$column_filter) && input$filter_value != "") { + filtered_data <- data[data[[input$column_filter]] == input$filter_value, ] + } else { + filtered_data <- data + } + + datatable(filtered_data) + }) + + # Observe the create_project button + observeEvent(input$create_project, { + project_name <- input$project_name + metadata_field1 <- input$metadata_field1 + metadata_field2 <- input$metadata_field2 + + # Define the project directory path + project_dir <- file.path(getwd(), project_name) + + # Check if the directory already exists + if (dir.exists(project_dir)) { + output$message <- renderText("Directory already exists. Please choose a different project name.") + } else { + # Create the directory + dir.create(project_dir) + + # Save the metadata fields to a TSV file in the project directory + metadata <- data.frame(Field1 = metadata_field1, Field2 = metadata_field2) + metadata_file <- file.path(project_dir, "metadata.tsv") + write.table(metadata, metadata_file, sep = "\t", row.names = FALSE, col.names = TRUE) + + # Provide feedback to the user + output$message <- renderText(paste("Project created successfully in", project_dir)) + } + }) + + # Close the database connection when the app is stopped + onStop(function() { + if (!is.null(db_conn())) { + dbDisconnect(db_conn()) + } + }) +} + +# Run the app +shinyApp(ui = ui, server = server) \ No newline at end of file diff --git a/_site/index.html b/_site/index.html index 81afc5b4..f7820231 100644 --- a/_site/index.html +++ b/_site/index.html @@ -164,7 +164,7 @@

    Computational Research Data Management

    Modified
    -

    April 17, 2024

    +

    April 29, 2024

    @@ -180,6 +180,19 @@

    Computational Research Data Management

    # You should hide the navigation if there are no subsections # You should hide the Table of Contents if there are no important titles --> +
    +
    +
    + +
    +
    +Practical RDM workshop +
    +
    +
    +

    We offer workshops on practical RDM for biodata. Keep an eye on the upcoming events on the Sandbox website.

    +
    +

    Research Data Management for biological data

    The course “Research Data Management (RDM) for biological data” is designed to provide participants with foundational knowledge and practical skills in handling the extensive data generated by modern studies, with a focus on Next Generation Sequencing (NGS) data. It emphasizes the importance of Open Science and FAIR principles in managing data effectively. This course covers essential principles and best practices guidelines in data organization, metadata annotation, version control, and data preservation. These principles are explored from a computational perspective, ensuring participants gain hands-on experience in applying them to real-world scenarios in their research labs. Additionally, the course delves into FAIR principles and Open Science, promoting collaboration and reproducibility in research endeavors. By the course’s conclusion, attendees will possess essential tools and techniques to address the data challenges prevalent in today’s NGS research landscape, as well as in other related fields to health and bioinformatics.

    diff --git a/_site/practical_workflows.html b/_site/practical_workflows.html index 0dbf8cf6..14c35da4 100644 --- a/_site/practical_workflows.html +++ b/_site/practical_workflows.html @@ -190,7 +190,7 @@
    Modified
    -

    April 22, 2024

    +

    April 29, 2024

    @@ -242,8 +242,8 @@
    -
    -

    Workflows

    +
    +

    FAIR Workflows

    Data analysis typically involves the use of different tools, algorithms, and scripts. It often requires multiple steps to transform, filter, aggregate, and visualize data. The process can be time-consuming because each tool may demand specific inputs and parameter settings. As analyses become more complex, the importance of reproducible and scalable automated workflow management increases. Workflow management encompasses tasks such as parallelization, resumption, logging, and data provenance.

    If you develop your own software make sure you follow FAIR principles. We highly endorse following these FAIR recommendations and to register your computational workflow here.

    Using workflow managers, you ensure:

    @@ -351,6 +351,9 @@

    Nextflow

    +
    +
    +

    FAIR environments

    Sources

      @@ -359,6 +362,7 @@

      Sources

    • https://bioconda.github.io
    • Köster, Johannes and Rahmann, Sven. “Snakemake - A scalable bioinformatics workflow engine”. Bioinformatics 2012.
    • Köster, Johannes. “Parallelization, Scalability, and Reproducibility in Next-Generation Sequencing Analysis”, PhD thesis, TU Dortmund 2014.
    • +
    • faircookbook worflows
    diff --git a/_site/search.json b/_site/search.json index 5c2e2185..821ce494 100644 --- a/_site/search.json +++ b/_site/search.json @@ -93,7 +93,7 @@ "href": "develop/practical_workshop.html#version-control-of-your-data-analysis-using-git-and-github", "title": "Practical material", "section": "5. Version control of your data analysis using Git and GitHub", - "text": "5. Version control of your data analysis using Git and GitHub\nVersion control is a systematic approach to tracking changes made to a project over time. It provides a structured means of documenting alterations, allowing you to revisit and understand the evolution of your work. In research data management and data analytics, version control is very important and gives you a lot of advantages.\nGit is a distributed version control system that enables developers and researchers to efficiently manage their project’s history, collaborate seamlessly, and ensure data integrity. At its core, Git operates through the following principles and mechanisms: On the other hand, GitHub is a web-based platform that enhances Git’s capabilities by providing a collaborative and centralized hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects.\n\n\n\n\n\n\nCreate a GitHub organization for your lab or department\n\n\n\nGitHub allows users to create organizations and teams that will collaborate or create repositories under the same umbrella organization. If you would like to create an educational organization in GitHub, you can do so for free! For example, you could create a GitHub account for your lab.\nTo create a GitHub organization, follow these instructions\nAfter you have created the GitHub organization, make sure that you create your repositories under the organization space and not your user!\n\n\n\nCreating a git repo online and copying your project folder\nVersion controlling your data analysis folders, a.k.a. Project folder, is very easy once you have set up your Cookiecutter templates. The simplest way of doing this is to first create a remote GitHub repository from the webpage (or from the Desktop app, if you are using it) with a proper project name. Then git clone that repository you just made into your Projects main folder. Then, use cookiecutter to create a project folder template and copy-paste the contents of the folder template to your cloned repo. Remember to fill up your metadata and description files! If you wish, you could already git add, commit, and push the first changes to the folders and continue from there on.\nGo back to the course material lesson 5 and read the differences between converting folders to git repositories and cloning a folder to an existing git repository.\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nIf you would like to know more about Git commits and the best way to make clear Git messages, check out this post!\n\n\n\n\nGitHub Pages\nOnce you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, Rmarkdowns, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we really recommend that you follow the nice tutorial that GitHub has put for you. Nonetheless, we will see the main steps in the exercise below.\nThere are many different ways to create your web pages. We recommend using Mkdocs and Mkdocs materials as a framework to create a nice webpage simply. The folder templates that we used as an example in the previous exercise already contain everything you need to start a webpage. Nonetheless, you will need to understand the basics of MkDocs and MkDocs materials to design a webpage to your liking. MkDocs is a static webpage generator that is very easy to use, while MkDocs materials is an extension of the tool that gives you many more options to customize your website. Check out their web pages to get started!\n\n\n\n\n\n\nExercise 5: make a project folder and publish a data analysis webpage\n\n\n\n\n\n\n\n\nConfigure your main GitHub Page and its repo\nThe first step is to set up the main GitHub Page site and the repository that will host it. This is very simple, as you will only need to follow these steps. In a Markdown document, outline the primary objectives of the organization and provide an overview of ongoing research projects. After you have created the organization/usernamegithub.io, it is time to configure your Project repository webpage using MkDocs!\nStart a new project from Cookiecutter or use one from the previous exercise.\nIf you use a Project repo from the first exercise, go to the next paragraph. Using Cookiecutter, create a new data analysis project. Remember to fill up your metadata and description files! After you have created the folder, it would be best to initialize a Git repo following the instructions from the previous section.\nNext, link your data of interest (or create a small fake dataset) and make an example of a data analysis notebook/report (this could be just a scatter plot of a random matrix of values). Depending on your setup, you might be using Jupyter Notebooks or Rmarkdowns. The extensions that we have installed using pip allow you to directly add a Jupyter Notebook file to the mkdocs.yml navigation section. On the other hand, if you are using Rmarkdown, you will have to knit your document into either an HTML page or a GitHub document.\nFor the purposes of this exercise, we have already included a basic index.md markdown file that can serve as the intro page of your repo, and a jupyter_example.ipynb with some code in it. You are welcome to modify them further to test them out!\nUse MkDocs to create your webpage\nWhen you are happy with your files and are ready to publish them, make sure to add, commit, and push the changes to the remote. Then, build up your webpage using MkDocs and the mkdocs gh-deploy command from the same directory where the mkdocs.yml file is. For example, if your mkdocs.yml for your Project folder is in /Users/JARH/Projects/project1_JARH_20231010/mkdocs.yml, do cd /Users/JARH/Projects/project1_JARH_20231010/ and then mkdocs gh-deploy. This requires a couple of changes in your GitHub organization settings.\nRemember to make sure that your markdowns, images, reports, etc., are included in the docs folder and properly set up in the navigation section of your mkdocs.yml file.\nFinally, we only need to set up the GitHub Project repo settings.\nPublishing your GitHub Page\nGo to your GitHub repo settings and configure the Page section. Since you are using the mkdocs gh-deploy command to publish your site in the gh-pages branch (as explained the the mkdocs documentation), we need to change where GitHub is fetching the website. You will need to configure the settings of this repository in GitHub so that the Page is taken from the gh-pages branch and the root folder.\n\n\n\nGitHub Pages setup\n\n\n\nBranch should be gh-pages\nFolder should be root\n\nAfter a couple of minutes, your webpage should be ready! You should be able to see your webpage through the link provided in the Page section!\n\nNow it is also possible to include this repository webpage in your main webpage organizationgithub.io by including the link of the repo website (https://organizationgithub.io/repo-name) in the navigation section of the mkdocs.yml file in the main organizationgithub.io repo." + "text": "5. Version control of your data analysis using Git and GitHub\nVersion control involves systematically tracking changes to a project over time, offering a structured way to document revisions and understand the progression of your work. In research data management and data analytics, it plays a critical role and provides numerous benefits.\nGit is a distributed version control system that helps developers and researchers efficiently manage project history, collaborate seamlessly, and maintain data integrity. On the other hand, GitHub is a web-based platform that builds on Git’s functionality by providing a centralized, collaborative hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects.\n\n\n\n\n\n\nCreate a GitHub organization for your lab or department\n\n\n\nGitHub users can create organizations, allowing groups to collaborate or create repositories under the same organization umbrella. You can create an educational organization on Github for free, by setting up a Github account for your lab.\nFollow these instructions to create a GitHub organization.\nOnce you’ve established your GitHub organization, be sure to create your repositories within the organization’s space rather than under your personal user account. This keeps your projects centralized and accessible to the entire group. Best practices for managing an organization on GitHub include setting clear access permissions, regularly reviewing roles and memberships, and organizing repositories effectively to keep your projects structured and easy to navigate.\n\n\n\nSetting up a GitHub repository for your project folder\nVersion controlling your data analysis folders becomes straightforward once you’ve established your Cookiecutter templates. After you’ve created several folder structures and metadata using your Cookiecutter template, you can manage version control by either converting those folders into Git repositories or copying a folder into an existing Git repository. Both approaches are explained in Lesson 5.\n\n\n\n\n\n\nExercise 6: initialize a repository from an existing folder:\n\n\n\n\n\n\n\n\nInitialize the repository: Begin by running the command git init in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See (git init) for more details.\nCreate a remote repository: Once the local repository is initialized, create an empty new repository on GitHub (website or Github Desktop).\nConnect the remote repository: Add the GitHub repository URL to your local repository using the command git remote add origin <URL>. This associates the remote repository with the name “origin.”\nCommit changes: If you have files you want to add to your repository, stage them using git add ., then create a commit to save a snapshot of your changes with git commit -m \"add local folder\".\nPush to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using git push -u origin main.\n\n\n\n\n\n\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nIf you would like to know more about Git commits and the best way to make clear Git messages, check out this post!\n\n\n\n\nGitHub Pages\nOnce you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, R Markdown files, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we really recommend that you follow the nice tutorial that GitHub has put for you. Nonetheless, we will see the main steps in the exercise below.\nThere are many different ways to create your web pages. We recommend using Mkdocs and Mkdocs materials as a framework to create a nice webpage simply. The folder templates that we used as an example in the previous exercise already contain everything you need to start a webpage. Nonetheless, you will need to understand the basics of MkDocs and MkDocs materials to design a webpage to your liking. MkDocs is a static webpage generator that is very easy to use, while MkDocs materials is an extension of the tool that gives you many more options to customize your website. Check out their web pages to get started!\n\n\n\n\n\n\nExercise 5: make a project folder and publish a data analysis webpage\n\n\n\n\n\n\n\n\nConfigure your main GitHub Page and its repo\nThe first step is to set up the main GitHub Page site and the repository that will host it. This is very simple, as you will only need to follow these steps. In a Markdown document, outline the primary objectives of the organization and provide an overview of ongoing research projects. After you have created the organization/usernamegithub.io, it is time to configure your Project repository webpage using MkDocs!\nStart a new project from Cookiecutter or use one from the previous exercise.\nIf you use a Project repo from the first exercise, go to the next paragraph. Using Cookiecutter, create a new data analysis project. Remember to fill up your metadata and description files! After you have created the folder, it would be best to initialize a Git repo following the instructions from the previous section.\nNext, link your data of interest (or create a small fake dataset) and make an example of a data analysis notebook/report (this could be just a scatter plot of a random matrix of values). Depending on your setup, you might be using Jupyter Notebooks or Rmarkdowns. The extensions that we have installed using pip allow you to directly add a Jupyter Notebook file to the mkdocs.yml navigation section. On the other hand, if you are using Rmarkdown, you will have to knit your document into either an HTML page or a GitHub document.\nFor the purposes of this exercise, we have already included a basic index.md markdown file that can serve as the intro page of your repo, and a jupyter_example.ipynb with some code in it. You are welcome to modify them further to test them out!\nUse MkDocs to create your webpage\nWhen you are happy with your files and are ready to publish them, make sure to add, commit, and push the changes to the remote. Then, build up your webpage using MkDocs and the mkdocs gh-deploy command from the same directory where the mkdocs.yml file is. For example, if your mkdocs.yml for your Project folder is in /Users/JARH/Projects/project1_JARH_20231010/mkdocs.yml, do cd /Users/JARH/Projects/project1_JARH_20231010/ and then mkdocs gh-deploy. This requires a couple of changes in your GitHub organization settings.\nRemember to make sure that your markdowns, images, reports, etc., are included in the docs folder and properly set up in the navigation section of your mkdocs.yml file.\nFinally, we only need to set up the GitHub Project repo settings.\nPublishing your GitHub Page\nGo to your GitHub repo settings and configure the Page section. Since you are using the mkdocs gh-deploy command to publish your site in the gh-pages branch (as explained the the mkdocs documentation), we need to change where GitHub is fetching the website. You will need to configure the settings of this repository in GitHub so that the Page is taken from the gh-pages branch and the root folder.\n\n\n\nGitHub Pages setup\n\n\n\nBranch should be gh-pages\nFolder should be root\n\nAfter a couple of minutes, your webpage should be ready! You should be able to see your webpage through the link provided in the Page section!\n\nNow it is also possible to include this repository webpage in your main webpage organizationgithub.io by including the link of the repo website (https://organizationgithub.io/repo-name) in the navigation section of the mkdocs.yml file in the main organizationgithub.io repo." }, { "objectID": "develop/practical_workshop.html#archive-github-repositories-on-zenodo", @@ -459,7 +459,7 @@ "href": "index.html", "title": "Computational Research Data Management", "section": "", - "text": "The course “Research Data Management (RDM) for biological data” is designed to provide participants with foundational knowledge and practical skills in handling the extensive data generated by modern studies, with a focus on Next Generation Sequencing (NGS) data. It emphasizes the importance of Open Science and FAIR principles in managing data effectively. This course covers essential principles and best practices guidelines in data organization, metadata annotation, version control, and data preservation. These principles are explored from a computational perspective, ensuring participants gain hands-on experience in applying them to real-world scenarios in their research labs. Additionally, the course delves into FAIR principles and Open Science, promoting collaboration and reproducibility in research endeavors. By the course’s conclusion, attendees will possess essential tools and techniques to address the data challenges prevalent in today’s NGS research landscape, as well as in other related fields to health and bioinformatics.\n\n\n\n\n\n\nCourse Overview\n\n\n\n\n📖 Syllabus:\n\n\nData Lifecycle Management\nData Management Plans (DMPs)\nData Organization and storage\nDocumentation standards for biodata\nVersion Control and Collaboration\nProcessing and analyzing biodata\nStoring and sharing biodata\n\n\n⏰ Total Time Estimation: X hours\n\n📁 Supporting Materials:\n\n👨‍💻 Target Audience: Ph.D., MSc, anyone interested in RDM for NGS data or other related fields within bioinformatics.\n👩‍🎓 Level: Beginner.\n🔒 License: Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.\n\n💰 Funding: This project was funded by the Novo Nordisk Fonden (NNF20OC0063268).\n\n\n\n\n\n\n\n\n\n\nCourse Requirements\n\n\n\n\nBasic understanding Next Generation Sequencing data and formats.\nCommand Line experience\nBasic programming experience\nQuarto or Mkdocs tools\n\n\n\nThis course offers participants with an in-depth introduction to effectively managing the vast amounts of data generated in modern studies. Throughout the program, emphasis is placed on practical understanding of RDM principles and the importance of efficient handling of large datasets. In this context, participants will learn the necessity of adopting Open Science and FAIR principles for enhancing data accessibility and reusability.\nParticipants will acquire practical skills for organizing data, including the creation of folder and file structures, and the implementation of metadata to facilitate data discoverability and interpretation. Special attention is given to the development of Data Management Plans (DMPs) with examples tailored to omics data, ensuring compliance with institutional and funding agency requirements while maintaining data integrity. Attendees will also gain insights into the establishment of simple databases and the use of version control systems to track changes in data analysis, thereby promoting collaboration and reproducibility.\nThe course concludes with a focus on archiving and data repositories, enabling participants to learn strategies for preserving and sharing data for long-term scientific usage. By the end of the course, attendees will be equipped with essential tools and techniques to effectively navigate the challenges prevalent in today’s research landscape. This will not only foster successful data management practices but also enhance collaboration within the scientific community.\n\n\n\n\n\n\nCourse Goals\n\n\n\nBy the end of this workshop, you should be able to apply the following concepts in the context of Next Generation Sequencing data:\n\nUnderstand the Importance of Research Data Management (RDM)\nFamiliarize Yourself with FAIR and Open Science Principles\nDraft a Data Management Plan for your own Data\nEstablish File and Folder Naming Conventions\nEnhance Data with Descriptive Metadata\nImplement Version Control for Data Analysis\nSelect an Appropriate Repository for Data Archiving\nMake your data analysis and workflows reproducible and FAIR\n\n\n\n\n\n\n\n\n\nWarning\n\n\n\nThis is a computational workshop that focuses primarily on the digital aspect of our data. While wet lab Research Data Management (RDM) involving protocols, instruments, reagents, ELM or LIMS systems is integral to the entire RDM process, it won’t be covered in this course.\nAs part of effective data management, it’s crucial to prioritize strategies that ensure security and privacy. While these aspects are important, please note that they won’t be covered in our course. However, we highly recommend enrolling in the GDPR course offered by Center for Health Data Science, specially if you’re working with sensitive data. This course specifically focuses on GDPR compliance and will provide you with valuable insights and skills in managing data privacy and security.\n\n\n\n\n\nUniversity of Copenhagen\nUniversity Library of Southern Denmark\nTechnical University of Denmark\nAalborg University\nAarhus University\n\n\n\n\n\nRDMkit, ELIXIR (2021) Research Data Management Kit. A deliverable from the EU-funded ELIXIR-CONVERGE project (grant agreement 871075).\nUniversity of Copenhagen Research Data Management Team.\nMartin Proks and Sarah Lundregan, Brickman Lab, NNF Center for Stem Cell Biology (reNEW), University of Copenhagen.\nRichard Dennis, Data Steward, NNF Center for Stem Cell Biology (reNEW), University of Copenhagen.\nNBISweden." + "text": "Practical RDM workshop\n\n\n\nWe offer workshops on practical RDM for biodata. Keep an eye on the upcoming events on the Sandbox website." }, { "objectID": "develop/06_file_structure.html", @@ -917,7 +917,7 @@ { "objectID": "practical_workflows.html", "href": "practical_workflows.html", - "title": "Workflows", + "title": "FAIR Workflows", "section": "", "text": "Course Overview\n\n\n\n\n⏰ Total Time Estimation: X hours\n\n📁 Supporting Materials:\n\n👨‍💻 Target Audience: Ph.D., MSc, anyone interested in workflow management systems for High-Throughput data or other related fields within bioinformatics.\n👩‍🎓 Level: Advanced.\n🔒 License: Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.\n\n💰 Funding: This project was funded by the Novo Nordisk Fonden (NNF20OC0063268)." }, @@ -1055,7 +1055,7 @@ "href": "develop/03_DOD.html#template-engine", "title": "3. Data organization and storage", "section": "Template engine", - "text": "Template engine\nSetting up folder structures manually for each new project can be time-consuming. Thankfully, tools like Cookiecutter offer a solution by allowing users to create project templates easily. These templates can ensure consistency across projects and save time. Additionally, using cruft alongside Cookiecutter can assist in maintaining older templates when updates are made (by synchronizing them with the latest version).\n\n\n\n\n\n\nCookiecutter templates\n\n\n\n\nCookiecutter template for Data science projects\nBrickmanlab template for NGS data: similar to the folder structures in the examples above. You can download and modify it to suit your needs.\n\n\n\n\nQuick tutorial on cookiecutter\n\n\n\n\n\n\nSandbox Tutorial\n\n\n\nLearn how to create your own template here.\nWe offer workshops on practical RDM for biodata. Keep an eye on the upcoming events on the Sandbox website.", + "text": "Template engine\nSetting up folder structures manually for each new project can be time-consuming. Thankfully, tools like Cookiecutter offer a solution by allowing users to create project templates easily. These templates can ensure consistency across projects and save time. Additionally, using cruft alongside Cookiecutter can assist in maintaining older templates when updates are made (by synchronizing them with the latest version).\n\n\n\n\n\n\nCookiecutter templates\n\n\n\n\nSandbox Project/Data analysis template\nSandbox Data/Assay template\nCookiecutter template for Data science projects\nBrickmanlab template for NGS data: similar to the folder structures in the examples above. You can download and modify it to suit your needs.\n\n\n\n\nQuick tutorial on cookiecutter\n\n\n\n\n\n\nSandbox Tutorial\n\n\n\nLearn how to create your own template here.", "crumbs": [ "Course material", "Key practices", @@ -1175,7 +1175,7 @@ "href": "develop/04_metadata.html#wrap-up", "title": "4. Documentation for biodata", "section": "Wrap up", - "text": "Wrap up\nIn this lesson, we’ve covered the importance of attaching metadata to your data for future reusability and comprehension. We briefly introduced various controlled vocabularies and provided several sources for inspiration. Implementing ontologies is optional, as their usage complexity varies.\nOptionally, if you’ve gone through the lesson, you’ve learned how to use the metadata YAML files to create a database and a catalog browser using Shiny apps. This makes it easy to manage all assays together.\n\nSources\n\nRMDKit: https://rdmkit.elixir-europe.org/data_brokering#collecting-and-processing-the-metadata-and-data\nFAIRsharing.org: provide a searchable database of metadata standards for a wide variety of disciplines\n\nOther sources:\n\nJohns Hopkins Sheridan libraries, RDM. They provide a list of medical metadata standards resources.\n\nKU Leuven Guidance: https://www.kuleuven.be/rdm/en/guidance/documentation-metadata\nTranscriptomics metadata standards and fields\nBiological ontologies for data scientists,Bionty\nNIH standardizing data collection\nObservational Health Data Sciences and Informatics (OHDSI) OMOP Common Data Model\n\n\n\nTools and software\n\nRightfield: open source tool facilitates the integration of ontology terms into Excel spreadsheet.\nOwlready2: Python package, enables the loading of ontologies as Python objects. This versatile tool allows users to manipulate and store ontology classes, instances, and properties as needed.", + "text": "Wrap up\nIn this lesson, we’ve covered the importance of attaching metadata to your data for future reusability and comprehension. We briefly introduced various controlled vocabularies and provided several sources for inspiration. Implementing ontologies is optional, as their usage complexity varies.\nOptionally, if you’ve gone through the lesson, you’ve learned how to use the metadata YAML files to create a database and a catalog browser using Shiny apps. This makes it easy to manage all assays together.\n\nSources\n\nRMDKit: https://rdmkit.elixir-europe.org/data_brokering#collecting-and-processing-the-metadata-and-data\nFAIRsharing.org: provide a searchable database of metadata standards for a wide variety of disciplines\n\nOther sources:\n\nJohns Hopkins Sheridan libraries, RDM. They provide a list of medical metadata standards resources.\n\nKU Leuven Guidance: https://www.kuleuven.be/rdm/en/guidance/documentation-metadata\nTranscriptomics metadata standards and fields\nNIH standardizing data collection\nObservational Health Data Sciences and Informatics (OHDSI) OMOP Common Data Model\n\n\n\nTools and software\n\nRightfield: open source tool facilitates the integration of ontology terms into Excel spreadsheet.\nOwlready2: Python package, enables the loading of ontologies as Python objects. This versatile tool allows users to manipulate and store ontology classes, instances, and properties as needed.\nShiny Apps: easy interactive web apps for data science", "crumbs": [ "Course material", "Key practices", @@ -1307,7 +1307,7 @@ "href": "develop/05_VC.html", "title": "5. Data Analysis with Version Control", "section": "", - "text": "Course Overview\n\n\n\n⏰ Time Estimation: X minutes\n💬 Learning Objectives:\n\nVersion control essentials and practices\nGit and Github repositories\nCreate repositories\nGitHub page to showcase your data analysis reports\n\n\n\nThis lesson introduces version control with Git and Github and its significance in research. You will gain the ability to create Git repositories, and skills to build GitHub pages for showcasing data analysis.\n\n\nVersion control systematically tracks project changes, documenting alterations for understanding project evolution. It holds significant importance in research data management, software development, and data analysis, offering numerous advantages.\n\n\n\n\n\n\nAdvantages of using version control\n\n\n\n\nDocument Progress: Detailed change history aids understanding of project development and modifications.\nEnsure Data Integrity: Prevents accidental data loss or corruption, with each change tracked for easy recovery.\nFacilitate Collaboration: Enables seamless collaboration among team members, allowing multiple individuals to work concurrently without conflicts.\nReproducibility: Preserves project state for accurate validation and analysis.\nBranching and Experimentation: Allows the creation of alternative project versions for experimentation, without altering the main branch.\nGlobal Accessibility: Platforms like GitHub provide visibility for sharing, feedback, and contribution to open science.\n\n\n\n\n\n\n\n\n\nTake our course on Git & Github\n\n\n\nif you’re interested in delving deeper, explore our course on Git and GitHub.\nAlternatively, here are some examples and online resources to expand your understanding:\n\nGit and GitHub online resources\nGitHub documentation\nGit documentation\n\n\n\n\n\nGit is a widely adopted version control system that empowers developers and researchers to efficiently manage their project’s history, collaborate seamlessly, track changes, and ensure data integrity. Git operates on core principles and mechanisms:\n\nLocal Repository: Each user maintains a local repository on their computer, storing the complete project history for independent work.\nSnapshots, Not Files: Git captures snapshots of the entire project at different points instead of tracking individual file changes, ensuring data consistency.\nCommits: Users create ‘commits’ as snapshots of the project at specific moments, recording changes made to files along with explanatory commit messages.\nBranching: Git supports branching, enabling users to create separate lines of development for new features or bug fixes without affecting the main branch.\nMerging: Changes from one branch can be merged into another, facilitating the incorporation of new features or bug fixes back into the main project with a smooth merging process.\nDistributed Architecture: Git’s distributed nature means each user’s local repository is a complete copy of the project, enabling offline work and ensuring data redundancy.\nRemote Repositories: Users can connect and synchronize their local repositories with remote repositories hosted on platforms like GitHub, facilitating collaboration and project sharing.\nPush and Pull: Users ‘push’ their local changes to a remote repository to share with others and ‘pull’ changes made by others into their local repository to stay updated.\nConflict Resolution: Git provides tools to resolve conflicts manually in cases of conflicting changes, ensuring data integrity during collaboration.\nVersioning and Tagging: Git offers versioning and tagging capabilities, allowing users to mark specific points in history such as major releases or significant milestones.\n\n\n\n\nIn addition to exploring Git, we will also explore GitHub, a collaborative platform for hosting Git repositories. GitHub enhances Git’s capabilities by offering features like issue tracking, security measures to protect repositories, and GitHub Pages for creating project websites. Additionally, GitHub provides the option to set repositories as private until you are ready to share your work publicly.\n\n\n\n\n\n\nAlternatives flows for collaborative projects\n\n\n\n\nGitLab\nBitBucket\n\nWe will focus on GitHub for the remainder of this lesson due to its widespread usage and compatibility.\n\n\n\n\n\n\n\n\nWarning\n\n\n\nWe will discuss repositories for archiving experimental or large datasets in lesson 7.\n\n\n\n\nMoving from Git to GitHub involves transitioning from a local version control setup to a remote hosting platform. You will need a GitHub account for the exercise in this section.\n\n\n\n\n\n\nCreate a GitHub account\n\n\n\n\nIf you don’t have a GitHub account yet, click here.\nInstall Git from Git webpage\n\n\n\nYou have two options when it comes to creating a repository for your project. First, you can start from scratch by creating a new repository and adding files to it as your project progresses. Alternatively, if you already have an existing folder structure for your project, you can initialize a repository directly from that folder. It is crucial to initiate version control in the early stages of a project to facilitate easy tracking of changes and effective management of the project’s version history from the beginning.\n\n\nIf you completed all the exercises in lesson 3, you should have a project data structure prepared. Otherwise, consider using one of your existing projects or creating a small toy example for practice using cookiecutter (see practical_workshop).\n\n\n\n\n\n\nGithub documentation link\n\n\n\n\nAdding locally hosted code to Github\n\n\n\n\n\n\n\n\n\nExercise 1: initialize a repository from an existing folder:\n\n\n\n\n\n\n\n\nFirst, initialize the repository using the command git init. This command is run only once, even in collaborative projects (git init).\nOnce the repository is initialized, create a remote repository on GitHub.\nAdd the remote URL to your local git repository using git remote add origin <URL>`. This associates the remote URL with the name “origin”.\nEnsure you have at least one commit in your history by staging existing files with git add and then creating a snapshot, known as committing, with git commit.\nFinally, push your local commits to the remote repository and establish a tracking relationship using git push -u origin master.\n\n\n\n\n\n\n\n\n\nAlternatively to converting folders to repositories, you can create a new repository remotely, and then clone (git clone) it locally. Here, git init is not needed. You can move the files into the repository locally (git add, git commit, and git push). If you are creating a collaborative repository, you can now share it with your colleagues.\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nWrite useful and clear Git commits. Check out this post for tips.\n\n\n\n\n\n\n\nAfter setting up your repository on GitHub, take advantage of the opportunity to enhance it by adding your data analysis reports. Whether they are in Jupyter Notebooks, Rmarkdowns, or HTML reports, you can showcase them on a GitHub Page.\nOnce you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, Rmarkdowns, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we recommend that you follow the nice tutorial that GitHub has put for you.\nFor simplicity, we recommend using Quarto or MkDocs. Visit their websites and follow the instructions to get started.\n\n\n\n\n\n\nTutorial links\n\n\n\n\nGet started in quarto: https://quarto.org/docs/get-started/. We recommend using the VS code tool, if you do, follow this tutorial.\nMkDocs materials to further customize MkDocs websites.\n\n\n\n\n\n\nWe provide an example of setting up Git, MkDocs, and a GitHub account, enabling you to replicate the process independently! (see Exercise 5 in the practical material)\n\n\n\n\nIn this lesson, we explored version control and utilized Git and GitHub to establish data analysis repositories from our Project folders. Additionally, we delved into creating a GitHub organization and leveraging GitHub Pages to showcase data analysis scripts and notebooks publicly. Remember to complete the corresponding exercise from the practical workshop to reinforce your knowledge.\n\n\n\nVersion Control and Code Repository Link.", + "text": "Course Overview\n\n\n\n⏰ Time Estimation: X minutes\n💬 Learning Objectives:\n\nVersion control essentials and practices\nGit and Github repositories\nCreate repositories\nGitHub page to showcase your data analysis reports\n\n\n\nThis lesson introduces version control with Git and Github and its significance in research. You will gain the ability to create Git repositories, and skills to build GitHub pages for showcasing data analysis.\n\n\nVersion control systematically tracks project changes, documenting alterations for understanding project evolution. It holds significant importance in research data management, software development, and data analysis, offering numerous advantages.\n\n\n\n\n\n\nAdvantages of using version control\n\n\n\n\nDocument Progress: Detailed change history aids understanding of project development and modifications.\nEnsure Data Integrity: Prevents accidental data loss or corruption, with each change tracked for easy recovery.\nFacilitate Collaboration: Enables seamless collaboration among team members, allowing multiple individuals to work concurrently without conflicts.\nReproducibility: Preserves project state for accurate validation and analysis.\nBranching and Experimentation: Allows the creation of alternative project versions for experimentation, without altering the main branch.\nGlobal Accessibility: Platforms like GitHub provide visibility for sharing, feedback, and contribution to open science.\n\n\n\n\n\n\n\n\n\nTake our course on Git & Github\n\n\n\nif you’re interested in delving deeper, explore our course on Git and GitHub.\nAlternatively, here are some examples and online resources to expand your understanding:\n\nGit and GitHub online resources\nGitHub documentation\nGit documentation\n\n\n\n\n\nGit is a widely adopted version control system that empowers developers and researchers to efficiently manage their project’s history, collaborate seamlessly, track changes, and ensure data integrity. Git operates on core principles and mechanisms:\n\nLocal Repository: Each user maintains a local repository on their computer, storing the complete project history for independent work.\nSnapshots, Not Files: Git captures snapshots of the entire project at different points instead of tracking individual file changes, ensuring data consistency.\nCommits: Users create ‘commits’ as snapshots of the project at specific moments, recording changes made to files along with explanatory commit messages.\nBranching: Git supports branching, enabling users to create separate lines of development for new features or bug fixes without affecting the main branch.\nMerging: Changes from one branch can be merged into another, facilitating the incorporation of new features or bug fixes back into the main project with a smooth merging process.\nDistributed Architecture: Git’s distributed nature means each user’s local repository is a complete copy of the project, enabling offline work and ensuring data redundancy.\nRemote Repositories: Users can connect and synchronize their local repositories with remote repositories hosted on platforms like GitHub, facilitating collaboration and project sharing.\nPush and Pull: Users ‘push’ their local changes to a remote repository to share with others and ‘pull’ changes made by others into their local repository to stay updated.\nConflict Resolution: Git provides tools to resolve conflicts manually in cases of conflicting changes, ensuring data integrity during collaboration.\nVersioning and Tagging: Git offers versioning and tagging capabilities, allowing users to mark specific points in history such as major releases or significant milestones.\n\n\n\n\nIn addition to exploring Git, we will also explore GitHub, a collaborative platform for hosting Git repositories. GitHub enhances Git’s capabilities by offering features like issue tracking, security measures to protect repositories, and GitHub Pages for creating project websites. Additionally, GitHub provides the option to set repositories as private until you are ready to share your work publicly.\n\n\n\n\n\n\nAlternatives flows for collaborative projects\n\n\n\n\nGitLab\nBitBucket\n\nWe will focus on GitHub for the remainder of this lesson due to its widespread usage and compatibility.\n\n\n\n\n\n\n\n\nWarning\n\n\n\nWe will discuss repositories for archiving experimental or large datasets in lesson 7.\n\n\n\n\nMoving from Git to GitHub involves transitioning from a local version control setup to a remote hosting platform. You will need a GitHub account for the exercise in this section.\n\n\n\n\n\n\nCreate a GitHub account\n\n\n\n\nIf you don’t have a GitHub account yet, click here\nInstall Git from Git webpage\n\n\n\nYou have two options when it comes to creating a repository for your project. First, you can start from scratch by creating a new repository and adding files to it as your project progresses. Alternatively, if you already have an existing folder structure for your project, you can initialize a repository directly from that folder. It is crucial to initiate version control in the early stages of a project to facilitate easy tracking of changes and effective management of the project’s version history from the beginning.\n\n\nIf you completed all the exercises in lesson 3, you should have a project data structure prepared. Otherwise, consider using one of your existing projects or creating a small toy example for practice using cookiecutter (see practical_workshop).\n\n\n\n\n\n\nGithub documentation link\n\n\n\n\nAdding locally hosted code to Github\n\n\n\n\n\n\n\n\n\nExercise 1: initialize a repository from an existing folder:\n\n\n\n\n\n\n\n\nInitialize the repository: Begin by running the command git init in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See (git init) for more details.\nCreate a remote repository: Once the local repository is initialized, create am empty new repository on GitHub.\nConnect the remote repository: Add the GitHub repository URL to your local repository using the command git remote add origin <URL>. This associates the remote repository with the name “origin.”\nCommit changes: If you have files you want to add to your repository, stage them using git add ., then create a commit to save a snapshot of your changes with git commit -m \"add local folder\".\nPush to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using git push -u origin main.\n\n\n\n\n\n\n\n\n\nAlternatively to converting folders to repositories, you can create a new repository remotely, and then clone (git clone) it locally. Here, git init is not needed. You can move the files into the repository locally (git add, git commit, and git push). If you are creating a collaborative repository, you can now share it with your colleagues.\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nWrite useful and clear Git commits. Check out this post for tips.\n\n\n\n\n\n\n\nAfter setting up your repository on GitHub, take advantage of the opportunity to enhance it by adding your data analysis reports. Whether they are in Jupyter Notebooks, R Markdown files, or HTML reports, you can showcase them on a GitHub Page.\nOnce you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, R Markdown files, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we recommend that you follow the nice tutorial that GitHub has put for you.\nFor simplicity, we recommend using Quarto or MkDocs. Visit their websites and follow the instructions to get started.\n\n\n\n\n\n\nTutorial links\n\n\n\n\nGet started in quarto: https://quarto.org/docs/get-started/. We recommend using the VS code tool, if you do, follow this tutorial.\nMkDocs materials to further customize MkDocs websites.\n\n\n\n\n\n\nWe provide an example of setting up Git, MkDocs, and a GitHub account, enabling you to replicate the process independently! (see Exercise 5 in the practical material)\n\n\n\n\nIn this lesson, we explored version control and utilized Git and GitHub to establish data analysis repositories from our Project folders. Additionally, we delved into creating a GitHub organization and leveraging GitHub Pages to showcase data analysis scripts and notebooks publicly. Remember to complete the corresponding exercise from the practical workshop to reinforce your knowledge.\n\n\n\nVersion Control and Code Repository Link.\nGit cheat sheet.", "crumbs": [ "Course material", "Key practices", @@ -1319,7 +1319,7 @@ "href": "develop/05_VC.html#version-control", "title": "5. Data Analysis with Version Control", "section": "", - "text": "Version control systematically tracks project changes, documenting alterations for understanding project evolution. It holds significant importance in research data management, software development, and data analysis, offering numerous advantages.\n\n\n\n\n\n\nAdvantages of using version control\n\n\n\n\nDocument Progress: Detailed change history aids understanding of project development and modifications.\nEnsure Data Integrity: Prevents accidental data loss or corruption, with each change tracked for easy recovery.\nFacilitate Collaboration: Enables seamless collaboration among team members, allowing multiple individuals to work concurrently without conflicts.\nReproducibility: Preserves project state for accurate validation and analysis.\nBranching and Experimentation: Allows the creation of alternative project versions for experimentation, without altering the main branch.\nGlobal Accessibility: Platforms like GitHub provide visibility for sharing, feedback, and contribution to open science.\n\n\n\n\n\n\n\n\n\nTake our course on Git & Github\n\n\n\nif you’re interested in delving deeper, explore our course on Git and GitHub.\nAlternatively, here are some examples and online resources to expand your understanding:\n\nGit and GitHub online resources\nGitHub documentation\nGit documentation\n\n\n\n\n\nGit is a widely adopted version control system that empowers developers and researchers to efficiently manage their project’s history, collaborate seamlessly, track changes, and ensure data integrity. Git operates on core principles and mechanisms:\n\nLocal Repository: Each user maintains a local repository on their computer, storing the complete project history for independent work.\nSnapshots, Not Files: Git captures snapshots of the entire project at different points instead of tracking individual file changes, ensuring data consistency.\nCommits: Users create ‘commits’ as snapshots of the project at specific moments, recording changes made to files along with explanatory commit messages.\nBranching: Git supports branching, enabling users to create separate lines of development for new features or bug fixes without affecting the main branch.\nMerging: Changes from one branch can be merged into another, facilitating the incorporation of new features or bug fixes back into the main project with a smooth merging process.\nDistributed Architecture: Git’s distributed nature means each user’s local repository is a complete copy of the project, enabling offline work and ensuring data redundancy.\nRemote Repositories: Users can connect and synchronize their local repositories with remote repositories hosted on platforms like GitHub, facilitating collaboration and project sharing.\nPush and Pull: Users ‘push’ their local changes to a remote repository to share with others and ‘pull’ changes made by others into their local repository to stay updated.\nConflict Resolution: Git provides tools to resolve conflicts manually in cases of conflicting changes, ensuring data integrity during collaboration.\nVersioning and Tagging: Git offers versioning and tagging capabilities, allowing users to mark specific points in history such as major releases or significant milestones.\n\n\n\n\nIn addition to exploring Git, we will also explore GitHub, a collaborative platform for hosting Git repositories. GitHub enhances Git’s capabilities by offering features like issue tracking, security measures to protect repositories, and GitHub Pages for creating project websites. Additionally, GitHub provides the option to set repositories as private until you are ready to share your work publicly.\n\n\n\n\n\n\nAlternatives flows for collaborative projects\n\n\n\n\nGitLab\nBitBucket\n\nWe will focus on GitHub for the remainder of this lesson due to its widespread usage and compatibility.\n\n\n\n\n\n\n\n\nWarning\n\n\n\nWe will discuss repositories for archiving experimental or large datasets in lesson 7.\n\n\n\n\nMoving from Git to GitHub involves transitioning from a local version control setup to a remote hosting platform. You will need a GitHub account for the exercise in this section.\n\n\n\n\n\n\nCreate a GitHub account\n\n\n\n\nIf you don’t have a GitHub account yet, click here.\nInstall Git from Git webpage\n\n\n\nYou have two options when it comes to creating a repository for your project. First, you can start from scratch by creating a new repository and adding files to it as your project progresses. Alternatively, if you already have an existing folder structure for your project, you can initialize a repository directly from that folder. It is crucial to initiate version control in the early stages of a project to facilitate easy tracking of changes and effective management of the project’s version history from the beginning.\n\n\nIf you completed all the exercises in lesson 3, you should have a project data structure prepared. Otherwise, consider using one of your existing projects or creating a small toy example for practice using cookiecutter (see practical_workshop).\n\n\n\n\n\n\nGithub documentation link\n\n\n\n\nAdding locally hosted code to Github\n\n\n\n\n\n\n\n\n\nExercise 1: initialize a repository from an existing folder:\n\n\n\n\n\n\n\n\nFirst, initialize the repository using the command git init. This command is run only once, even in collaborative projects (git init).\nOnce the repository is initialized, create a remote repository on GitHub.\nAdd the remote URL to your local git repository using git remote add origin <URL>`. This associates the remote URL with the name “origin”.\nEnsure you have at least one commit in your history by staging existing files with git add and then creating a snapshot, known as committing, with git commit.\nFinally, push your local commits to the remote repository and establish a tracking relationship using git push -u origin master.\n\n\n\n\n\n\n\n\n\nAlternatively to converting folders to repositories, you can create a new repository remotely, and then clone (git clone) it locally. Here, git init is not needed. You can move the files into the repository locally (git add, git commit, and git push). If you are creating a collaborative repository, you can now share it with your colleagues.\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nWrite useful and clear Git commits. Check out this post for tips.\n\n\n\n\n\n\n\nAfter setting up your repository on GitHub, take advantage of the opportunity to enhance it by adding your data analysis reports. Whether they are in Jupyter Notebooks, Rmarkdowns, or HTML reports, you can showcase them on a GitHub Page.\nOnce you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, Rmarkdowns, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we recommend that you follow the nice tutorial that GitHub has put for you.\nFor simplicity, we recommend using Quarto or MkDocs. Visit their websites and follow the instructions to get started.\n\n\n\n\n\n\nTutorial links\n\n\n\n\nGet started in quarto: https://quarto.org/docs/get-started/. We recommend using the VS code tool, if you do, follow this tutorial.\nMkDocs materials to further customize MkDocs websites.\n\n\n\n\n\n\nWe provide an example of setting up Git, MkDocs, and a GitHub account, enabling you to replicate the process independently! (see Exercise 5 in the practical material)", + "text": "Version control systematically tracks project changes, documenting alterations for understanding project evolution. It holds significant importance in research data management, software development, and data analysis, offering numerous advantages.\n\n\n\n\n\n\nAdvantages of using version control\n\n\n\n\nDocument Progress: Detailed change history aids understanding of project development and modifications.\nEnsure Data Integrity: Prevents accidental data loss or corruption, with each change tracked for easy recovery.\nFacilitate Collaboration: Enables seamless collaboration among team members, allowing multiple individuals to work concurrently without conflicts.\nReproducibility: Preserves project state for accurate validation and analysis.\nBranching and Experimentation: Allows the creation of alternative project versions for experimentation, without altering the main branch.\nGlobal Accessibility: Platforms like GitHub provide visibility for sharing, feedback, and contribution to open science.\n\n\n\n\n\n\n\n\n\nTake our course on Git & Github\n\n\n\nif you’re interested in delving deeper, explore our course on Git and GitHub.\nAlternatively, here are some examples and online resources to expand your understanding:\n\nGit and GitHub online resources\nGitHub documentation\nGit documentation\n\n\n\n\n\nGit is a widely adopted version control system that empowers developers and researchers to efficiently manage their project’s history, collaborate seamlessly, track changes, and ensure data integrity. Git operates on core principles and mechanisms:\n\nLocal Repository: Each user maintains a local repository on their computer, storing the complete project history for independent work.\nSnapshots, Not Files: Git captures snapshots of the entire project at different points instead of tracking individual file changes, ensuring data consistency.\nCommits: Users create ‘commits’ as snapshots of the project at specific moments, recording changes made to files along with explanatory commit messages.\nBranching: Git supports branching, enabling users to create separate lines of development for new features or bug fixes without affecting the main branch.\nMerging: Changes from one branch can be merged into another, facilitating the incorporation of new features or bug fixes back into the main project with a smooth merging process.\nDistributed Architecture: Git’s distributed nature means each user’s local repository is a complete copy of the project, enabling offline work and ensuring data redundancy.\nRemote Repositories: Users can connect and synchronize their local repositories with remote repositories hosted on platforms like GitHub, facilitating collaboration and project sharing.\nPush and Pull: Users ‘push’ their local changes to a remote repository to share with others and ‘pull’ changes made by others into their local repository to stay updated.\nConflict Resolution: Git provides tools to resolve conflicts manually in cases of conflicting changes, ensuring data integrity during collaboration.\nVersioning and Tagging: Git offers versioning and tagging capabilities, allowing users to mark specific points in history such as major releases or significant milestones.\n\n\n\n\nIn addition to exploring Git, we will also explore GitHub, a collaborative platform for hosting Git repositories. GitHub enhances Git’s capabilities by offering features like issue tracking, security measures to protect repositories, and GitHub Pages for creating project websites. Additionally, GitHub provides the option to set repositories as private until you are ready to share your work publicly.\n\n\n\n\n\n\nAlternatives flows for collaborative projects\n\n\n\n\nGitLab\nBitBucket\n\nWe will focus on GitHub for the remainder of this lesson due to its widespread usage and compatibility.\n\n\n\n\n\n\n\n\nWarning\n\n\n\nWe will discuss repositories for archiving experimental or large datasets in lesson 7.\n\n\n\n\nMoving from Git to GitHub involves transitioning from a local version control setup to a remote hosting platform. You will need a GitHub account for the exercise in this section.\n\n\n\n\n\n\nCreate a GitHub account\n\n\n\n\nIf you don’t have a GitHub account yet, click here\nInstall Git from Git webpage\n\n\n\nYou have two options when it comes to creating a repository for your project. First, you can start from scratch by creating a new repository and adding files to it as your project progresses. Alternatively, if you already have an existing folder structure for your project, you can initialize a repository directly from that folder. It is crucial to initiate version control in the early stages of a project to facilitate easy tracking of changes and effective management of the project’s version history from the beginning.\n\n\nIf you completed all the exercises in lesson 3, you should have a project data structure prepared. Otherwise, consider using one of your existing projects or creating a small toy example for practice using cookiecutter (see practical_workshop).\n\n\n\n\n\n\nGithub documentation link\n\n\n\n\nAdding locally hosted code to Github\n\n\n\n\n\n\n\n\n\nExercise 1: initialize a repository from an existing folder:\n\n\n\n\n\n\n\n\nInitialize the repository: Begin by running the command git init in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See (git init) for more details.\nCreate a remote repository: Once the local repository is initialized, create am empty new repository on GitHub.\nConnect the remote repository: Add the GitHub repository URL to your local repository using the command git remote add origin <URL>. This associates the remote repository with the name “origin.”\nCommit changes: If you have files you want to add to your repository, stage them using git add ., then create a commit to save a snapshot of your changes with git commit -m \"add local folder\".\nPush to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using git push -u origin main.\n\n\n\n\n\n\n\n\n\nAlternatively to converting folders to repositories, you can create a new repository remotely, and then clone (git clone) it locally. Here, git init is not needed. You can move the files into the repository locally (git add, git commit, and git push). If you are creating a collaborative repository, you can now share it with your colleagues.\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nWrite useful and clear Git commits. Check out this post for tips.\n\n\n\n\n\n\n\nAfter setting up your repository on GitHub, take advantage of the opportunity to enhance it by adding your data analysis reports. Whether they are in Jupyter Notebooks, R Markdown files, or HTML reports, you can showcase them on a GitHub Page.\nOnce you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, R Markdown files, or HTML reports, in a GitHub Page website. Creating a GitHub page is very simple, and we recommend that you follow the nice tutorial that GitHub has put for you.\nFor simplicity, we recommend using Quarto or MkDocs. Visit their websites and follow the instructions to get started.\n\n\n\n\n\n\nTutorial links\n\n\n\n\nGet started in quarto: https://quarto.org/docs/get-started/. We recommend using the VS code tool, if you do, follow this tutorial.\nMkDocs materials to further customize MkDocs websites.\n\n\n\n\n\n\nWe provide an example of setting up Git, MkDocs, and a GitHub account, enabling you to replicate the process independently! (see Exercise 5 in the practical material)", "crumbs": [ "Course material", "Key practices", @@ -1374,7 +1374,7 @@ "href": "develop/05_VC.html#wrap-up", "title": "5. Data Analysis with Version Control", "section": "", - "text": "In this lesson, we explored version control and utilized Git and GitHub to establish data analysis repositories from our Project folders. Additionally, we delved into creating a GitHub organization and leveraging GitHub Pages to showcase data analysis scripts and notebooks publicly. Remember to complete the corresponding exercise from the practical workshop to reinforce your knowledge.\n\n\n\nVersion Control and Code Repository Link.", + "text": "In this lesson, we explored version control and utilized Git and GitHub to establish data analysis repositories from our Project folders. Additionally, we delved into creating a GitHub organization and leveraging GitHub Pages to showcase data analysis scripts and notebooks publicly. Remember to complete the corresponding exercise from the practical workshop to reinforce your knowledge.\n\n\n\nVersion Control and Code Repository Link.\nGit cheat sheet.", "crumbs": [ "Course material", "Key practices", @@ -1446,7 +1446,7 @@ "href": "develop/04_metadata.html#controlled-vocabularies-and-ontologies", "title": "4. Documentation for biodata", "section": "Controlled vocabularies and ontologies", - "text": "Controlled vocabularies and ontologies\nResearchers encountering inconsistent and non-standardized terms (e.g., gene names, disease names, cell types, protein domains, etc.) across datasets may face challenges in data integration. Thus, requiring additional curation time to enable meaningful comparisons. Standardized vocabularies streamline integration, improving consistency and comparability in analysis. Leveraging widely accepted ontologies in the documentation ensures consistent capture of experiment details in metadata fields, aiding data interpretation.\n\n\n\n\n\n\nExamples of ontology services\n\n\n\n\nUberon anatomy ontology\nGene ontology\nEnsembl gene IDs\nMedical Subject Headings (MeSH)\nChemical Entities of Biological Interest\nMicroarray Gene Expression Society Ontology (MGED)\nNCBI taxonomy\nMondo disease database\n\n\n\n\n\n\n\n\n\nOntology definition\n\n\n\n\n\n\n\nAn ontology is a structured framework representing concepts, attributes, and relationships within a specific domain, aiding knowledge organization and integration. Employing standardized vocabularies, it facilitates effective communication and reasoning between humans and computers. Ontologies are crucial for knowledge representation, data integration, and semantic interoperability, enhancing understanding and collaboration across complex domains.\n\n\n\n\n\nStandardization improves data discoverability and interoperability, enabling robust analysis, accelerating knowledge sharing, and facilitating cross-study comparisons. Ontologies act as universal translators, fostering harmonious data interpretation and collaboration across scientific disciplines.\nYou can find three examples of metadata tailored for different purposes NGS data examples: sample metadata, project metadata, and experimental metadata. We suggest exploring controlled vocabularies and metadata standards within your field and seeking additional specialized sources. You will find a few sources at the end of the page.", + "text": "Controlled vocabularies and ontologies\nResearchers encountering inconsistent and non-standardized terms (e.g., gene names, disease names, cell types, protein domains, etc.) across datasets may face challenges in data integration. Thus, requiring additional curation time to enable meaningful comparisons. Standardized vocabularies streamline integration, improving consistency and comparability in analysis. Leveraging widely accepted ontologies in the documentation ensures consistent capture of experiment details in metadata fields, aiding data interpretation.\n\n\n\n\n\n\nExamples of ontology services\n\n\n\n\nBiological ontologies for data scientists - Bionty\nAnatomy - Uberon\nTissue - Uberon\nChemical compoundsChemical Entities of Biological Interest\nExperimentalFactor - Experimental Factor Ontology\nSpecies - NCBI Taxonomy, Ensembl Species\nDisease - Mondo, Human Disease\nGene - Ensembl, NCBI Gene, Gene ontology,Microarray Gene Expression Society Ontology (MGED)\nProtein - Uniprot\nCellLine - Cell Line Ontology\nCellType - Cell Ontology\nCellMarker - CellMarker\nPhenotype - Human Phenotype, Phecodes, PATO, Mammalian Phenotype, Zebrafish Phenotype\nPathway - Gene Ontology, Pathway Ontology\nDevelopmentalStage - Human Developmental Stages, Mouse Developmental Stages\nDrug - Drug Ontology\nEthnicity - Human Ancestry Ontology\nBFXPipeline - largely based on nf-core\nBioSample - NCBI BioSample attributes\nArticles Indexing Medical Subject Headings (MeSH)\n\n\n\n\n\n\n\n\n\nOntology definition\n\n\n\n\n\n\n\nAn ontology is a structured framework representing concepts, attributes, and relationships within a specific domain, aiding knowledge organization and integration. Employing standardized vocabularies, it facilitates effective communication and reasoning between humans and computers. Ontologies are crucial for knowledge representation, data integration, and semantic interoperability, enhancing understanding and collaboration across complex domains.\n\n\n\n\n\nStandardization improves data discoverability and interoperability, enabling robust analysis, accelerating knowledge sharing, and facilitating cross-study comparisons. Ontologies act as universal translators, fostering harmonious data interpretation and collaboration across scientific disciplines.\nYou can find three examples of metadata tailored for different purposes NGS data examples: sample metadata, project metadata, and experimental metadata. We suggest exploring controlled vocabularies and metadata standards within your field and seeking additional specialized sources. You will find a few sources at the end of the page.", "crumbs": [ "Course material", "Key practices", @@ -1470,7 +1470,7 @@ "href": "develop/04_metadata.html#database-and-data-catalogs", "title": "4. Documentation for biodata", "section": "Database and data catalogs", - "text": "Database and data catalogs\nMetadata can be used to create data catalogs, particularly beneficial for the efficient organization of experimental or sequencing data generated by researchers. While databases can range from simple tabular formats like Excel to sophisticated DataBase Management Systems (DBMS) like SQLite, the choice depends on factors such as complexity and volume of data. Leveraging a DBMS offers advantages like efficient data storage, enhanced security, and rapid data querying capabilities.\n\nTables as databases\nA browsable table can be created by recursively navigating through a project’s folder hierarchy using a script and generating a TSV file (tab-separated values) named, for example, database_YYYYMMDD.tsv. This table acts as a centralized repository for all project data, simplifying access and organization. Consistency in metadata structure across projects is vital for efficient data management and integration, as it aids in tracking all conducted assays. Adhering to a uniform metadata format enables the seamless inclusion of essential information from YAML files into the browsable table.\n\n\n\n\n\n\nExercise 2: Generate database tables from metadata\n\n\n\n\n\n\n\nWrite a script (R or Python) that recursively fetches metadata.yml files in a given path. It is important that each subdirectory contains its corresponding metadata.yml.\nRequirements:\n\nData folder structure: containing all project folders\nYAML metadata files associated with each project\n\nClick on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nquiet <- function(x) { suppressMessages(suppressWarnings(x)) }\nquiet(library(yaml))\nquiet(library(dplyr))\nquiet(library(lubridate))\n\n# Function to recursively fetch metadata.yml files\nget_metadata <- function(folder_path) {\n file_list <- list.files(path = folder_path, \n pattern = \"metadata\\\\.yml$\", \n recursive = TRUE, full.names = TRUE)\n metadata_list <- lapply(file_list, yaml::yaml.load_file)\n return(metadata_list)\n}\n\n# Specify the folder path\nfolder_path <- \"/path/to/your/folder\"\n\n# Fetch metadata from the specified folder\nmetadata <- get_metadata(folder_path)\n\n# Convert metadata to a data frame\nmetadata_df <- data.frame(matrix(unlist(metadata), \nncol = length(metadata), byrow = TRUE))\ncolnames(metadata_df) <- names(metadata[[1]])\n\n# Save the data frame as a TSV file\noutput_file <- paste0(\"database_\", format(Sys.Date(), \"%Y%m%d\"), \".tsv\")\nwrite.table(metadata_df, \n file = output_file, \n sep = \"\\t\", \n quote = FALSE, \n row.names = FALSE)\n\n# Print confirmation message\nprint(\"Database saved as\", output_file, \"\\n\")\n\n\n\n\n\n\n\n\n\n\n\n\nSQLite database\nAn alternative to the tabular format is SQLite, a lightweight and self-contained relational database management system known for its simplicity and efficiency. SQLite operates without the need for a separate server, making it ideal for scenarios requiring minimal resource usage. It excels in tasks involving structured data storage and retrieval, making it suitable for managing experiment metadata. Similar to the previous example, you can use a script that records all the information from the YAML file in a SQLite database.\n\n\n\n\n\n\nAdvantages of using SQLite database\n\n\n\n\nEfficient Querying: SQLite databases optimize querying and data retrieval, enabling fast and efficient extraction of specific information.\nStructured Organization: Databases provide structured and organized data storage, ensuring easy access and maintenance.\nData Integrity: SQLite databases enforce data integrity through constraints and validations, minimizing errors and inconsistencies.\nConcurrency and Multi-User Support: SQLite supports concurrent read access from multiple users, ensuring accessibility without compromising data integrity.\nScalability: It can handle growing volumes of data without significant performance degradation.\nModularity and Portability: Databases are self-contained and modular, simplifying data distribution and portability.\nSecurity and Access Control: SQLite offers security features like password protection and encryption, with granular control over user access.\nIndexing: Support for indexing accelerates data retrieval based on specific columns, particularly beneficial for large datasets.\nData Relationships: Databases allow for the establishment of relationships between tables, facilitating storage of interconnected data, such as project, assay, and sample information.\n\n\n\n\n\n\n\n\n\nExercise 3: Generate a SQLite database from metadata\n\n\n\n\n\n\n\nClick on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nquiet <- function(x) { suppressMessages(suppressWarnings(x)) }\nquiet(library(yaml))\nquiet(library(dplyr))\nquiet(library(lubridate))\nquiet(library(DBI))\n\n# Generate the metadata_df using the script from the example above (recursively fetching metadata.yml files)\n\n# Create an SQLite database and insert data\ndb_file <- paste0(\"database_\", format(Sys.Date(), \"%Y%m%d\"), \".sqlite\")\ncon <- dbConnect(SQLite(), db_file)\n\ndbWriteTable(con, \"metadata\", metadata_df, row.names = FALSE)\n\n# Print confirmation message\ncat(\"Database saved as\", db_file, \"\\n\")\n\n# Close the database connection\ndbDisconnect(con)\n\n\n\n\n\n\n\n\n\n\n\n\nCatalog browser\nYou can design a user-friendly catalog browser for your database using tools like Rshiny or Panel. These frameworks provide interfaces for dynamic search, filtering, and visualization, facilitating efficient exploration of database contents. Creating such a tool with Rshiny from both a TSV file and a SQLite database will be demonstrated below.\nHere’s an example of an SQLite database catalog created by the Brickman Lab at the Center for Stem Cell Medicine. It’s simple yet effective! Clicking on a data row opens the metadata.yml file, allowing access to detailed metadata for that assay.\n\n\nVideo\ntype:video\n\n\n\n\n\n\n\n\nExercise 4: Create your first catalog browser using Rshiny\n\n\n\n\n\n\n\nClick on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration.\n\nSolution A. From a TSV\n\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nR script\n\nquiet <- function(x) { suppressMessages(suppressWarnings(x)) }\nquiet(library(shiny))\nquiet(library(DT))\n\n# UI\nui <- fluidPage(\n titlePanel(\"TSV File Viewer\"),\n \n sidebarLayout(\n sidebarPanel(\n fileInput(\"file\", \"Choose a TSV file\", accept = c(\".tsv\"))\n ),\n \n mainPanel(\n DTOutput(\"table\")\n )\n )\n)\n\n# Server\nserver <- function(input, output) {\n \n data <- reactive({\n req(input$file)\n read.delim(input$file$datapath, sep = \"\\t\")\n })\n \n output$table <- renderDT({\n datatable(data())\n })\n}\n\n# Run the app\nshinyApp(ui, server)\n\n\n\n\n\n\nSolution B. From an SQLite database\n\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nR script\nquiet <- function(x) { suppressMessages(suppressWarnings(x)) }\nquiet(library(shiny))\nquiet(library(DT))\nquiet(library(DBI))\n\n# UI\nui <- fluidPage(\n titlePanel(\"SQLite Database Viewer\"),\n \n sidebarLayout(\n sidebarPanel(\n fileInput(\"db_file\", \"Choose an SQLite Database\", accept = c(\".sqlite\")),\n textInput(\"table_name\", \"Enter Table Name:\", value = \"\"),\n actionButton(\"load_button\", \"Load Table\")\n ),\n \n mainPanel(\n DTOutput(\"table\")\n )\n )\n)\n\n# Server\nserver <- function(input, output, session) {\n \n con <- reactive({\n if (!is.null(input$db_file)) {\n dbConnect(SQLite(), input$db_file$datapath)\n }\n })\n \n data <- reactive({\n req(input$load_button > 0, input$table_name, con())\n query <- glue::glue_sql(\"SELECT * FROM {dbQuoteIdentifier(con(), input$table_name)}\")\n dbGetQuery(con(), query)\n })\n \n output$table <- renderDT({\n datatable(data())\n })\n \n observeEvent(input$load_button, {\n output$table <- renderDT({\n datatable(data())\n })\n })\n \n # Disconnect from the database when app closes\n observe({\n on.exit(dbDisconnect(con()), add = TRUE)\n })\n}\n\n# Run the app\nshinyApp(ui, server)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nExercise 5: Add complex features to your catalog browser\n\n\n\n\n\n\n\nOnce you’ve finished the previous exercise, consider implementing these additional ideas to maximize the utility of your catalog browser.\n\nAdd a tab to create a project directory interactively (and fill up the metadata fields)\nModify existing entries\nVisualize results using Cirrocumulus", + "text": "Database and data catalogs\nMetadata can be used to create data catalogs, particularly beneficial for the efficient organization of experimental or sequencing data generated by researchers. While databases can range from simple tabular formats like Excel to sophisticated DataBase Management Systems (DBMS) like SQLite, the choice depends on factors such as complexity and volume of data. Leveraging a DBMS offers advantages like efficient data storage, enhanced security, and rapid data querying capabilities.\n\nTables as databases\nA browsable table can be created by recursively navigating through a project’s folder hierarchy using a script and generating a TSV file (tab-separated values) named, for example, database_YYYYMMDD.tsv. This table acts as a centralized repository for all project data, simplifying access and organization. Consistency in metadata structure across projects is vital for efficient data management and integration, as it aids in tracking all conducted assays. Adhering to a uniform metadata format enables the seamless inclusion of essential information from YAML files into the browsable table.\n\n\n\n\n\n\nExercise 2: Generate database tables from metadata\n\n\n\n\n\n\n\nWrite a script (R or Python) that recursively fetches metadata.yml files in a given path. It is important that each subdirectory contains its corresponding metadata.yml.\nRequirements:\n\nData folder structure: containing all project folders\nYAML metadata files associated with each project\n\nClick on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration.\nYou can find a thorough guided exercise in the practical material - Exercise 4.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\n# Load required packages\npackages <- c(\"yaml\", \"ggplot2\", \"lubridate\")\n\n# Function to recursively fetch YAML files files, read and convert them to a data frame\n\ndf = lapply(file_list, yaml::yaml.load_file)\n\n# Save the data frame as a TSV file\n\n\n\n\n\n\n\n\n\n\n\n\nSQLite database\nAn alternative to the tabular format is SQLite, a lightweight and self-contained relational database management system known for its simplicity and efficiency. SQLite operates without the need for a separate server, making it ideal for scenarios requiring minimal resource usage. It excels in tasks involving structured data storage and retrieval, making it suitable for managing experiment metadata. Similar to the previous example, you can use a script that records all the information from the YAML file in a SQLite database.\n\n\n\n\n\n\nAdvantages of using SQLite database\n\n\n\n\nEfficient Querying: SQLite databases optimize querying and data retrieval, enabling fast and efficient extraction of specific information.\nStructured Organization: Databases provide structured and organized data storage, ensuring easy access and maintenance.\nData Integrity: SQLite databases enforce data integrity through constraints and validations, minimizing errors and inconsistencies.\nConcurrency and Multi-User Support: SQLite supports concurrent read access from multiple users, ensuring accessibility without compromising data integrity.\nScalability: It can handle growing volumes of data without significant performance degradation.\nModularity and Portability: Databases are self-contained and modular, simplifying data distribution and portability.\nSecurity and Access Control: SQLite offers security features like password protection and encryption, with granular control over user access.\nIndexing: Support for indexing accelerates data retrieval based on specific columns, particularly beneficial for large datasets.\nData Relationships: Databases allow for the establishment of relationships between tables, facilitating storage of interconnected data, such as project, assay, and sample information.\n\n\n\n\n\n\n\n\n\nExercise 3: Generate a SQLite database from metadata\n\n\n\n\n\n\n\nClick on the hint to reveal the necessary libraries and some functions, which may serve as inspiration.\nYou can find a thorough guided exercise, complete with code example, in the practical material - Exercise 4, option B.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\n# Load required packages\npackages <- c(\"yaml\", \"ggplot2\", \"lubridate\", \"DBI\")\n\n# Function to recursively fetch YAML files files, read and convert them to a data frame\n\ndf = lapply(file_list, yaml::yaml.load_file)\n\n# Create an SQLite database from a dataframe and insert data\ndbConnect(SQLite(), \"filenameXXX.sqlite\")\ndbWriteTable()\n\n\n\n\n\n\n\n\n\n\n\n\nCatalog browser\nTo further optimize the use of your metadata and improve the integration of all your lab metadata, you can design a user-friendly catalog browser for your database using tools like Rshiny or Panel. These frameworks provide interfaces for dynamic search, filtering, and visualization, facilitating efficient exploration of database contents.\nCreating such a tool with RShiny is straightforward and does not require extensive development knowledge, whether using a TSV file or a SQLite database. In the practical materials, we demonstrate both scenarios and showcase various functionalities for inspiration. SQLite files are particularly advantageous for data fetching and other operations due to their efficient querying and indexing capabilities.\nHere’s an example of an SQLite database catalog created by the Brickman Lab at the Center for Stem Cell Medicine. It’s simple yet effective! Clicking on a data row opens the metadata.yml file, allowing access to detailed metadata for that assay.\n\n\nVideo\ntype:video\n\n\n\n\n\n\n\n\nExercise 4: Create your first catalog browser using Rshiny\n\n\n\n\n\n\n\nGo to the practical material for complete exercise instructions and solutions. The code provided can serve as inspiration for you to adapt as needed.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nThese are some of the libraries required: install.packages(c(\"shiny\", \"DT\", \"DBI\"))\nYou need to define both a user interface (UI) and a server function. The UI (fluidPage()) outlines the app’s layout using for example, the sidebarLayout() and mainPanel() functions for input controls and output displays.\nThe server function manages data manipulation and user interactions. Use shinyApp() to launch the app once the UI and server are set up.\nHere is a simple example of a server function settup including the main parts (additional components provide advanced functionalities):\n server <- function(input, output, session) {\n # Define a reactive expression for data based on user inputs\n data <- reactive({\n req(input$dataInput) # Ensure data input is available\n # Load or manipulate data here\n })\n\n # Define an output table based on data\n output$dataTable <- renderTable({\n data() # Render the data as a table\n })\n\n # Observe a button click event and perform an action\n observeEvent(input$actionButton, {\n # Perform an action when the button is clicked\n })\n\n # Define cleanup tasks when the app stops\n onStop(function() {\n # Close connections or save state if necessary\n })\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nExercise 5: Add complex features to your catalog browser\n\n\n\n\n\n\n\nOnce you’ve finished the previous exercise, consider implementing these additional ideas to maximize the utility of your catalog browser.\n\nAdd a functionality to only select certain columns uiOutput(\"column_select\")\nAdd buttons to order numeric columns ascending or descending using radioButtons()\nUse SQL aggregation functions (e.g., SUM, COUNT, AVG) to perform custom data summaries and calculations.\nAdd a tab tabPanel() to create a project directory interactively (and fill up the metadata fields), tips: dir.create(), data.frame(), write.table()\nModify existing entries\nVisualize results using Cirrocumulus, an interactive visualization tool for large-scale single-cell genomics data.\n\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nExplore this example with advanced features such as a two-tab layout, filtering by numeric values and matching strings, and a color-customized dashboard here.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTip\n\n\n\n\nFor R Enthusiasts Explore demosfrom the R Shiny community to kickstart your projects or for inspiration.\nFor python Enthusiasts If you want to dive deeper into Shiny apps and their various uses (such as dynamic plots or other interactive widgets), Shiny for Python provides live, interactive code throughout its entire tutorial. Additionally, it offers a great tool called Playground, where you can code and test your own app to explore how different features render.", "crumbs": [ "Course material", "Key practices", @@ -1530,7 +1530,7 @@ "href": "develop/06_pipelines.html#wrap-up", "title": "6. Processing and analyzing biodata", "section": "Wrap up", - "text": "Wrap up\nThis lesson emphasized the importance of reproducibility in computational research and provided practical techniques for achieving it. Using annotated notebooks, pipeline frameworks, and community-curated pipelines, such as those developed by the nf-core community, enhances reproducibility and readability.\n\nSources\n\nRDMkit, Elixir Data Management - Data Analysis\nCode documentation by Johns Hopkins Sheridan libraries. This link includes best practices for code documentation, style guides, R markdown, Jupyter Notebook, version control, and code repository.\nGuide to reproducible code in ecology and evolution\nBest practices for Scientific computing\nElixir Software Best Practices", + "text": "Wrap up\nThis lesson emphasized the importance of reproducibility in computational research and provided practical techniques for achieving it. Using annotated notebooks, pipeline frameworks, and community-curated pipelines, such as those developed by the nf-core community, enhances reproducibility and readability.\n\nSources\n\nRDMkit, Elixir Data Management - Data Analysis\nCode documentation by Johns Hopkins Sheridan libraries. This link includes best practices for code documentation, style guides, R markdown, Jupyter Notebook, version control, and code repository.\nGuide to reproducible code in ecology and evolution\nBest practices for Scientific computing\nElixir Software Best Practices\nfaircookbook worflows", "crumbs": [ "Course material", "Key practices", @@ -1541,22 +1541,22 @@ "objectID": "index.html#research-data-management-for-biological-data", "href": "index.html#research-data-management-for-biological-data", "title": "Computational Research Data Management", - "section": "", - "text": "The course “Research Data Management (RDM) for biological data” is designed to provide participants with foundational knowledge and practical skills in handling the extensive data generated by modern studies, with a focus on Next Generation Sequencing (NGS) data. It emphasizes the importance of Open Science and FAIR principles in managing data effectively. This course covers essential principles and best practices guidelines in data organization, metadata annotation, version control, and data preservation. These principles are explored from a computational perspective, ensuring participants gain hands-on experience in applying them to real-world scenarios in their research labs. Additionally, the course delves into FAIR principles and Open Science, promoting collaboration and reproducibility in research endeavors. By the course’s conclusion, attendees will possess essential tools and techniques to address the data challenges prevalent in today’s NGS research landscape, as well as in other related fields to health and bioinformatics.\n\n\n\n\n\n\nCourse Overview\n\n\n\n\n📖 Syllabus:\n\n\nData Lifecycle Management\nData Management Plans (DMPs)\nData Organization and storage\nDocumentation standards for biodata\nVersion Control and Collaboration\nProcessing and analyzing biodata\nStoring and sharing biodata\n\n\n⏰ Total Time Estimation: X hours\n\n📁 Supporting Materials:\n\n👨‍💻 Target Audience: Ph.D., MSc, anyone interested in RDM for NGS data or other related fields within bioinformatics.\n👩‍🎓 Level: Beginner.\n🔒 License: Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.\n\n💰 Funding: This project was funded by the Novo Nordisk Fonden (NNF20OC0063268).\n\n\n\n\n\n\n\n\n\n\nCourse Requirements\n\n\n\n\nBasic understanding Next Generation Sequencing data and formats.\nCommand Line experience\nBasic programming experience\nQuarto or Mkdocs tools\n\n\n\nThis course offers participants with an in-depth introduction to effectively managing the vast amounts of data generated in modern studies. Throughout the program, emphasis is placed on practical understanding of RDM principles and the importance of efficient handling of large datasets. In this context, participants will learn the necessity of adopting Open Science and FAIR principles for enhancing data accessibility and reusability.\nParticipants will acquire practical skills for organizing data, including the creation of folder and file structures, and the implementation of metadata to facilitate data discoverability and interpretation. Special attention is given to the development of Data Management Plans (DMPs) with examples tailored to omics data, ensuring compliance with institutional and funding agency requirements while maintaining data integrity. Attendees will also gain insights into the establishment of simple databases and the use of version control systems to track changes in data analysis, thereby promoting collaboration and reproducibility.\nThe course concludes with a focus on archiving and data repositories, enabling participants to learn strategies for preserving and sharing data for long-term scientific usage. By the end of the course, attendees will be equipped with essential tools and techniques to effectively navigate the challenges prevalent in today’s research landscape. This will not only foster successful data management practices but also enhance collaboration within the scientific community.\n\n\n\n\n\n\nCourse Goals\n\n\n\nBy the end of this workshop, you should be able to apply the following concepts in the context of Next Generation Sequencing data:\n\nUnderstand the Importance of Research Data Management (RDM)\nFamiliarize Yourself with FAIR and Open Science Principles\nDraft a Data Management Plan for your own Data\nEstablish File and Folder Naming Conventions\nEnhance Data with Descriptive Metadata\nImplement Version Control for Data Analysis\nSelect an Appropriate Repository for Data Archiving\nMake your data analysis and workflows reproducible and FAIR\n\n\n\n\n\n\n\n\n\nWarning\n\n\n\nThis is a computational workshop that focuses primarily on the digital aspect of our data. While wet lab Research Data Management (RDM) involving protocols, instruments, reagents, ELM or LIMS systems is integral to the entire RDM process, it won’t be covered in this course.\nAs part of effective data management, it’s crucial to prioritize strategies that ensure security and privacy. While these aspects are important, please note that they won’t be covered in our course. However, we highly recommend enrolling in the GDPR course offered by Center for Health Data Science, specially if you’re working with sensitive data. This course specifically focuses on GDPR compliance and will provide you with valuable insights and skills in managing data privacy and security.\n\n\n\n\n\nUniversity of Copenhagen\nUniversity Library of Southern Denmark\nTechnical University of Denmark\nAalborg University\nAarhus University\n\n\n\n\n\nRDMkit, ELIXIR (2021) Research Data Management Kit. A deliverable from the EU-funded ELIXIR-CONVERGE project (grant agreement 871075).\nUniversity of Copenhagen Research Data Management Team.\nMartin Proks and Sarah Lundregan, Brickman Lab, NNF Center for Stem Cell Biology (reNEW), University of Copenhagen.\nRichard Dennis, Data Steward, NNF Center for Stem Cell Biology (reNEW), University of Copenhagen.\nNBISweden." + "section": "Research Data Management for biological data", + "text": "Research Data Management for biological data\nThe course “Research Data Management (RDM) for biological data” is designed to provide participants with foundational knowledge and practical skills in handling the extensive data generated by modern studies, with a focus on Next Generation Sequencing (NGS) data. It emphasizes the importance of Open Science and FAIR principles in managing data effectively. This course covers essential principles and best practices guidelines in data organization, metadata annotation, version control, and data preservation. These principles are explored from a computational perspective, ensuring participants gain hands-on experience in applying them to real-world scenarios in their research labs. Additionally, the course delves into FAIR principles and Open Science, promoting collaboration and reproducibility in research endeavors. By the course’s conclusion, attendees will possess essential tools and techniques to address the data challenges prevalent in today’s NGS research landscape, as well as in other related fields to health and bioinformatics.\n\n\n\n\n\n\nCourse Overview\n\n\n\n\n📖 Syllabus:\n\n\nData Lifecycle Management\nData Management Plans (DMPs)\nData Organization and storage\nDocumentation standards for biodata\nVersion Control and Collaboration\nProcessing and analyzing biodata\nStoring and sharing biodata\n\n\n⏰ Total Time Estimation: X hours\n\n📁 Supporting Materials:\n\n👨‍💻 Target Audience: Ph.D., MSc, anyone interested in RDM for NGS data or other related fields within bioinformatics.\n👩‍🎓 Level: Beginner.\n🔒 License: Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.\n\n💰 Funding: This project was funded by the Novo Nordisk Fonden (NNF20OC0063268).\n\n\n\n\n\n\n\n\n\n\nCourse Requirements\n\n\n\n\nBasic understanding Next Generation Sequencing data and formats.\nCommand Line experience\nBasic programming experience\nQuarto or Mkdocs tools\n\n\n\nThis course offers participants with an in-depth introduction to effectively managing the vast amounts of data generated in modern studies. Throughout the program, emphasis is placed on practical understanding of RDM principles and the importance of efficient handling of large datasets. In this context, participants will learn the necessity of adopting Open Science and FAIR principles for enhancing data accessibility and reusability.\nParticipants will acquire practical skills for organizing data, including the creation of folder and file structures, and the implementation of metadata to facilitate data discoverability and interpretation. Special attention is given to the development of Data Management Plans (DMPs) with examples tailored to omics data, ensuring compliance with institutional and funding agency requirements while maintaining data integrity. Attendees will also gain insights into the establishment of simple databases and the use of version control systems to track changes in data analysis, thereby promoting collaboration and reproducibility.\nThe course concludes with a focus on archiving and data repositories, enabling participants to learn strategies for preserving and sharing data for long-term scientific usage. By the end of the course, attendees will be equipped with essential tools and techniques to effectively navigate the challenges prevalent in today’s research landscape. This will not only foster successful data management practices but also enhance collaboration within the scientific community.\n\n\n\n\n\n\nCourse Goals\n\n\n\nBy the end of this workshop, you should be able to apply the following concepts in the context of Next Generation Sequencing data:\n\nUnderstand the Importance of Research Data Management (RDM)\nFamiliarize Yourself with FAIR and Open Science Principles\nDraft a Data Management Plan for your own Data\nEstablish File and Folder Naming Conventions\nEnhance Data with Descriptive Metadata\nImplement Version Control for Data Analysis\nSelect an Appropriate Repository for Data Archiving\nMake your data analysis and workflows reproducible and FAIR\n\n\n\n\n\n\n\n\n\nWarning\n\n\n\nThis is a computational workshop that focuses primarily on the digital aspect of our data. While wet lab Research Data Management (RDM) involving protocols, instruments, reagents, ELM or LIMS systems is integral to the entire RDM process, it won’t be covered in this course.\nAs part of effective data management, it’s crucial to prioritize strategies that ensure security and privacy. While these aspects are important, please note that they won’t be covered in our course. However, we highly recommend enrolling in the GDPR course offered by Center for Health Data Science, specially if you’re working with sensitive data. This course specifically focuses on GDPR compliance and will provide you with valuable insights and skills in managing data privacy and security.\n\n\n\nDanish institutional RDM links\n\nUniversity of Copenhagen\nUniversity Library of Southern Denmark\nTechnical University of Denmark\nAalborg University\nAarhus University\n\n\n\nAcknowledgements\n\nRDMkit, ELIXIR (2021) Research Data Management Kit. A deliverable from the EU-funded ELIXIR-CONVERGE project (grant agreement 871075).\nUniversity of Copenhagen Research Data Management Team.\nMartin Proks and Sarah Lundregan, Brickman Lab, NNF Center for Stem Cell Biology (reNEW), University of Copenhagen.\nRichard Dennis, Data Steward, NNF Center for Stem Cell Biology (reNEW), University of Copenhagen.\nNBISweden." }, { "objectID": "practical_workflows.html#snakemake", "href": "practical_workflows.html#snakemake", - "title": "Workflows", + "title": "FAIR Workflows", "section": "Snakemake", "text": "Snakemake\nIt is a text-based tool using python-based language plus domain specific syntax. The workflow is decompose into rules that are define to obtain output files from input files. It infers dependencies and the execution order.\n\nBasics\n\nDefine rules\nGeneralise the rule: creating wildcards You can refer by index or by name\nDependencies are determined top-down\n\nFor a given target, a rule that can be applied to create it, is determined (a job) For the input files of the rule, go on recursively, If no target is specified, snakemake , tries to apply the first rule\n\nRule all: target rule that collects results\n\n\n\nJob execution\nA job is executed if and only if: - otuput file is target and does not exist - output file needed by another executed job and does not exist - input file newer than output file - input file will be updated by other job (eg. changes in rules) - execution is force (‘–force-all’)\nYou can plot the DAG (directed acyclic graph) of the jobs\n\n\nUseful command line interface\n# dry-run (-n), print shell commands (-p)\nsnakemake -n -p\n# Snakefile named different in another location \nsnakemake --snakefile path/to/file.smoker\n# dry-run (-n), print execution reason for each job\nsnakemake -n -r\n# Visualise DAG of jobs using Graphviz dot command\nsnakemake --dag | dot -Tsvg > dag.svg\n\n\nDefining resources\nrule myrule:\n resources: mem_mb= 100 #(100MB memory allocation)\n threads: X\n shell:\n \"command {threads}\"\nLet’s say you defined our rule myrule needs 4 works, if we execute the workflow with 8 cores as follows:\nsnakemake --cores 8\nThis means that 2 ‘myrule’ jobs, will be executed in parallel.\nThe jobs are schedules to maximize parallelization, high priority jobs will be scheduled first, all while satisfying resource constrains. This means:\nIf we allocate 100MB for the execution of ‘myrule’ and we call snakemake as follows:\nsnakemake --resources mem_mb=100 --cores 8\nOnly one ‘myrule’ job can be executed in parallel (you do not provide enough memory resources for 2). The memory resources is useful for jobs that are heavy memory demanding to avoid running out of memory. You will need to benchmark your pipeline to estimate how much memory and time your full workflow will take. We highly recommend doing so, get a subset of your dataset and give it a go! Log files will come very handy for the resource estimation. Of course, the execution of jobs is dependant on the free resources availability (eg. CPU cores).\nrule myrule:\n log: \"logs/myrule.log\"\n threads: X\n shell:\n \"command {threads}\"\nLog files need to define the same wildcards as the output files, otherwise, you will get an error.\n\n\nConfig files\nYou can also define values for wildcards or parameters in the config file. This is recommended when the pipeline might be used several times at different time points, to avoid unwanted modifications to the workflow. parameterization is key for such cases.\n\n\nCluster execution\nWhen working from cluster systems you can execute the workflow using -qsub submission command\nsnakemake --cluster qsub \n\n\nAdditional advanced features\n\nmodularization\nhandling temporary and protected files: very important for intermediate files that filled up our memory and are not used in the long run and can be deleted once the final output is generated. This is automatically done by snakemake if you defined them in your pipeline HTML5 reports\nrule parameters\ntracking tool versions and code changes: will force rerunning older jobs when code and software are modified/updated.\ndata provenance information per file\npython API for embedding snakemake in other tools\n\n\n\nCreate an isolated environment to install dependencies\nBasic file structure\n| - config.yml\n| - requirements.txt (commonly also named environment.txt)\n| - rules/\n| | - myrules.smk\n| - scripts/\n| | - script1.py\n| - Snakefile\nCreate conda environment, one per project!\n# create env\nconda create -n myworklow --file requirements.txt\n# activate environment\nsource activate myworkflow\n# then execute snakemake\nUse git repositories to save your projects and pipelines!" }, { "objectID": "practical_workflows.html#sources", "href": "practical_workflows.html#sources", - "title": "Workflows", + "title": "FAIR Workflows", "section": "Sources", - "text": "Sources\n\nSnakemake tutorial\nSnakemake turorial slides by Johannes Koster\nhttps://bioconda.github.io\nKöster, Johannes and Rahmann, Sven. “Snakemake - A scalable bioinformatics workflow engine”. Bioinformatics 2012.\nKöster, Johannes. “Parallelization, Scalability, and Reproducibility in Next-Generation Sequencing Analysis”, PhD thesis, TU Dortmund 2014." + "text": "Sources\n\nSnakemake tutorial\nSnakemake turorial slides by Johannes Koster\nhttps://bioconda.github.io\nKöster, Johannes and Rahmann, Sven. “Snakemake - A scalable bioinformatics workflow engine”. Bioinformatics 2012.\nKöster, Johannes. “Parallelization, Scalability, and Reproducibility in Next-Generation Sequencing Analysis”, PhD thesis, TU Dortmund 2014.\nfaircookbook worflows" }, { "objectID": "develop/practical_workshop.html#create-a-catalog-of-your-assay-folder", @@ -1580,7 +1580,7 @@ { "objectID": "practical_workflows.html#nextflow", "href": "practical_workflows.html#nextflow", - "title": "Workflows", + "title": "FAIR Workflows", "section": "Nextflow", "text": "Nextflow" }, @@ -1601,14 +1601,14 @@ "href": "develop/practical_workshop.html#organize-and-structure-your-datasets-and-data-analysis", "title": "Practical material", "section": "1. Organize and structure your datasets and data analysis", - "text": "1. Organize and structure your datasets and data analysis\nEstablishing a consistent file structure and naming conventions will help you efficiently manage your data. We will classify your data and data analyses into two distinct types of folders to ensure the data can be used and shared by many lab members while preventing modifications by any individual:\n\nData folders (assay or external databases and resources): They house the raw and processed datasets, alongside the pipeline/workflow used to generate the processed data, the provenance of the raw data, and quality control reports of the data. The data should be locked and set to read-only to prevent unintended modifications. This applies to experimental data generated in your lab as well as external resources. Provide an MD5 checksum file when you download them yourself to verify their integrity.\nProject folders: They contain all the essential files for a specific research project. Projects may use data from various resources or experiments, or build upon previous results from other projects. The data should not be copied or duplicated, instead, it should be linked directly from the source.\n\nData and data analysis are kept separate because a project may utilize one or more datasets to address a scientific question. Data can be reused in multiple projects over time, combined with other datasets for comparison, or used to build larger datasets. Additionally, data may be utilized by different researchers to answer various research questions.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nWhen organizing your data folders, separate assays from external resources and maintain a consistent structure. For example, organize genome references by species and further categorize them by versions. Make sure to include all relevant information, and refer to this lesson for additional tips on data organization.\nThis will help you to keep your data tidied up, especially if you are working in a big lab where assays may be used for different purposes and by different people!\n\n\n\n\n\n\nData folders\nWhether your lab generates its own experimental data, receives it from collaborators, or works with previously published datasets, the data folder should follow a similar structure to the one presented here. Create a separate folder for each dataset, including raw files and processed files alongside the corresponding documentation and pipeline that generated the processed data. Raw files should remain untouched, and you should consider locking modifications to the final results once data preprocessing is complete. This precaution helps prevent unwanted changes to the data. Each subfolder should be named in a way that is distinct, easily readable and clear at a glance. Check this lesson for tips on naming conventions.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nUse an acronym (1) that describes the type of NGS assay (RNAseq, ChIPseq, ATACseq) a keyword (2) that represents a unique element to that assay, and the date (3).\n<Assay-ID>_<keyword>_YYYYMMDD\nFor example CHIP_Oct4_20230101 is a ChIPseq assay made on 1st January 2023 with the keyword Oct4, so it is easily identifiable by the eye.\n\n\n\n\n\nLet’s explore a potential folder structure and the types of files you might encounter within it.\n<data_type>_<keyword>_YYYYMMDD/\n├── README.md \n├── CHECKSUMS\n├── pipeline\n ├── pipeline.md\n ├── scripts/\n├── processed\n ├── fastqc/\n ├── multiqc/\n ├── final_fastq/\n└── raw\n ├── .fastq.gz \n └── samplesheet.csv\n\nREADME.md: This file contains a detailed description of the dataset commonly in markdown format. It should include the provenance of the raw data (such as samples, laboratory protocols used, the aim of the project, folder structure, naming conventions, etc.).\nmetadata.yml: This metadata file outlines different keys and essential information, usually presented in YAML format. For more details, refer to this lesson.\npipeline.md: This file provides an overview of the pipeline used to process raw data, as well as the commands to run the pipeline. The pipeline itself and all the required scripts should be collected in the same directory.\nprocessed: This folder contains the results from the preprocessing pipeline. The content vary depending on the specific pipeline used (create additional subdirectories as needed).\nraw: This folder holds the raw data.\n\n.fastq.gz: For example, in NGS assays, there should be ‘fastq’ files.\nsamplesheet.csv: This file holds essential metadata for the samples, including sample identification, experimental variables, batch information, and other metrics crucial for downstream analysis. It is important that this file is complete and current, as it is key to interpreting results. If you are considering running nf-core pipelines, this file will be required.\n\n\n\n\nProject folders\nOn the other hand, we have another type of folder called Projects which refers to data analyses that are specific to particular tasks, such as those involved in preparing a potential article. In this folder, you will create a subfolder for each project that you or your lab is working on. Each Project subfolder should include project-specific information, data analysis pipelines, notebooks, and scripts used for that particular project. Additionally, you should include an environment file with all the required software and dependencies needed for the project, including their versions. This helps ensure that the analyses can be easily replicated and shared with others.\nThe Project folder should be named in a way that is unique, easy to read, distinguishable, and clear at a glance. For example, you might name it based on the main author’s initials, the dataset being analyzed, the project name, a unique descriptive element related to the project, or the part of the project you are responsible for, along with the date:\n<project>_<keyword>_YYYYMMDD\n\n\n\n\n\n\nNaming examples\n\n\n\n\n\n\n\n\nRNASeq_Mouse_Brain_20230512: a project RNA sequencing data from a mouse brain experiment, created on May 12, 2023\nEHR_COVID19_Study_20230115: a project around electronic health records data for a COVID-19 study, created on January 15, 2023.\n\n\n\n\n\n\nNow, let’s explore an example of a folder structure and the types of files you might encounter within it.\n<project>_<keyword>_YYYYMMDD\n├── data\n│ └── <ID>_<keyword>_YYYYMMDD <- symbolic link\n├── documents\n│ └── research_project_template.docx\n├── metadata.yml\n├── notebooks\n│ └── 01_data_processing.rmd\n│ └── 02_data_analysis.rmd\n│ └── 03_data_visualization.rmd\n├── README.md\n├── reports\n│ └── 01_data_processing.html\n│ └── 02_data_analysis.html\n│ ├── 03_data_visualization.html\n│ │ └── figures\n│ │ └── tables\n├── requirements.txt // env.yaml\n├── results\n│ ├── figures\n│ │ └── 02_data_analysis/\n│ │ └── heatmap_sampleCor_20230102.png\n│ ├── tables\n│ │ └── 02_data_analysis/\n│ │ └── DEA_treat-control_LFC1_p01.tsv\n│ │ └── SumStats_sampleCor_20230102.tsv\n├── pipeline\n│ ├── rules // processes \n│ │ └── step1_data_processing.smk\n│ └── pipeline.md\n├── scratch\n└── scripts\n\ndata: This folder contains symlinks or shortcuts to the actual data files, ensuring that the original files remain unaltered.\ndocuments: This folder houses Word documents, slides, or PDFs associated with the project, including data and project explanations, research papers, and more. It also includes the Data Management Plan.\n\nresearch_project_template.docx. If you download our template you will find a is a pre-filled Data Management Plan based on the Horizon Europe guidelines named ‘Non-sensitive_NGS_research_project_template.docx’.\n\nmetadata.yml: metadata file describing various keys of the project or experiment (see this lesson).\nnotebooks: This folder stores Jupyter, R Markdown, or Quarto notebooks containing the data analysis. Figures and tables used for the reports are organized under subfolders named after the notebook that created them for provenance purposes.\nREADME.md: A detailed project description in markdown or plain-text format.\nreports: Notebooks rendered as HTML, docx, or PDF files for sharing with colleagues or as formal data analysis reports.\n\nfigures: figures produced upon rendering notebooks. The figures will be saved under a subfolder named after the notebook that created them. This is for provenance purposes so we know which notebook created which figures.\n\nrequirements.txt: This file lists the necessary software, libraries, and their versions required to reproduce the code. If you’re using conda environments, you will also find the env.yaml file here, which outlines the specific environment configuration.\nresults: This folder contains analysis results, such as figures and tables. Organizing results by the pipeline, script, or notebook that generated them will make it easier to locate and interpret the data.\npipeline: A folder containing pipeline scripts or workflows for processing and analyzing data.\nscratch: A folder designated for temporary files or workspace for experiments and development.\nscripts: Folder for helper scripts needed to run data analysis or reproduce the work.\n\n\n\nTemplate engine\nCreating a folder template is straightforward with cookiecutter a command-line tool that generates projects from templates (called cookiecutters). For example, it can help you set up a Python package project based on a Python package project template.\n\n\n\n\n\n\nCookiecutter templates\n\n\n\nHere are some template that you can use to get started, adapt and modify them to your own needs:\n\nPython package project\nSandbox test\nData science\nNGS data\n\nCreate your own template from scratch.\n\n\n\nQuick tutorial on cookiecutter\nBuilding a Cookiecutter template from scratch requires defining a folder structure, crafting a cookiecutter.json file, and outlining placeholders (keywords) that will be substituted when generating a new project. Here’s a step-by-step guide on how to proceed:\n\nStep 1: Create a Folder Template\nFirst, begin by creating a folder structure that aligns with your desired template design. For instance, let’s set up a simple Python project template:\nmy_template/\n|-- {{cookiecutter.project_name}}\n| |-- main.py\n|-- tests\n| |-- test_{{cookiecutter.project_name}}.py\n|-- README.md\nIn this example, {cookiecutter.project_name} is a placeholder that will be replaced with the actual project name when the template is used. This directory contains a python script (‘main.py’), a subdirectory (‘tests’) with a second python script named after the project (‘test_{{cookiecutter.project_name}}.py’) and a ‘README.md’ file.\n\n\nStep 2: Create cookiecutter.json\nIn the root of your template folder, create a file named cookiecutter.json. This file will define the variables (keywords) that users will be prompted to fill in. For our Python project template, it might look like this:\n{\n \"project_name\": \"MyProject\",\n \"author_name\": \"Your Name\",\n \"description\": \"A short description of your project\"\n}\nWhen users generate a project based on your template, they will be prompted with these questions. The provided values (“responses”) will be used to substitute the placeholders in your template files.\nBeyond substituting placeholders in file and directory names, Cookiecutter can automatically populate text file contents with information. This feature is useful for offering default configurations or code file templates. Let’s enhance our earlier example by incorporating a placeholder within a text file:\nFirst, modify the my_template/main.py file to include a placeholder inside its contents:\n# main.py\n\ndef hello():\n print(\"Hello, {{cookiecutter.project_name}}!\")\nThe ‘{{cookiecutter.project_name}}’ placeholder is now included within the main.py file. When you execute Cookiecutter, it will automatically replace the placeholders in both file and directory names and within text file contents.\nAfter running Cookiecutter, your generated ‘main.py’ file could appear as follows:\n# main.py\n\ndef hello():\n print(\"Hello, MyProject!\") # Assuming \"MyProject\" was entered as the project_name\n\n\nStep 3: Use Cookiecutter\nOnce your template is prepared, you can utilize Cookiecutter to create a project from it. Open a terminal and execute:\ncookiecutter path/to/your/template\nCookiecutter will prompt you to provide values for project_name, author_name, and description. Once you input these values, Cookiecutter will replace the placeholders in your template files with the entered values.\n\n\nStep 4: Review the Generated Project\nAfter the generation process is complete, navigate to the directory where Cookiecutter created the new project. You will find a project structure with the placeholders replaced by the values you provided.\n\n\n\n\n\n\nExercise 1: Create your own template\n\n\n\n\n\n\n\nUse Cookiecutter to create custom templates for your folders. You can do it from scratch (see Exercise 1, part B) or opt for one of our pre-made templates available as a Github repository (recommended for this workshop). Feel free to tailor the template to your specific requirements—you don’t have to follow our examples exactly.\nRequirements\nWe assume you have already gone through the requirements at the beginning of the practical lesson. This includes installing the necessary tools and setting up accounts as needed.\nProject\n\nGo to our Cookicutter template and click on the Fork button at the top-right corner of the repository page to create a copy of the repository on your own GitHub account or organization. \nOpen a terminal on your computer, copy the URL of your fork and clone the repository to your local machine (the URL should look something like https://github.com/your_username/cookiecutter-template):\ngit clone <your URL to the template>\nIf you have a GitHub Desktop, click Add and select “Clone repository” from the options\nOpen the repository and navigate through the different directories\nModify the contents of the repository as needed to fit your project’s requirements. You can change files, add new ones. remove existing one or adjust the folder structure. For inspiration, review the data structure above under ‘Project folder’. For instance, this template is missing the ‘reports’ directory and add the ‘requirements.txt’ file. Consider creating it, along with a subdirectory named ‘reports/figures’.\n├── results/\n│ ├── figures/\n├── requirements.txt\nHere’s an example of how to do it:\n# Open your terminal and navigate to your template directory. Then: \ncd \\{\\{\\ cookiecutter.project_name\\ \\}\\}/ \nmkdir reports \ntouch requirements.txt\nCommit and push changes when you are done with your modifications\n\n\nStage the changes with git add\nCommit the changes with a meaningful commit message git commit -m \"update cookicutter template\"\nPush the changes to your forked repository on Github git push origin main (or the appropriate branch name)\n\n\nTest your template by using cookiecutter <URL to your GitHub repository \"cookicutter-template\">\nFill up the variables and verify that the new structure (and folders) looks like you would expect. Have any new folders been added, or have some been removed?\n\n\n\n\n\n\n\n\n\n\n\n\nOptional Exercise 1, part B\n\n\n\n\n\n\n\nCreate a template from scratch using this tutorial scratch, it can be as basic as this one below or ‘Data folder’:\nmy_template/\n|-- {{cookiecutter.project_name}}\n| |-- main.py\n|-- tests\n| |-- test_{{cookiecutter.project_name}}.py\n|-- README.md\n\nStep 1: Create a directory for the template.\nStep 2: Write a cookiecutter.json file with variables such as project_name and author.\nStep 3: Set up the folder structure by creating subdirectories and files as needed.\nStep 4: Incorporate cookiecutter variables in the names of files.\nStep 5: Use cookiecutter variables within scripts, such as printing a message that includes the project name." + "text": "1. Organize and structure your datasets and data analysis\nEstablishing a consistent file structure and naming conventions will help you efficiently manage your data. We will classify your data and data analyses into two distinct types of folders to ensure the data can be used and shared by many lab members while preventing modifications by any individual:\n\nData folders (assay or external databases and resources): They house the raw and processed datasets, alongside the pipeline/workflow used to generate the processed data, the provenance of the raw data, and quality control reports of the data. The data should be locked and set to read-only to prevent unintended modifications. This applies to experimental data generated in your lab as well as external resources. Provide an MD5 checksum file when you download them yourself to verify their integrity.\nProject folders: They contain all the essential files for a specific research project. Projects may use data from various resources or experiments, or build upon previous results from other projects. The data should not be copied or duplicated, instead, it should be linked directly from the source.\n\nData and data analysis are kept separate because a project may utilize one or more datasets to address a scientific question. Data can be reused in multiple projects over time, combined with other datasets for comparison, or used to build larger datasets. Additionally, data may be utilized by different researchers to answer various research questions.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nWhen organizing your data folders, separate assays from external resources and maintain a consistent structure. For example, organize genome references by species and further categorize them by versions. Make sure to include all relevant information, and refer to this lesson for additional tips on data organization.\nThis will help you to keep your data tidied up, especially if you are working in a big lab where assays may be used for different purposes and by different people!\n\n\n\n\n\n\nData folders\nWhether your lab generates its own experimental data, receives it from collaborators, or works with previously published datasets, the data folder should follow a similar structure to the one presented here. Create a separate folder for each dataset, including raw files and processed files alongside the corresponding documentation and pipeline that generated the processed data. Raw files should remain untouched, and you should consider locking modifications to the final results once data preprocessing is complete. This precaution helps prevent unwanted changes to the data. Each subfolder should be named in a way that is distinct, easily readable and clear at a glance. Check this lesson for tips on naming conventions.\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nUse an acronym (1) that describes the type of NGS assay (RNAseq, ChIPseq, ATACseq) a keyword (2) that represents a unique element to that assay, and the date (3).\n<Assay-ID>_<keyword>_YYYYMMDD\nFor example CHIP_Oct4_20230101 is a ChIPseq assay made on 1st January 2023 with the keyword Oct4, so it is easily identifiable by the eye.\n\n\n\n\n\nLet’s explore a potential folder structure and the types of files you might encounter within it.\n<data_type>_<keyword>_YYYYMMDD/\n├── README.md \n├── CHECKSUMS\n├── pipeline\n ├── pipeline.md\n ├── scripts/\n├── processed\n ├── fastqc/\n ├── multiqc/\n ├── final_fastq/\n└── raw\n ├── .fastq.gz \n └── samplesheet.csv\n\nREADME.md: This file contains a detailed description of the dataset commonly in markdown format. It should include the provenance of the raw data (such as samples, laboratory protocols used, the aim of the project, folder structure, naming conventions, etc.).\nmetadata.yml: This metadata file outlines different keys and essential information, usually presented in YAML format. For more details, refer to this lesson.\npipeline.md: This file provides an overview of the pipeline used to process raw data, as well as the commands to run the pipeline. The pipeline itself and all the required scripts should be collected in the same directory.\nprocessed: This folder contains the results from the preprocessing pipeline. The content vary depending on the specific pipeline used (create additional subdirectories as needed).\nraw: This folder holds the raw data.\n\n.fastq.gz: For example, in NGS assays, there should be ‘fastq’ files.\nsamplesheet.csv: This file holds essential metadata for the samples, including sample identification, experimental variables, batch information, and other metrics crucial for downstream analysis. It is important that this file is complete and current, as it is key to interpreting results. If you are considering running nf-core pipelines, this file will be required.\n\n\n\n\nProject folders\nOn the other hand, we have another type of folder called Projects which refers to data analyses that are specific to particular tasks, such as those involved in preparing a potential article. In this folder, you will create a subfolder for each project that you or your lab is working on. Each Project subfolder should include project-specific information, data analysis pipelines, notebooks, and scripts used for that particular project. Additionally, you should include an environment file with all the required software and dependencies needed for the project, including their versions. This helps ensure that the analyses can be easily replicated and shared with others.\nThe Project folder should be named in a way that is unique, easy to read, distinguishable, and clear at a glance. For example, you might name it based on the main author’s initials, the dataset being analyzed, the project name, a unique descriptive element related to the project, or the part of the project you are responsible for, along with the date:\n<project>_<keyword>_YYYYMMDD\n\n\n\n\n\n\nNaming examples\n\n\n\n\n\n\n\n\nRNASeq_Mouse_Brain_20230512: a project RNA sequencing data from a mouse brain experiment, created on May 12, 2023\nEHR_COVID19_Study_20230115: a project around electronic health records data for a COVID-19 study, created on January 15, 2023.\n\n\n\n\n\n\nNow, let’s explore an example of a folder structure and the types of files you might encounter within it.\n<project>_<keyword>_YYYYMMDD\n├── data\n│ └── <ID>_<keyword>_YYYYMMDD <- symbolic link\n├── documents\n│ └── research_project_template.docx\n├── metadata.yml\n├── notebooks\n│ └── 01_data_processing.rmd\n│ └── 02_data_analysis.rmd\n│ └── 03_data_visualization.rmd\n├── README.md\n├── reports\n│ └── 01_data_processing.html\n│ └── 02_data_analysis.html\n│ ├── 03_data_visualization.html\n│ │ └── figures\n│ │ └── tables\n├── requirements.txt // env.yaml\n├── results\n│ ├── figures\n│ │ └── 02_data_analysis/\n│ │ └── heatmap_sampleCor_20230102.png\n│ ├── tables\n│ │ └── 02_data_analysis/\n│ │ └── DEA_treat-control_LFC1_p01.tsv\n│ │ └── SumStats_sampleCor_20230102.tsv\n├── pipeline\n│ ├── rules // processes \n│ │ └── step1_data_processing.smk\n│ └── pipeline.md\n├── scratch\n└── scripts\n\ndata: This folder contains symlinks or shortcuts to the actual data files, ensuring that the original files remain unaltered.\ndocuments: This folder houses Word documents, slides, or PDFs associated with the project, including data and project explanations, research papers, and more. It also includes the Data Management Plan.\n\nresearch_project_template.docx. If you download our template you will find a is a pre-filled Data Management Plan based on the Horizon Europe guidelines named ‘Non-sensitive_NGS_research_project_template.docx’.\n\nmetadata.yml: metadata file describing various keys of the project or experiment (see this lesson).\nnotebooks: This folder stores Jupyter, R Markdown, or Quarto notebooks containing the data analysis. Figures and tables used for the reports are organized under subfolders named after the notebook that created them for provenance purposes.\nREADME.md: A detailed project description in markdown or plain-text format.\nreports: Notebooks rendered as HTML, docx, or PDF files for sharing with colleagues or as formal data analysis reports.\n\nfigures: figures produced upon rendering notebooks. The figures will be saved under a subfolder named after the notebook that created them. This is for provenance purposes so we know which notebook created which figures.\n\nrequirements.txt: This file lists the necessary software, libraries, and their versions required to reproduce the code. If you’re using conda environments, you will also find the env.yaml file here, which outlines the specific environment configuration.\nresults: This folder contains analysis results, such as figures and tables. Organizing results by the pipeline, script, or notebook that generated them will make it easier to locate and interpret the data.\npipeline: A folder containing pipeline scripts or workflows for processing and analyzing data.\nscratch: A folder designated for temporary files or workspace for experiments and development.\nscripts: Folder for helper scripts needed to run data analysis or reproduce the work.\n\n\n\nTemplate engine\nCreating a folder template is straightforward with cookiecutter a command-line tool that generates projects from templates (called cookiecutters). For example, it can help you set up a Python package project based on a Python package project template.\n\n\n\n\n\n\nCookiecutter templates\n\n\n\nHere are some template that you can use to get started, adapt and modify them to your own needs:\n\nPython package project\nSandbox test\nData science\nNGS data\n\nCreate your own template from scratch.\n\n\n\nQuick tutorial on cookiecutter\nBuilding a Cookiecutter template from scratch requires defining a folder structure, crafting a cookiecutter.json file, and outlining placeholders (keywords) that will be substituted when generating a new project. Here’s a step-by-step guide on how to proceed:\n\nStep 1: Create a Folder Template\nFirst, begin by creating a folder structure that aligns with your desired template design. For instance, let’s set up a simple Python project template:\nmy_template/\n|-- {{cookiecutter.project_name}}\n| |-- main.py\n|-- tests\n| |-- test_{{cookiecutter.project_name}}.py\n|-- README.md\nIn this example, {cookiecutter.project_name} is a placeholder that will be replaced with the actual project name when the template is used. This directory contains a python script (‘main.py’), a subdirectory (‘tests’) with a second python script named after the project (‘test_{{cookiecutter.project_name}}.py’) and a ‘README.md’ file.\n\n\nStep 2: Create cookiecutter.json\nIn the root of your template folder, create a file named cookiecutter.json. This file will define the variables (keywords) that users will be prompted to fill in. For our Python project template, it might look like this:\n{\n \"project_name\": \"MyProject\",\n \"author_name\": \"Your Name\",\n \"description\": \"A short description of your project\"\n}\nWhen users generate a project based on your template, they will be prompted with these questions. The provided values (“responses”) will be used to substitute the placeholders in your template files.\nBeyond substituting placeholders in file and directory names, Cookiecutter can automatically populate text file contents with information. This feature is useful for offering default configurations or code file templates. Let’s enhance our earlier example by incorporating a placeholder within a text file:\nFirst, modify the my_template/main.py file to include a placeholder inside its contents:\n\n\nmain.py\n\n# main.py\ndef hello():\n print(\"Hello, {{cookiecutter.project_name}}!\")\n\nThe ‘{{cookiecutter.project_name}}’ placeholder is now included within the main.py file. When you execute Cookiecutter, it will automatically replace the placeholders in both file and directory names and within text file contents.\nAfter running Cookiecutter, your generated ‘main.py’ file could appear as follows:\n# main.py, assuming \"MyProject\" was entered as the project_name\ndef hello():\n print(\"Hello, MyProject!\") \n\n\nStep 3: Use Cookiecutter\nOnce your template is prepared, you can utilize Cookiecutter to create a project from it. Open a terminal and execute:\ncookiecutter path/to/your/template\nCookiecutter will prompt you to provide values for project_name, author_name, and description. Once you input these values, Cookiecutter will replace the placeholders in your template files with the entered values.\n\n\nStep 4: Review the Generated Project\nAfter the generation process is complete, navigate to the directory where Cookiecutter created the new project. You will find a project structure with the placeholders replaced by the values you provided.\n\n\n\n\n\n\nExercise 1: Create your own template\n\n\n\n\n\n\n\nUse Cookiecutter to create custom templates for your folders. You can do it from scratch (see Exercise 1, part B) or opt for one of our pre-made templates available as a Github repository (recommended for this workshop). Feel free to tailor the template to your specific requirements—you don’t have to follow our examples exactly.\nRequirements\nWe assume you have already gone through the requirements at the beginning of the practical lesson. This includes installing the necessary tools and setting up accounts as needed.\nProject\n\nGo to our Cookicutter template and click on the Fork button at the top-right corner of the repository page to create a copy of the repository on your own GitHub account or organization. \nOpen a terminal on your computer, copy the URL of your fork and clone the repository to your local machine (the URL should look something like https://github.com/your_username/cookiecutter-template):\ngit clone <your URL to the template>\nIf you have a GitHub Desktop, click Add and select “Clone repository” from the options\nOpen the repository and navigate through the different directories\nModify the contents of the repository as needed to fit your project’s requirements. You can change files, add new ones. remove existing one or adjust the folder structure. For inspiration, review the data structure above under ‘Project folder’. For instance, this template is missing the ‘reports’ directory and add the ‘requirements.txt’ file. Consider creating it, along with a subdirectory named ‘reports/figures’.\n├── results/\n│ ├── figures/\n├── requirements.txt\nHere’s an example of how to do it:\n# Open your terminal and navigate to your template directory. Then: \ncd \\{\\{\\ cookiecutter.project_name\\ \\}\\}/ \nmkdir reports \ntouch requirements.txt\nCommit and push changes when you are done with your modifications\n\n\nStage the changes with git add\nCommit the changes with a meaningful commit message git commit -m \"update cookicutter template\"\nPush the changes to your forked repository on Github git push origin main (or the appropriate branch name)\n\n\nTest your template by using cookiecutter <URL to your GitHub repository \"cookicutter-template\">\nFill up the variables and verify that the new structure (and folders) looks like you would expect. Have any new folders been added, or have some been removed?\n\n\n\n\n\n\n\n\n\n\n\n\nOptional Exercise 1, part B\n\n\n\n\n\n\n\nCreate a template from scratch using this tutorial scratch, it can be as basic as this one below or ‘Data folder’:\nmy_template/\n|-- {{cookiecutter.project_name}}\n| |-- main.py\n|-- tests\n| |-- test_{{cookiecutter.project_name}}.py\n|-- README.md\n\nStep 1: Create a directory for the template.\nStep 2: Write a cookiecutter.json file with variables such as project_name and author.\nStep 3: Set up the folder structure by creating subdirectories and files as needed.\nStep 4: Incorporate cookiecutter variables in the names of files.\nStep 5: Use cookiecutter variables within scripts, such as printing a message that includes the project name." }, { "objectID": "develop/practical_workshop.html#data-documentation", "href": "develop/practical_workshop.html#data-documentation", "title": "Practical material", "section": "2. Data documentation", - "text": "2. Data documentation\nData documentation involves organizing, describing, and providing context for datasets and projects. While metadata concentrates on the data itself, README files provide a broader perspective on the overall project or resource.\n\nMetadata\n\n\n\n\n\n\nmetadata.yml\n\n\n\nChoose the format that best suits the project’s needs. In this workshop, we will focus on YAMl as it is highly used for configuration files (e.g., in conda or pipelines).\n\n\n\n\n\n\nFile formats\n\n\n\n\n\n\n\n\nXML (eXtensible Markup Language): uses custom tags to describe data and allows for a hierarchical structure.\nJSON (JavaScript Object Notation): lightweight and human-readable format that is easy to parse and generate.\nCSV (Comma-Separated Values) or TSV (tabulate-separate values): simple and widely supported for representing tabular formats. Easy to manipulate using software or programming languages. It is often use for sample metadata.\nYAML (YAML Ain’t Markup Language): human-readable data serialization format, commonly used as project configuration files.\n\nOthers such as RDF or HDF5.\n\n\n\n\n\nLink to the file format database.\n\n\nMetadata in biological datasets refers to the information that describes the data and provides context for how the data was collected, processed, and analyzed. Metadata is crucial for understanding, interpreting, and using biological datasets effectively. It also ensures that datasets are reusable, reproducible and understandable by other researchers. Some of the components may differ depending on the type of project, but there are general concepts that will always be shared across different projects:\n\nSample information and collection details\nBiological context (such experimental conditions if applicable)\nData description\nData processing steps applied to the raw data\nAnnotation and Ontology terms\nFile metadata (file type, file format, etc.)\nEthical and Legal Compliance (ownership, access, provenance)\n\n\n\n\n\n\n\nMetadata and controlled vocabularies\n\n\n\nTo maximize the usefulness of metadata, aim to use controlled vocabularies across all fields. Read more about data documentation and find ontology services examples in lesson 4. We encourage you to begin implementing them systematically on your own (under the “sources” section, you will find some helpful links to guide you putting them in practice).\nIf you work with NGS data, check out this recommendations and examples of metadata for samples, projects and datasets.\n\n\n\n\nREADME file\n\n\n\n\n\n\nREADME.md\n\n\n\nChoose the format that best suits the project’s needs. In this workshop, we will focused on Markdown as it is the most used format due to its balance of simplicity and expressive formatting options.\n\n\n\n\n\n\nFile formats\n\n\n\n\n\n\n\n\nMarkdown (.md): commonly used because is easy to read and write and is compatible across platforms (e.g., GitHub, GitLab). Supports formatting like headings, lists, links, images, and code blocks.\nPlain Text (.txt): Simple and straightforward format without any rich formatting and great for basic instructions. Lack the ability of structure content effectively.\nReStructuredText (.rst): commonly used for python projects. Supports advanced formatting (takes, links, images and code blocks) .\n\nOthers such as HTML, YAML and Notebooks.\n\n\n\n\n\nLink to the file format database\n\n\nThe README.md file is a markdown file that provides a comprehensive description of the data within a folder. Its rich text format (including bold, italic, links, etc.) allows you to explain the contents of the folder, as well as the reasons and methods behind its creation or collection. The content will vary depending on what it described (data or assays, project, software…).\nHere is an example of a README file for a bioinformatics project:\n\n\n\n\n\n\nREADME\n\n\n\n\n\n# TITLE\nClear and descriptive.\n# OVERVIEW\nIntroduction to the project including its aims, and its significance. Describe the main purpose and the biological questions being addressed.\n\n\n\n\n\n\nExample text\n\n\n\n\n\n\n\nThis project aims to investigate gene expression patterns across various human tissues using Next Generation Sequencing (NGS) data. By analyzing the transcriptomes of different tissues, we seek to uncover tissue-specific gene expression profiles and identify potential markers associated with specific biological functions or diseases.\nUnderstanding tissue-specific gene expression is crucial for deciphering the molecular basis of health and disease. Identifying genes that are uniquely expressed in certain tissues can provide insights into tissue function, development, and potential therapeutic targets. This project contributes to our broader understanding of human biology and has implications for personalized medicine and disease research.\n\n\n\n\n\n# TABLE OF CONTENTS (optional but helpful for others to navigate to different sections)\n# INSTALLATION AND SETUP\nList all prerequisites, software, dependencies, and system requirements needed for others to reproduce the project. If available, you may link to a Docker image, Conda YAML file, or requirements.txt file.\n# USAGE\nInclude command-line examples for various functionalities or steps and path for running a pipeline, if applicable.\n# DATASETS\nDescribe the data,, including its sources, format, and how to access it. If the data has undergone preprocessing, provide a description of the processes applied or the pipeline used.\n\n\n\n\n\n\nExample text\n\n\n\n\n\n\n\nWe have used internal datasets with IDs: RNA_humanSkin_20201030, RNA_humanBrain_20210102, RNA_humanLung_20220304.\nIn addition, we utilized publicly available NGS datasets from the GTEx (Genotype-Tissue Expression) project, which provides comprehensive RNA-seq data across multiple human tissues. These datasets offer a wealth of information on gene expression levels and isoform variations across diverse tissues, making them ideal for our analysis.\n\n\n\n\n\n# RESULTS\nSummarize the results and key findings or outputs.\n\n\n\n\n\n\nExample text\n\n\n\n\n\n\n\nOur analysis revealed distinct gene expression patterns among different human tissues. We identified tissue-specific genes enriched in brain tissues, highlighting their potential roles in neurodevelopment and function. Additionally, we found a set of genes that exhibit consistent expression across a range of tissues, suggesting their fundamental importance in basic cellular processes.\nFurthermore, our differential expression analysis unveiled significant changes in gene expression between healthy and diseased tissues, shedding light on potential molecular factors underlying various diseases. Overall, this project underscores the power of NGS data in unraveling intricate gene expression networks and their implications for human health.\n\n\n\n\n\n# CONTRIBUTIONS AND CONTACT INFO\n# LICENSE\n\n\n\n\n\n\n\n\n\n\nExercise 2: modify the metadata.yml file in your Cookiecutter template\n\n\n\n\n\n\n\nIt is time now to customize your Cookiecutter templates and modify the metadata.yml files so that they fit your needs!\n\nConsider changing variables (add/remove) in the metadata.yml file from the cookicutter template.\nModify the cookiecutter.json file. You could add new variables or change the default key and/or values:\n{\n\"project_name\": \"myProject\",\n\"project_slug\": \"{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}\",\n\"authors\": \"myName\",\n\"start_date\": \"{% now 'utc', '%Y%m%d' %}\",\n\"short_desc\": \"\",\n\"version\": \"0.1.0\"\n}\nThe metadata file will be filled accordingly.\nOptional: You can customize or remove this prompt message entirely, allowing you to tailor the text to your preferences for a unique experience each time you use the template.\n\"__prompts__\": {\n \"project_name\": \"Project directory name [Example: project_short_description_202X]\",\n \"author\": \"Author of the project\",\n \"date\": \"Date of project creation, default is today's date\",\n \"short_description\": \"Provide a detailed description of the project (context/content)\"\n},\nModify the metadata.yml file so that it includes the metadata recorded by the cookiecutter.json file. Hint below:\nproject: {{ cookiecutter.project_name }}\nauthor: {{ cookiecutter.author }}\ndate: {{ cookiecutter.date }}\ndescription: {{ cookiecutter.short_description }}\nModify the README.md file so that it includes the short description recorded by the cookiecutter.json file and the metadata at the top of the markdown file (top between lines of dashed).\n---\ntitle: {{ cookiecutter.project_name }}\ndate: \"{{ cookiecutter.date }}\"\nauthor: {{ cookiecutter.author }}\nversion: {{ cookiecutter.version }}\n---\n\nProject description\n----\n\n{{ cookiecutter.short_description }}\nCommit and push changes when you are done with your modifications\n\n\nStage the changes with git add\nCommit the changes with a meaningful commit message git commit -m \"update cookicutter template\"\nPush the changes to your forked repository on Github git push origin main (or the appropriate branch name)\n\n\nTest your template by using cookiecutter <URL to your GitHub repository \"cookicutter-template\">\nFill up the variables and verify that the modified information looks like you would expect." + "text": "2. Data documentation\nData documentation involves organizing, describing, and providing context for datasets and projects. While metadata concentrates on the data itself, README files provide a broader perspective on the overall project or resource.\n\nMetadata\n\n\n\n\n\n\nmetadata.yml\n\n\n\nChoose the format that best suits the project’s needs. In this workshop, we will focus on YAMl as it is highly used for configuration files (e.g., in conda or pipelines).\n\n\n\n\n\n\nFile formats\n\n\n\n\n\n\n\n\nXML (eXtensible Markup Language): uses custom tags to describe data and allows for a hierarchical structure.\nJSON (JavaScript Object Notation): lightweight and human-readable format that is easy to parse and generate.\nCSV (Comma-Separated Values) or TSV (tabulate-separate values): simple and widely supported for representing tabular formats. Easy to manipulate using software or programming languages. It is often use for sample metadata.\nYAML (YAML Ain’t Markup Language): human-readable data serialization format, commonly used as project configuration files.\n\nOthers such as RDF or HDF5.\n\n\n\n\n\nLink to the file format database.\n\n\nMetadata in biological datasets refers to the information that describes the data and provides context for how the data was collected, processed, and analyzed. Metadata is crucial for understanding, interpreting, and using biological datasets effectively. It also ensures that datasets are reusable, reproducible and understandable by other researchers. Some of the components may differ depending on the type of project, but there are general concepts that will always be shared across different projects:\n\nSample information and collection details\nBiological context (such experimental conditions if applicable)\nData description\nData processing steps applied to the raw data\nAnnotation and Ontology terms\nFile metadata (file type, file format, etc.)\nEthical and Legal Compliance (ownership, access, provenance)\n\n\n\n\n\n\n\nMetadata and controlled vocabularies\n\n\n\nTo maximize the usefulness of metadata, aim to use controlled vocabularies across all fields. Read more about data documentation and find ontology services examples in lesson 4. We encourage you to begin implementing them systematically on your own (under the “sources” section, you will find some helpful links to guide you putting them in practice).\nIf you work with NGS data, check out this recommendations and examples of metadata for samples, projects and datasets.\n\n\n\n\nREADME file\n\n\n\n\n\n\nREADME.md\n\n\n\nChoose the format that best suits the project’s needs. In this workshop, we will focused on Markdown as it is the most used format due to its balance of simplicity and expressive formatting options.\n\n\n\n\n\n\nFile formats\n\n\n\n\n\n\n\n\nMarkdown (.md): commonly used because is easy to read and write and is compatible across platforms (e.g., GitHub, GitLab). Supports formatting like headings, lists, links, images, and code blocks.\nPlain Text (.txt): Simple and straightforward format without any rich formatting and great for basic instructions. Lack the ability of structure content effectively.\nReStructuredText (.rst): commonly used for python projects. Supports advanced formatting (takes, links, images and code blocks) .\n\nOthers such as HTML, YAML and Notebooks.\n\n\n\n\n\nLink to the file format database\n\n\nThe README.md file is a markdown file that provides a comprehensive description of the data within a folder. Its rich text format (including bold, italic, links, etc.) allows you to explain the contents of the folder, as well as the reasons and methods behind its creation or collection. The content will vary depending on what it described (data or assays, project, software…).\nHere is an example of a README file for a bioinformatics project:\n\n\n\n\n\n\nREADME\n\n\n\n\n\n# TITLE\nClear and descriptive.\n# OVERVIEW\nIntroduction to the project including its aims, and its significance. Describe the main purpose and the biological questions being addressed.\n\n\n\n\n\n\nExample text\n\n\n\n\n\n\n\nThis project aims to investigate gene expression patterns across various human tissues using Next Generation Sequencing (NGS) data. By analyzing the transcriptomes of different tissues, we seek to uncover tissue-specific gene expression profiles and identify potential markers associated with specific biological functions or diseases.\nUnderstanding tissue-specific gene expression is crucial for deciphering the molecular basis of health and disease. Identifying genes that are uniquely expressed in certain tissues can provide insights into tissue function, development, and potential therapeutic targets. This project contributes to our broader understanding of human biology and has implications for personalized medicine and disease research.\n\n\n\n\n\n# TABLE OF CONTENTS (optional but helpful for others to navigate to different sections)\n# INSTALLATION AND SETUP\nList all prerequisites, software, dependencies, and system requirements needed for others to reproduce the project. If available, you may link to a Docker image, Conda YAML file, or requirements.txt file.\n# USAGE\nInclude command-line examples for various functionalities or steps and path for running a pipeline, if applicable.\n# DATASETS\nDescribe the data,, including its sources, format, and how to access it. If the data has undergone preprocessing, provide a description of the processes applied or the pipeline used.\n\n\n\n\n\n\nExample text\n\n\n\n\n\n\n\nWe have used internal datasets with IDs: RNA_humanSkin_20201030, RNA_humanBrain_20210102, RNA_humanLung_20220304.\nIn addition, we utilized publicly available NGS datasets from the GTEx (Genotype-Tissue Expression) project, which provides comprehensive RNA-seq data across multiple human tissues. These datasets offer a wealth of information on gene expression levels and isoform variations across diverse tissues, making them ideal for our analysis.\n\n\n\n\n\n# RESULTS\nSummarize the results and key findings or outputs.\n\n\n\n\n\n\nExample text\n\n\n\n\n\n\n\nOur analysis revealed distinct gene expression patterns among different human tissues. We identified tissue-specific genes enriched in brain tissues, highlighting their potential roles in neurodevelopment and function. Additionally, we found a set of genes that exhibit consistent expression across a range of tissues, suggesting their fundamental importance in basic cellular processes.\nFurthermore, our differential expression analysis unveiled significant changes in gene expression between healthy and diseased tissues, shedding light on potential molecular factors underlying various diseases. Overall, this project underscores the power of NGS data in unraveling intricate gene expression networks and their implications for human health.\n\n\n\n\n\n# CONTRIBUTIONS AND CONTACT INFO\n# LICENSE\n\n\n\n\n\n\n\n\n\n\nExercise 2: modify the metadata.yml file in your Cookiecutter template\n\n\n\n\n\n\n\nIt is time now to customize your Cookiecutter templates and modify the metadata.yml files so that they fit your needs!\n\nConsider changing variables (add/remove) in the metadata.yml file from the cookicutter template.\nModify the cookiecutter.json file. You could add new variables or change the default key and/or values:\n\n\ncookiecutter.json\n\n{\n\"project_name\": \"myProject\",\n\"project_slug\": \"{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}\",\n\"authors\": \"myName\",\n\"start_date\": \"{% now 'utc', '%Y%m%d' %}\",\n\"short_desc\": \"\",\n\"version\": \"0.1.0\"\n}\n\nThe metadata file will be filled accordingly.\nOptional: You can customize or remove this prompt message entirely, allowing you to tailor the text to your preferences for a unique experience each time you use the template.\n\n\ncookiecutter.json\n\n\"__prompts__\": {\n \"project_name\": \"Project directory name [Example: project_short_description_202X]\",\n \"author\": \"Author of the project\",\n \"date\": \"Date of project creation, default is today's date\",\n \"short_description\": \"Provide a detailed description of the project (context/content)\"\n},\n\nModify the metadata.yml file so that it includes the metadata recorded by the cookiecutter.json file. Hint below:\n\n\nmetadata.yml\n\nproject: {{ cookiecutter.project_name }}\nauthor: {{ cookiecutter.author }}\ndate: {{ cookiecutter.date }}\ndescription: {{ cookiecutter.short_description }}\n\nModify the README.md file so that it includes the short description recorded by the cookiecutter.json file and the metadata at the top of the markdown file (top between lines of dashed).\n\n\nREADME.md\n\n---\ntitle: {{ cookiecutter.project_name }}\ndate: \"{{ cookiecutter.date }}\"\nauthor: {{ cookiecutter.author }}\nversion: {{ cookiecutter.version }}\n---\n\nProject description\n----\n\n{{ cookiecutter.short_description }}\n\nCommit and push changes when you are done with your modifications\n\n\nStage the changes with git add\nCommit the changes with a meaningful commit message git commit -m \"update cookicutter template\"\nPush the changes to your forked repository on Github git push origin main (or the appropriate branch name)\n\n\nTest your template by using cookiecutter <URL to your GitHub repository \"cookicutter-template\">\nFill up the variables and verify that the modified information looks like you would expect." }, { "objectID": "develop/practical_workshop.html#overview", @@ -1662,6 +1662,25 @@ "href": "develop/practical_workshop.html#create-a-catalog-of-your-data-folder", "title": "Practical material", "section": "4. Create a catalog of your data folder", - "text": "4. Create a catalog of your data folder\nThe next step is to collect all the NGS datasets that you have created in the manner explained above. Since your folders all should contain the metadata.yml file in the same place with the same metadata, it should be very easy to iteratively go through all the folders and merge all the metadata.yml files into a one single table. This table can be then browsed easily with Microsoft Excel, for example. If you are interested in making a Shiny app or Python Panel tool to interactively browse the catalog, check out this lesson.\n\n\n\n\n\n\nExercise 4: create a metadata.tsv catalog\n\n\n\n\n\n\n\nWe will make a small script in R (or you can make one with Python) that recursively goes through all the folders inside an input path (like your Assays folder), fetches all the metadata.yml files, and merges them. Finally, it will write a TSV file as an output.\n\nCreate a folder called dataset and change directory cd dataset\nFork this repository: a Cookiecutter template designed for NGS datasets. While you are welcome to create your own template from scratch, we recommend using this one to save time.\nRun the cookiecutter cc-data-template command at least twice to create multiple datasets or projects. Use different values each time to simulate various scenarios (do this in the dataset directory that you have previously created). Execute the script below using R (or create your own script in Python). Adjust the folder_path variable so that it matches the path to the Assays folder. The resulting table will be saved in the same folder_path.\nOpen your database_YYYYMMDD.tsv table in a text editor from the command-line, or view it in Excel for better visualization.\n\n\nlibrary(yaml)\nlibrary(dplyr)\nlibrary(lubridate)\n\n# Function to read a YAML file and transform it into a dataframe format.\nread_yaml <- function(file_path) {\n # Read the YAML file and convert it to a data frame\n df <- yaml::yaml.load_file(file_path) %>% as.data.frame(stringsAsFactors = FALSE)\n \n # Return the data frame\n return(df)\n}\n\n# Function to recursively fetch metadata.yml files\nget_metadata <- function(folder_path) {\n file_list <- list.files(path = folder_path, pattern = \"metadata\\\\.yml$\", recursive = TRUE, full.names = TRUE)\n\n metadata_list <- lapply(file_list, read_yaml)\n \n # Combine the list of data frames into a single data frame using dplyr::bind_rows()\n combined_metadata <- bind_rows(metadata_list)\n\n return(combined_metadata)\n}\n\n# Specify the folder path\nfolder_path <- \"/path/to/your/folder\"\n\n# Fetch metadata from the specified folder\nmetadata <- get_metadata(folder_path)\n\n# Save the data frame as a TSV file\noutput_file <- paste0(\"database_\", format(Sys.Date(), \"%Y%m%d\"), \".tsv\")\nwrite.table(metadata, file = output_file, sep = \"\\t\", quote = FALSE, row.names = FALSE)\n\n# Print confirmation message\ncat(\"Database saved as\", output_file, \"\\n\")" + "text": "4. Create a catalog of your data folder\nThe next step is to collect all the datasets that you have created in the manner explained above. Since your folders all should contain the metadata.yml file in the same place with the same metadata, it should be very easy to iteratively go through all the folders and merge all the metadata.yml files into a one single table. he table can be easily viewed in your terminal or even with Microsoft Excel.\n\n\n\n\n\n\nExercise 4: create a metadata.tsv catalog\n\n\n\n\n\n\n\nWe will make a small script in R (or you can make one with Python) that recursively goes through all the folders inside an input path (like your Assays folder), fetches all the metadata.yml files, merges them and writes a TSV file as an output.\n\nCreate a folder called dataset and change directory cd dataset\nFork this repository: a Cookiecutter template designed for NGS datasets.While you are welcome to create your own template from scratch, we recommend using this one to save time.\nRun the cookiecutter cc-data-template command at least twice to create multiple datasets or projects. Use different values each time to simulate various scenarios (do this in the dataset directory that you have previously created).\nExecute the script below using R (or create your own script in Python). Adjust the folder_path variable so that it matches the path to the Assays folder. The resulting table will be saved in the same folder_path.\nOpen your database_YYYYMMDD.tsv table in a text editor from the command-line, or view it in Excel for better visualization.\n\n\nSolution A. From a TSV\n\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\n# R version 4.3.2\n# RScript to read all yaml files in directory and save the metadata into a dataframe\nquiet <- function(package_name) {\n # Suppress warnings and messages while checking and installing the package\n suppressMessages(suppressWarnings({\n # Check if the package is available and load it\n if (!requireNamespace(package_name, quietly = TRUE)) {\n install.packages(package_name)\n }\n # Load the package\n library(package_name, character.only = TRUE)\n }))\n}\n\n# Check and install necessary libraries\nquiet(\"yaml\")\nquiet(\"dplyr\")\nquiet(\"lubridate\")\n\n\nread_yaml <- function(file_path) {\n # Read the YAML file and convert it to a data frame\n df <- yaml::yaml.load_file(file_path) %>% as.data.frame(stringsAsFactors = FALSE)\n \n # Return the data frame\n return(df)\n}\n\n# Function to recursively fetch metadata.yml files\nget_metadata <- function(folder_path) {\n file_list <- list.files(path = folder_path, pattern = \"metadata\\\\.yml$\", recursive = TRUE, full.names = TRUE)\n\n metadata_list <- lapply(file_list, read_yaml)\n \n # Combine the list of data frames into a single data frame using dplyr::bind_rows()\n combined_metadata <- bind_rows(metadata_list)\n\n return(combined_metadata)\n}\n\n# Specify the folder path\nfolder_path <- \"./\" #/path/to/your/folder\n\n# Fetch metadata from the specified folder\ndf <- get_metadata(folder_path)\n\n# Save the data frame as a TSV file\noutput_file <- paste0(\"database_\", format(Sys.Date(), \"%Y%m%d\"), \".tsv\")\nwrite.table(df, file = output_file, sep = \"\\t\", quote = FALSE, row.names = FALSE)\n\n# Print confirmation message\ncat(\"Database saved as\", output_file, \"\\n\")\n\n\n\n\n\nExercise 4, option B: create a SQLite database \nAlternatively, create a SQLite database from a metadata. If you opt for this option in the exercise, you must still complete the first three steps outlined above. Read more from the RSQLite documentation.\n\nSolution B. SQLite database\n\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nprint(\"Assuming the libraries from Exercise 4 are already loaded and a dataframe has been generated from the YAML files...\")\n\n# check_and_install() form Exercise 4, and load the other packages. \nquiet(\"DBI\")\nquiet(\"RSQLite\")\n\n# Initialize a temporary in memory database and copy the data.frame into it\n\ndb_file_path <- paste0(\"database_\", format(Sys.Date(), \"%Y%m%d\"), \".sqlite\")\ncon <- dbConnect(RSQLite::SQLite(), db_file_path)\n\ndbWriteTable(con, \"metadata\", df, overwrite=TRUE) #row.names = FALSE,append =\n\n# Print confirmation message\ncat(\"Database saved as\", db_file_path, \"\\n\")\n\n# Close the database connection\ndbDisconnect(con)\n\n\n\n\n\n\n\n\n\n\n\nShiny apps\nTo get the most out of your metadata file and the ones from other colleagues, you can combine them and explore them by creating an interactive catalog browser. You can create interactive web apps straight from R or Python. Whether you have generated a tabulated-file or a sqlite database, browse through the metadata using Shiny. Shiny apps are perfect for researchers because they enable you to create interactive visualizations and dashboards with dynamic data inputs and outputs without needing extensive web development knowledge. Shiny provides a variety of user interface components such as forms, tables, graphs, and maps to help you organize and present your data effectively. It also allows you to filter, sort, and segment data for deeper insights.\n\n\n\n\n\n\nTip\n\n\n\n\nFor R Enthusiasts\n\nExplore demos from the R Shiny community to kickstart your projects or for inspiration.\n\nFor python Enthusiasts\n\nShiny for Python provides live, interactive code throughout its entire tutorial. Additionally, it offers a great tool called Playground, where you can code and test your own app to explore how different features render.\n\n\n\n\n\n\n\n\nExercise 5: Skill Booster, build an interactive catalog browser\n\n\n\n\n\n\n\nBuild an interactive web app straight from R or Python. Below, you will find an example of an R shiny app. In either case, you will need to define a user interface (UI) and a server function. The UI specifies the layout and appearance of the app, including input controls and output displays. The server function contains the app’s logic, handling data manipulation, and responding to user interactions. Once you set up the UI and server, you can launch the app!\nHere’s the UI and server function structure for an R Shiny app:\n# Don't forget to load shiny and DT libraries!\n\n# Specify the layout\nui <- fluidPage(\n titlePanel(...)\n # Define the appearance of the app\n sidebarLayout(\n sidebarPanel(...)\n mainPanel(...)\n )\n)\n\nserver <- function(input, output, session) {\n # Define a reactive expression for data based on user inputs\n data <- reactive({\n req(input$dataInput) # Ensure data input is available\n # Load or manipulate data here\n })\n\n # Define an output table based on data\n output$dataTable <- renderTable({\n data() # Render the data as a table\n })\n\n # Observe a button click event and perform an action\n observeEvent(input$actionButton, {\n # Perform an action when the button is clicked\n })\n\n # Define cleanup tasks when the app stops\n onStop(function() {\n # Close connections or save state if necessary\n })\n}\n# Run the app\nshinyApp(ui, server)\nIf you need more assistance, take a look at the code below (Hint).\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\n# R version 4.3.2\nprint(\"Assuming the libraries from Exercise 4 are already loaded and a dataframe has been generated from the YAML files...\")\n\n# check_and_install() form Exercise 4. \nquiet(\"shiny\")\nquiet(\"DT\")\n\n# UI\nui <- fluidPage(\n titlePanel(\"TSV File Viewer\"),\n \n sidebarLayout(\n sidebarPanel(\n fileInput(\"file\", \"Choose a TSV file\", accept = c(\".tsv\")),\n selectInput(\"filter_column\", \"Filter by Column:\", choices = c(\"n_samples\", \"technology\"), selected = \"technology\"),\n textInput(\"filter_value\", \"Filter Value:\", value = \"\"),\n # if only numbers, numericInput()\n radioButtons(\"sort_order\", \"Sort Order:\", choices = c(\"Ascending\", \"Descending\"), selected = \"Ascending\")\n ),\n \n mainPanel(\n DTOutput(\"table\")\n )\n )\n)\n\n# Server\nserver <- function(input, output) {\n \n data <- reactive({\n req(input$file)\n df <- read.delim(input$file$datapath, sep = \"\\t\")\n print(str(df))\n\n # Filter the DataFrame based on user input\n if (input$filter_column != \"\" && input$filter_value != \"\") {\n # Check if the column is numeric, and filter for value\n if (is.numeric(df[[input$filter_column]])) {\n df <- df[df[[input$filter_column]] >= as.numeric(input$filter_value), ]\n }\n # Check if the column is a string\n else if (is.character(df[[input$filter_column]])) {\n df <- df[df[[input$filter_column]] == input$filter_value, ]\n }\n }\n \n # Sort the DataFrame based on user input\n sort_order <- if (input$sort_order == \"Ascending\") TRUE else FALSE\n df <- df[order(df[[input$filter_column]], decreasing = !sort_order), ]\n df\n })\n \n output$table <- renderDT({\n datatable(data())\n })\n}\n\n# Run the app\nshinyApp(ui, server)\n\n\n\n\n\nIn the optional exercise below, you’ll find a code example for using an SQLite database as input instead of a tabulated file.\n\n\n\n\n\n\n\n\n\n\n\nExercise (optional)\n\n\n\n\n\n\n\nOnce you’ve finished the previous exercise, consider implementing these additional ideas to maximize the utility of your catalog browser.\n\nUse SQLite databases as input\nAdd a functionality to only select certain columns uiOutput(\"column_select\")\nFilter columns by value using column_filter_select()\nAdd multiple tabs using tabsetPanel()\nAdd buttons to order numeric columns ascending or descending using radioButtons()\nUse SQL aggregation functions (e.g., SUM, COUNT, AVG) to perform custom data summaries and calculations.\nAdd a tab tabPanel() to create a project directory interactively (and fill up the metadata fields), tips: dir.create(), data.frame(), write.table()\nModify existing entries\nVisualize results using Cirrocumulus, an interactive visualization tool for large-scale single-cell genomics data.\n\nIf you need some assistance, take a look at the code below (Hint).\n\n\n\n\n\n\nHint\n\n\n\n\n\n\n\nExplore an example with advanced features such as a two-tab layout, filtering by numeric values and matching strings, and a color-customized dashboard here." + }, + { + "objectID": "develop/practical_workshop.html#version-control-using-git-and-github", + "href": "develop/practical_workshop.html#version-control-using-git-and-github", + "title": "Practical material", + "section": "5. Version control using Git and GitHub", + "text": "5. Version control using Git and GitHub\nVersion control involves systematically tracking changes to a project over time, offering a structured way to document revisions and understand the progression of your work. In research data management and data analytics, it plays a critical role and provides numerous benefits.\nGit is a distributed version control system that helps developers and researchers efficiently manage project history, collaborate seamlessly, and maintain data integrity. On the other hand, GitHub is a web-based platform that builds on Git’s functionality by providing a centralized, collaborative hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects.\n\n\n\n\n\n\nCreate a GitHub organization for your lab or department\n\n\n\nGitHub users can create organizations, allowing groups to collaborate or create repositories under the same organization umbrella. You can create an educational organization on Github for free, by setting up a Github account for your lab.\nFollow these instructions to create a GitHub organization.\nOnce you’ve established your GitHub organization, be sure to create your repositories within the organization’s space rather than under your personal user account. This keeps your projects centralized and accessible to the entire group. Best practices for managing an organization on GitHub include setting clear access permissions, regularly reviewing roles and memberships, and organizing repositories effectively to keep your projects structured and easy to navigate.\n\n\n\nSetting up a GitHub repository for your project folder\nVersion controlling your data analysis folders becomes straightforward once you’ve established your Cookiecutter templates. After you’ve created several folder structures and metadata using your Cookiecutter template, you can manage version control by either converting those folders into Git repositories or copying a folder into an existing Git repository. Both approaches are explained in Lesson 5.\n\n\n\n\n\n\nExercise 6: initialize a repository from an existing folder:\n\n\n\n\n\n\n\n\nInitialize the repository: Begin by running the command git init in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See (git init) for more details.\nCreate a remote repository: Once the local repository is initialized, create an empty new repository on GitHub (website or Github Desktop).\nConnect the remote repository: Add the GitHub repository URL to your local repository using the command git remote add origin <URL>. This associates the remote repository with the name “origin.”\nCommit changes: If you have files you want to add to your repository, stage them using git add ., then create a commit to save a snapshot of your changes with git commit -m \"add local folder\".\nPush to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using git push -u origin main.\n\n\n\n\n\n\n\n\n\n\n\n\nTips to write good commit messages\n\n\n\nIf you would like to know more about Git commits and the best way to make clear Git messages, check out this post!\n\n\n\n\nGitHub Pages\nAfter creating your repository and hosting it on GitHub, you can now add your data analysis reports—such as Jupyter Notebooks, R Markdown files, or HTML reports—to a GitHub Page website. Setting up a GitHub Page is straightforward, and we recommend following GitHub’s helpful tutorial. However, we will go through the key steps in the exercise below. There are several ways to create your web pages, but we suggest using Quarto as a framework to build a sleek, professional-looking website with ease. The folder templates from the previous exercise already contain the necessary elements to launch a webpage. Familiarizing yourself with the basics of Quarto will help you design a webpage that suits your preferences. Other common options include MkDocs. If you want to use MkDocs instead, click here and follow the instructions.\n\n\n\n\n\n\nTip\n\n\n\nHere are some useful links to get started with Github Pages:\n\nGithub Pages\nQuarto Github Pages\n\n\n\n\n\n\n\n\n\nExercise 7: Create a Github Page using Quarto\n\n\n\n\n\n\n\n\nHead over to GitHub and create a new public repository named username.github.io, where username is your username (or organization name) on GitHub. If the first part of the repository doesn’t exactly match your username, it won’t work, so make sure to get it right.\nGo to the folder where you want to store your project, and clone the new repository: git clone https://github.com/username/username.github.io (or use Github Desktop)\nCreate a new file named _quarto.yml\n\n\n_quarto.yml\n\nproject:\n type: website\n\nOpen the terminal ```{.bash filename=“Terminal”} # Add a .nojekyll file to the root of the repository not to do additional processing of your published site touch .nojekyll #copy NUL .nojekyll for windows\n# Render and push it to Github quarto render git commit -m “Publish site to docs/” git push ```\nIf you do not have a gh-pages, you can create one as follows\n\n\nTerminal\n\ngit checkout --orphan gh-pages\ngit reset --hard # make sure all changes are committed before running this!\ngit commit --allow-empty -m \"Initialising gh-pages branch\"\ngit push origin gh-pages\n\nBefore attempting to publish you should ensure that the Source branch for your repository is gh-pages and that the site directory is set to the repository root (/)\n\nIt is important to not check your _site directory into version control, add the output directory of your project to .gitignore\n\n\n.gitignore\n\n/.quarto/\n/_site/\n\nNow is time to publish your website\n\n\n.Terminal\n\nquarto publish gh-pages\n\nOnce you’ve completed a local publish, add a publish.yml GitHub Action to your project by creating this YAML file and saving it to .github/workflows/publish.yml. Read how to do it here" + }, + { + "objectID": "develop/examples/mkdocs_pages.html", + "href": "develop/examples/mkdocs_pages.html", + "title": "Build your GitHub Page using Mkdocs", + "section": "", + "text": "Build your GitHub Page using Mkdocs\n\n\n\n\n\n\nExercise 5: make a project folder and publish a data analysis webpage\n\n\n\n\n\n\n\n\nConfigure your main GitHub Page and its repo\nThe first step is to set up the main GitHub Page site and the repository that will host it. This is very simple, as you will only need to follow these steps. In a Markdown document, outline the primary objectives of the organization and provide an overview of ongoing research projects. After you have created the organization/usernamegithub.io, it is time to configure your Project repository webpage using MkDocs!\nStart a new project from Cookiecutter or use one from the previous exercise.\nIf you use a Project repo from the first exercise, go to the next paragraph. Using Cookiecutter, create a new data analysis project. Remember to fill up your metadata and description files! After you have created the folder, it would be best to initialize a Git repo following the instructions from the previous section.\nNext, link your data of interest (or create a small fake dataset) and make an example of a data analysis notebook/report (this could be just a scatter plot of a random matrix of values). Depending on your setup, you might be using Jupyter Notebooks or R Markdown files. The extensions that we have installed using pip allow you to directly add a Jupyter Notebook file to the mkdocs.yml navigation section. On the other hand, if you are using R Markdown files, you will have to knit your document into either an HTML page or a GitHub document.\nFor the purposes of this exercise, we have already included a basic index.md markdown file that can serve as the intro page of your repo, and a jupyter_example.ipynb with some code in it. You are welcome to modify them further to test them out!\nUse MkDocs to create your webpage\nWhen you are happy with your files and are ready to publish them, make sure to add, commit, and push the changes to the remote. Then, build up your webpage using MkDocs and the mkdocs gh-deploy command from the same directory where the mkdocs.yml file is. For example, if your mkdocs.yml for your Project folder is in /Users/JARH/Projects/project1_JARH_20231010/mkdocs.yml, do cd /Users/JARH/Projects/project1_JARH_20231010/ and then mkdocs gh-deploy. This requires a couple of changes in your GitHub organization settings.\nRemember to make sure that your markdowns, images, reports, etc., are included in the docs folder and properly set up in the navigation section of your mkdocs.yml file.\nFinally, we only need to set up the GitHub Project repo settings.\nPublishing your GitHub Page\nGo to your GitHub repo settings and configure the Page section. Since you are using the mkdocs gh-deploy command to publish your site in the gh-pages branch (as explained the the mkdocs documentation), we need to change where GitHub is fetching the website. You will need to configure the settings of this repository in GitHub so that the Page is taken from the gh-pages branch and the root folder.\n\n\n\nGitHub Pages setup\n\n\n\nBranch should be gh-pages\nFolder should be root\n\nAfter a couple of minutes, your webpage should be ready! You should be able to see your webpage through the link provided in the Page section!\n\nNow it is also possible to include this repository webpage in your main webpage <organization>.github.io by including the link of the repo website (https://<organization>.github.io/repo-name) in the navigation section of the mkdocs.yml file in the main organizationgithub.io repo.\n\n\n\n\n\n\n\n\n\nCopyrightCC-BY-SA 4.0 license", + "crumbs": [ + "Use cases", + "General", + "Build your GitHub Page using Mkdocs" + ] } ] \ No newline at end of file diff --git a/develop/03_DOD.qmd b/develop/03_DOD.qmd index bba631eb..93e5022e 100644 --- a/develop/03_DOD.qmd +++ b/develop/03_DOD.qmd @@ -234,6 +234,8 @@ Next, let's take a look at a possible folder structure and what kind of files yo Setting up folder structures manually for each new project can be time-consuming. Thankfully, tools like [Cookiecutter](https://github.com/cookiecutter/cookiecutter) offer a solution by allowing users to create project templates easily. These templates can ensure consistency across projects and save time. Additionally, using [cruft](https://github.com/cruft/cruft) alongside Cookiecutter can assist in maintaining older templates when updates are made (by synchronizing them with the latest version). :::{.callout-note title="Cookiecutter templates"} +- [Sandbox Project/Data analysis template](https://github.com/hds-sandbox/cookiecutter-template) +- [Sandbox Data/Assay template](https://github.com/hds-sandbox/cc-data-template) - Cookiecutter template for [Data science projects](https://github.com/drivendata/cookiecutter-data-science) - Brickmanlab template for [NGS data](https://github.com/brickmanlab/ngs-template): similar to the folder structures in the examples above. You can download and modify it to suit your needs. ::: @@ -241,8 +243,6 @@ Setting up folder structures manually for each new project can be time-consuming ### Quick tutorial on cookiecutter :::{.callout-caution title="Sandbox Tutorial"} **Learn how to create your own template [here](./practical_workshop.qmd).** - -We offer workshops on practical RDM for biodata. Keep an eye on the upcoming events on the [Sandbox website](https://hds-sandbox.github.io/news/news.html). ::: diff --git a/develop/04_metadata.qmd b/develop/04_metadata.qmd index da01d264..f3755fd7 100644 --- a/develop/04_metadata.qmd +++ b/develop/04_metadata.qmd @@ -153,14 +153,26 @@ Researchers encountering inconsistent and non-standardized terms (e.g., gene nam :::{.callout-note} # Examples of ontology services -- [Uberon anatomy ontology](https://www.ebi.ac.uk/ols4/ontologies/uberon) -- [Gene ontology](https://geneontology.org/docs/tools-overview/) -- [Ensembl gene IDs](https://www.ebi.ac.uk/training/online/courses/ensembl-browsing-genomes/navigating-ensembl/investigating-a-gene/#:~:text=Ensembl%20gene%20IDs%20begin%20with,of%20species%20other%20than%20human) -- [Medical Subject Headings (MeSH)](https://www.ncbi.nlm.nih.gov/mesh) -- [Chemical Entities of Biological Interest](https://www.ebi.ac.uk/chebi/) -- [Microarray Gene Expression Society Ontology (MGED)](https://mged.sourceforge.net/ontologies/index.php) -- [NCBI taxonomy](https://www.ncbi.nlm.nih.gov/taxonomy) -- [Mondo disease database](https://mondo.monarchinitiative.org/) +- Biological ontologies for data scientists - [Bionty](https://lamin.ai/docs/bionty) +- Anatomy - [Uberon](https://www.ebi.ac.uk/ols4/ontologies/uberon) +- Tissue - [Uberon](http://obophenotype.github.io/uberon) +- Chemical compounds[Chemical Entities of Biological Interest](https://www.ebi.ac.uk/chebi/) +- ExperimentalFactor - [Experimental Factor Ontology](https://www.ebi.ac.uk/ols/ontologies/efo) +- Species - [NCBI Taxonomy](https://www.ncbi.nlm.nih.gov/taxonomy), [Ensembl Species](https://useast.ensembl.org/info/about/species.html) +- Disease - [Mondo](https://mondo.monarchinitiative.org/), [Human Disease](https://disease-ontology.org/) +- Gene - [Ensembl](https://ensembl.org/), [NCBI Gene](https://www.ncbi.nlm.nih.gov/gene), [Gene ontology](https://geneontology.org/docs/tools-overview/),[Microarray Gene Expression Society Ontology (MGED)](https://mged.sourceforge.net/ontologies/index.php) +- Protein - [Uniprot](https://www.uniprot.org/) +- CellLine - [Cell Line Ontology](https://github.com/CLO-ontology/CLO) +- CellType - [Cell Ontology](https://obophenotype.github.io/cell-ontology) +- CellMarker - [CellMarker](http://xteam.xbio.top/CellMarker) +- Phenotype - [Human Phenotype](https://hpo.jax.org/app), [Phecodes](https://phewascatalog.org/phecodes_icd10), [PATO](https://github.com/pato-ontology/pato), [Mammalian Phenotype](http://obofoundry.org/ontology/mp.html), [Zebrafish Phenotype](http://obofoundry.org/ontology/zp.html) +- Pathway - [Gene Ontology](https://bioportal.bioontology.org/ontologies/GO), [Pathway Ontology](https://bioportal.bioontology.org/ontologies/PW) +- DevelopmentalStage - [Human Developmental Stages](https://github.com/obophenotype/developmental-stage-ontologies/wiki/HsapDv), [Mouse Developmental Stages](https://github.com/obophenotype/developmental-stage-ontologies/wiki/MmusDv) +- Drug - [Drug Ontology](https://bioportal.bioontology.org/ontologies/DRON) +- Ethnicity - [Human Ancestry Ontology](https://github.com/EBISPOT/hancestro) +- BFXPipeline - largely based on [nf-core](https://nf-co.re/) +- BioSample - [NCBI BioSample attributes](https://www.ncbi.nlm.nih.gov/biosample/docs/attributes) +- Articles Indexing [Medical Subject Headings (MeSH)](https://www.ncbi.nlm.nih.gov/mesh) ::: :::{.callout-definition} @@ -191,43 +203,19 @@ Requirements: Click on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration. -:::{.callout-hint} -```{.r} -quiet <- function(x) { suppressMessages(suppressWarnings(x)) } -quiet(library(yaml)) -quiet(library(dplyr)) -quiet(library(lubridate)) - -# Function to recursively fetch metadata.yml files -get_metadata <- function(folder_path) { - file_list <- list.files(path = folder_path, - pattern = "metadata\\.yml$", - recursive = TRUE, full.names = TRUE) - metadata_list <- lapply(file_list, yaml::yaml.load_file) - return(metadata_list) -} +You can find a thorough guided exercise in the practical material - [Exercise 4](https://hds-sandbox.github.io/RDM_NGS_course/develop/practical_workshop.html#step-4-review-the-generated-project). -# Specify the folder path -folder_path <- "/path/to/your/folder" +:::{.callout-hint} +```{.r .code-overflow-wrap} +# Load required packages +packages <- c("yaml", "ggplot2", "lubridate") -# Fetch metadata from the specified folder -metadata <- get_metadata(folder_path) +# Function to recursively fetch YAML files files, read and convert them to a data frame -# Convert metadata to a data frame -metadata_df <- data.frame(matrix(unlist(metadata), -ncol = length(metadata), byrow = TRUE)) -colnames(metadata_df) <- names(metadata[[1]]) +df = lapply(file_list, yaml::yaml.load_file) # Save the data frame as a TSV file -output_file <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".tsv") -write.table(metadata_df, - file = output_file, - sep = "\t", - quote = FALSE, - row.names = FALSE) - -# Print confirmation message -print("Database saved as", output_file, "\n") + ``` ::: ::: @@ -251,36 +239,31 @@ An alternative to the tabular format is SQLite, a lightweight and self-contained :::{.callout-exercise} # Exercise 3: Generate a SQLite database from metadata -Click on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration. +Click on the hint to reveal the necessary libraries and some functions, which may serve as inspiration. + +You can find a thorough guided exercise, complete with code example, in the practical material - [Exercise 4, option B](https://hds-sandbox.github.io/RDM_NGS_course/develop/practical_workshop.html#step-4-review-the-generated-project). :::{.callout-hint} ```{.r .code-overflow-wrap} -quiet <- function(x) { suppressMessages(suppressWarnings(x)) } -quiet(library(yaml)) -quiet(library(dplyr)) -quiet(library(lubridate)) -quiet(library(DBI)) - -# Generate the metadata_df using the script from the example above (recursively fetching metadata.yml files) +# Load required packages +packages <- c("yaml", "ggplot2", "lubridate", "DBI") -# Create an SQLite database and insert data -db_file <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".sqlite") -con <- dbConnect(SQLite(), db_file) +# Function to recursively fetch YAML files files, read and convert them to a data frame -dbWriteTable(con, "metadata", metadata_df, row.names = FALSE) +df = lapply(file_list, yaml::yaml.load_file) -# Print confirmation message -cat("Database saved as", db_file, "\n") - -# Close the database connection -dbDisconnect(con) +# Create an SQLite database from a dataframe and insert data +dbConnect(SQLite(), "filenameXXX.sqlite") +dbWriteTable() ``` ::: ::: ### Catalog browser -You can design a user-friendly catalog browser for your database using tools like [Rshiny](https://www.rstudio.com/products/shiny/) or [Panel](https://panel.holoviz.org/). These frameworks provide interfaces for dynamic search, filtering, and visualization, facilitating efficient exploration of database contents. Creating such a tool with Rshiny from both a TSV file and a SQLite database will be demonstrated below. +To further optimize the use of your metadata and improve the integration of all your lab metadata, you can design a user-friendly catalog browser for your database using tools like [Rshiny](https://www.rstudio.com/products/shiny/) or [Panel](https://panel.holoviz.org/). These frameworks provide interfaces for dynamic search, filtering, and visualization, facilitating efficient exploration of database contents. + +Creating such a tool with RShiny is straightforward and does not require extensive development knowledge, whether using a TSV file or a SQLite database. In the [practical materials](https://hds-sandbox.github.io/RDM_NGS_course/develop/practical_workshop.html#create-a-catalog-of-your-data-folder), we demonstrate both scenarios and showcase various functionalities for inspiration. SQLite files are particularly advantageous for data fetching and other operations due to their efficient querying and indexing capabilities. Here's an example of an SQLite database catalog created by the [Brickman Lab](https://renew.ku.dk/research/reseach-groups/brickman-group/) at the Center for Stem Cell Medicine. It's simple yet effective! Clicking on a data row opens the metadata.yml file, allowing access to detailed metadata for that assay. @@ -288,114 +271,43 @@ Here's an example of an SQLite database catalog created by the [Brickman Lab](ht :::{.callout-exercise} # Exercise 4: Create your first catalog browser using Rshiny -Click on the hint to reveal the solution and a code example for the exercise, which may serve as inspiration. - -- Solution A. From a TSV +Go to the [practical material](https://hds-sandbox.github.io/RDM_NGS_course/develop/practical_workshop.html#create-a-catalog-of-your-data-folder) for complete exercise instructions and solutions. The code provided can serve as inspiration for you to adapt as needed. :::{.callout-hint .code-overflow-wrap} -R script -```{.r} - -quiet <- function(x) { suppressMessages(suppressWarnings(x)) } -quiet(library(shiny)) -quiet(library(DT)) - -# UI -ui <- fluidPage( - titlePanel("TSV File Viewer"), - - sidebarLayout( - sidebarPanel( - fileInput("file", "Choose a TSV file", accept = c(".tsv")) - ), - - mainPanel( - DTOutput("table") - ) - ) -) - -# Server -server <- function(input, output) { - - data <- reactive({ - req(input$file) - read.delim(input$file$datapath, sep = "\t") - }) - - output$table <- renderDT({ - datatable(data()) - }) -} +These are some of the libraries required: +`install.packages(c("shiny", "DT", "DBI"))` -# Run the app -shinyApp(ui, server) -``` -::: +You need to define both a user interface (UI) and a server function. The UI (`fluidPage()`) outlines the app's layout using for example, the `sidebarLayout()` and `mainPanel()` functions for input controls and output displays. -- Solution B. From an SQLite database +The server function manages data manipulation and user interactions. Use `shinyApp()` to launch the app once the UI and server are set up. -:::{.callout-hint .code-overflow-wrap} -R script -```{.r} -quiet <- function(x) { suppressMessages(suppressWarnings(x)) } -quiet(library(shiny)) -quiet(library(DT)) -quiet(library(DBI)) - -# UI -ui <- fluidPage( - titlePanel("SQLite Database Viewer"), - - sidebarLayout( - sidebarPanel( - fileInput("db_file", "Choose an SQLite Database", accept = c(".sqlite")), - textInput("table_name", "Enter Table Name:", value = ""), - actionButton("load_button", "Load Table") - ), - - mainPanel( - DTOutput("table") - ) - ) -) - -# Server -server <- function(input, output, session) { - - con <- reactive({ - if (!is.null(input$db_file)) { - dbConnect(SQLite(), input$db_file$datapath) - } - }) - - data <- reactive({ - req(input$load_button > 0, input$table_name, con()) - query <- glue::glue_sql("SELECT * FROM {dbQuoteIdentifier(con(), input$table_name)}") - dbGetQuery(con(), query) - }) - - output$table <- renderDT({ - datatable(data()) - }) - - observeEvent(input$load_button, { - output$table <- renderDT({ - datatable(data()) +Here is a simple example of a server function settup including the main parts (additional components provide advanced functionalities): + +```{.r .code-overflow-wrap} + server <- function(input, output, session) { + # Define a reactive expression for data based on user inputs + data <- reactive({ + req(input$dataInput) # Ensure data input is available + # Load or manipulate data here + }) + + # Define an output table based on data + output$dataTable <- renderTable({ + data() # Render the data as a table + }) + + # Observe a button click event and perform an action + observeEvent(input$actionButton, { + # Perform an action when the button is clicked }) - }) - - # Disconnect from the database when app closes - observe({ - on.exit(dbDisconnect(con()), add = TRUE) - }) -} -# Run the app -shinyApp(ui, server) + # Define cleanup tasks when the app stops + onStop(function() { + # Close connections or save state if necessary + }) +} ``` ::: - ::: @@ -403,10 +315,24 @@ shinyApp(ui, server) # Exercise 5: Add complex features to your catalog browser Once you've finished the previous exercise, consider implementing these additional ideas to maximize the utility of your catalog browser. -- Add a tab to create a project directory interactively (and fill up the metadata fields) +- Add a functionality to only select certain columns `uiOutput("column_select")` +- Add buttons to order numeric columns ascending or descending using `radioButtons()` +- Use SQL aggregation functions (e.g., SUM, COUNT, AVG) to perform custom data summaries and calculations. +- Add a tab `tabPanel()` to create a project directory interactively (and fill up the metadata fields), tips: `dir.create()`, `data.frame()`, `write.table()` - Modify existing entries -- Visualize results using [Cirrocumulus](https://cirrocumulus.readthedocs.io/en/latest/) +- Visualize results using [Cirrocumulus](https://cirrocumulus.readthedocs.io/en/latest/), an interactive visualization tool for large-scale single-cell genomics data. + +:::{.callout-hint} +Explore this example with advanced features such as a two-tab layout, filtering by numeric values and matching strings, and a color-customized dashboard [here](./scripts/shiny_sqlite_advanced.r){ target="_blank"}. +::: + +::: +:::{.callout-tip} +- For R Enthusiasts +Explore [demos](https://shiny.posit.co/r/gallery/#feature-demos)from the R Shiny community to kickstart your projects or for inspiration. +- For python Enthusiasts +If you want to dive deeper into Shiny apps and their various uses (such as dynamic plots or other interactive widgets), Shiny for Python provides live, interactive code throughout its entire tutorial. Additionally, it offers a great tool called [Playground](https://shinylive.io/py/examples/#basic-app), where you can code and test your own app to explore how different features render. ::: ## Wrap up @@ -424,7 +350,6 @@ Other sources: - [Johns Hopkins Sheridan libraries, RDM](https://guides.library.jhu.edu/documenting_data/medical_research#s-lg-box-wrapper-31197839). They provide a list of medical metadata standards resources. - KU Leuven Guidance: - [Transcriptomics metadata standards and fields](https://faircookbook.elixir-europe.org/content/recipes/interoperability/transcriptomics-metadata.html#analysis-metadata) -- Biological ontologies for data scientists,[Bionty](https://lamin.ai/docs/bionty) - [NIH standardizing data collection](https://www.nlm.nih.gov/oet/ed/cde/tutorial/index.html) - [Observational Health Data Sciences and Informatics (OHDSI) OMOP Common Data Model](https://www.ohdsi.org/data-standardization/) @@ -432,4 +357,5 @@ Other sources: ### Tools and software - [Rightfield](https://rightfield.org.uk/): open source tool facilitates the integration of ontology terms into Excel spreadsheet. - [Owlready2](https://pypi.org/project/owlready2/): Python package, enables the loading of ontologies as Python objects. This versatile tool allows users to manipulate and store ontology classes, instances, and properties as needed. +- [Shiny Apps](https://shiny.posit.co/): easy interactive web apps for data science diff --git a/develop/05_VC.qmd b/develop/05_VC.qmd index 8ce1652d..54f6d701 100644 --- a/develop/05_VC.qmd +++ b/develop/05_VC.qmd @@ -80,7 +80,7 @@ We will discuss repositories for archiving experimental or large datasets in [le Moving from Git to GitHub involves transitioning from a local version control setup to a remote hosting platform. You will need a GitHub account for the exercise in this section. :::{.callout-tip title="Create a GitHub account"} -- If you don't have a GitHub account yet, click [here](https://github.com/signup). +- If you don't have a GitHub account yet, click [here](https://github.com/signup) - Install Git from [Git webpage](https://git-scm.com/downloads) ::: @@ -95,14 +95,14 @@ If you completed all the exercises in [lesson 3](./03_DOD.qmd), you should have :::{.callout-exercise} # Exercise 1: initialize a repository from an existing folder: -1. First, initialize the repository using the command `git init`. This command is run only once, even in collaborative projects ([`git init`](https://git-scm.com/docs/git-init)). -2. Once the repository is initialized, create a remote repository on GitHub. -3. Add the remote URL to your local git repository using git remote add origin \`. This associates the remote URL with the name "origin". -4. Ensure you have at least one commit in your history by staging existing files with `git add` and then creating a snapshot, known as committing, with `git commit`. -5. Finally, push your local commits to the remote repository and establish a tracking relationship using `git push -u origin master`. +1. Initialize the repository: Begin by running the command `git init` in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See ([`git init`](https://git-scm.com/docs/git-init)) for more details. +2. Create a remote repository: Once the local repository is initialized, create am empty new repository on GitHub. +3. Connect the remote repository: Add the GitHub repository URL to your local repository using the command `git remote add origin `. This associates the remote repository with the name "origin." +4. Commit changes: If you have files you want to add to your repository, stage them using `git add .`, then create a commit to save a snapshot of your changes with `git commit -m "add local folder"`. +5. Push to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using `git push -u origin main`. ::: -##### Set Up a Git Repository and copy your project folder +##### Setting Up a Git Repository and copying an existing folder Alternatively to converting folders to repositories, you can create a new repository remotely, and then clone (`git clone`) it locally. Here, `git init` is not needed. You can move the files into the repository locally (`git add`, `git commit`, and `git push`). If you are creating a collaborative repository, you can now share it with your colleagues. @@ -113,9 +113,9 @@ Write useful and clear Git commits. Check out [this post](https://www.convention ### Github pages -After setting up your repository on GitHub, take advantage of the opportunity to enhance it by adding your data analysis reports. Whether they are in Jupyter Notebooks, Rmarkdowns, or HTML reports, you can showcase them on a [GitHub Page](https://pages.github.com/). +After setting up your repository on GitHub, take advantage of the opportunity to enhance it by adding your data analysis reports. Whether they are in Jupyter Notebooks, R Markdown files, or HTML reports, you can showcase them on a [GitHub Page](https://pages.github.com/). -Once you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, Rmarkdowns, or HTML reports, in a [GitHub Page website](https://pages.github.com/). Creating a GitHub page is very simple, and we recommend that you follow the nice tutorial that GitHub has put for you. +Once you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, R Markdown files, or HTML reports, in a [GitHub Page website](https://pages.github.com/). Creating a GitHub page is very simple, and we recommend that you follow the nice tutorial that GitHub has put for you. For simplicity, we recommend using [Quarto](https://quarto.org/) or [MkDocs](https://www.mkdocs.org/). Visit their websites and follow the instructions to get started. @@ -134,3 +134,4 @@ In this lesson, we explored version control and utilized Git and GitHub to estab ### Sources - [Version Control and Code Repository Link](https://guides.library.jhu.edu/c.php?g=1096705&p=8066729). +- [Git cheat sheet](https://education.github.com/git-cheat-sheet-education.pdf). \ No newline at end of file diff --git a/develop/06_pipelines.qmd b/develop/06_pipelines.qmd index 8367b375..13d3b30c 100644 --- a/develop/06_pipelines.qmd +++ b/develop/06_pipelines.qmd @@ -60,3 +60,4 @@ This lesson emphasized the importance of reproducibility in computational resear - [Guide to reproducible code in ecology and evolution](https://www.britishecologicalsociety.org/wp-content/uploads/2017/12/guide-to-reproducible-code.pdf) - [Best practices for Scientific computing](https://journals.plos.org/plosbiology/article?id=10.1371/journal.pbio.1001745) - [Elixir Software Best Practices](https://elixir-europe.org/platforms/tools/software-best-practices) +- [faircookbook worflows](https://faircookbook.elixir-europe.org/content/recipes/applied-examples/fair-workflows.html) diff --git a/develop/assets/other_metadata.txt b/develop/assets/other_metadata.txt deleted file mode 100644 index 6e697261..00000000 --- a/develop/assets/other_metadata.txt +++ /dev/null @@ -1,34 +0,0 @@ -https://lamin.ai/docs/bionty - -Gene - [Ensembl](https://ensembl.org/), [NCBI Gene](https://www.ncbi.nlm.nih.gov/gene) - -Protein - [Uniprot](https://www.uniprot.org/) - -Species - [NCBI Taxonomy](https://www.ncbi.nlm.nih.gov/taxonomy), [Ensembl Species](https://useast.ensembl.org/info/about/species.html) - -CellLine - [Cell Line Ontology](https://github.com/CLO-ontology/CLO) - -CellType - [Cell Ontology](https://obophenotype.github.io/cell-ontology) - -CellMarker - [CellMarker](http://xteam.xbio.top/CellMarker) - -Tissue - [Uberon](http://obophenotype.github.io/uberon) - -Disease - [Mondo](https://mondo.monarchinitiative.org/), [Human Disease](https://disease-ontology.org/) - -Phenotype - [Human Phenotype](https://hpo.jax.org/app), [Phecodes](https://phewascatalog.org/phecodes_icd10), [PATO](https://github.com/pato-ontology/pato), -[Mammalian Phenotype](http://obofoundry.org/ontology/mp.html), [Zebrafish Phenotype](http://obofoundry.org/ontology/zp.html) - -Pathway - [Gene Ontology](https://bioportal.bioontology.org/ontologies/GO), [Pathway Ontology](https://bioportal.bioontology.org/ontologies/PW) - -ExperimentalFactor - [Experimental Factor Ontology](https://www.ebi.ac.uk/ols/ontologies/efo) - -DevelopmentalStage - [Human Developmental Stages](https://github.com/obophenotype/developmental-stage-ontologies/wiki/HsapDv), [Mouse Developmental Stages](https://github.com/obophenotype/developmental-stage-ontologies/wiki/MmusDv) - -Drug - [Drug Ontology](https://bioportal.bioontology.org/ontologies/DRON) - -Ethnicity - [Human Ancestry Ontology](https://github.com/EBISPOT/hancestro) - -BFXPipeline - largely based on [nf-core](https://nf-co.re/) - -BioSample - [NCBI BioSample attributes](https://www.ncbi.nlm.nih.gov/biosample/docs/attributes) \ No newline at end of file diff --git a/develop/examples/mkdocs_pages.qmd b/develop/examples/mkdocs_pages.qmd new file mode 100644 index 00000000..42e80a52 --- /dev/null +++ b/develop/examples/mkdocs_pages.qmd @@ -0,0 +1,45 @@ +--- +format: html +summary: Build git pages using mkdocs +--- +# Build your GitHub Page using Mkdocs + +:::{.callout-exercise} + +# Exercise 5: make a project folder and publish a data analysis webpage + +1. Configure your main GitHub Page and its repo + + The first step is to set up the main GitHub Page site and the repository that will host it. This is very simple, as you will only need to follow [these steps](https://pages.github.com/). In a Markdown document, outline the primary objectives of the organization and provide an overview of ongoing research projects. + After you have created the *organization/username*github.io, it is time to configure your `Project` repository webpage using MkDocs! + +2. Start a new project from Cookiecutter or use one from the previous exercise. + + If you use a `Project` repo from the first exercise, go to the next paragraph. Using Cookiecutter, create a new data analysis project. Remember to fill up your metadata and description files! After you have created the folder, it would be best to initialize a Git repo following the instructions from the [previous section](#creating-a-git-repo-online-and-copying-your-project-folder). + + Next, link your data of interest (or create a small fake dataset) and make an example of a data analysis notebook/report (this could be just a scatter plot of a random matrix of values). Depending on your setup, you might be using Jupyter Notebooks or R Markdown files. The extensions that we have installed using `pip` allow you to directly add a Jupyter Notebook file to the `mkdocs.yml` navigation section. On the other hand, if you are using R Markdown files, you will have to knit your document into either an HTML page or a GitHub document. + + For the purposes of this exercise, we have already included a basic `index.md` markdown file that can serve as the intro page of your repo, and a `jupyter_example.ipynb` with some code in it. You are welcome to modify them further to test them out! + +3. Use MkDocs to create your webpage + + When you are happy with your files and are ready to publish them, make sure to add, commit, and push the changes to the remote. Then, build up your webpage using MkDocs and the [`mkdocs gh-deploy`](https://www.mkdocs.org/user-guide/deploying-your-docs/) command from the same directory where the `mkdocs.yml` file is. For example, if your `mkdocs.yml` for your `Project` folder is in `/Users/JARH/Projects/project1_JARH_20231010/mkdocs.yml`, do `cd /Users/JARH/Projects/project1_JARH_20231010/` and then `mkdocs gh-deploy`. + This requires a couple of changes in your GitHub organization settings. + + Remember to make sure that your markdowns, images, reports, etc., are included in the `docs` folder and properly set up in the navigation section of your `mkdocs.yml` file. + + Finally, we only need to set up the GitHub `Project` repo settings. + +4. Publishing your GitHub Page + + Go to your GitHub repo settings and configure the Page section. Since you are using the `mkdocs gh-deploy` command to publish your site in the `gh-pages` branch (as explained the the mkdocs documentation), we need to change where GitHub is fetching the website. You will need to configure the settings of this repository in GitHub so that the Page is taken from the `gh-pages` branch and the `root` folder. + + ![GitHub Pages setup](../images/git_pages.png) + + - Branch should be `gh-pages` + - Folder should be `root` + + After a couple of minutes, your webpage should be ready! You should be able to see your webpage through the link provided in the Page section! + +Now it is also possible to include this repository webpage in your main webpage ``.*github.io by including the link of the repo website (https://``.*github.io/*repo-name*) in the navigation section of the `mkdocs.yml` file in the main *organization*github.io repo. +::: \ No newline at end of file diff --git a/develop/images/github_pages_quarto.png b/develop/images/github_pages_quarto.png new file mode 100644 index 0000000000000000000000000000000000000000..4c326730a810b37294fe02a2fff5b520c5fe7fb2 GIT binary patch literal 183828 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 axxH0{;OwMlGfvk^VI;0 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�YqNOQ;^J&TIxev2 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�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 literal 0 HcmV?d00001 diff --git a/develop/practical_workshop.qmd b/develop/practical_workshop.qmd index 130153d5..db59e006 100644 --- a/develop/practical_workshop.qmd +++ b/develop/practical_workshop.qmd @@ -1,6 +1,8 @@ --- title: Practical material -format: html +format: + html: + code-copy: true date-modified: last-modified date-format: long date: 2023-11-30 @@ -226,9 +228,8 @@ Beyond substituting placeholders in file and directory names, Cookiecutter can a First, modify the `my_template/main.py` file to include a placeholder inside its contents: -```{.python .code-overflow-wrap} +```{.python .code-overflow-wrap filename="main.py"} # main.py - def hello(): print("Hello, {{cookiecutter.project_name}}!") ``` @@ -238,10 +239,9 @@ The '{{cookiecutter.project_name}}' placeholder is now included within the main. After running Cookiecutter, your generated 'main.py' file could appear as follows: ```{.python .code-overflow-wrap} -# main.py - +# main.py, assuming "MyProject" was entered as the project_name def hello(): - print("Hello, MyProject!") # Assuming "MyProject" was entered as the project_name + print("Hello, MyProject!") ``` ##### Step 3: Use Cookiecutter @@ -446,7 +446,7 @@ It is time now to customize your Cookiecutter templates and modify the metadata. 0. Consider changing variables (add/remove) in the metadata.yml file from the cookicutter template. 1. Modify the `cookiecutter.json` file. You could add new variables or change the default key and/or values: - ```{.json .code-overflow-wrap} + ```{.json .code-overflow-wrap filename="cookiecutter.json"} { "project_name": "myProject", "project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}", @@ -460,7 +460,7 @@ The metadata file will be filled accordingly. 2. Optional: You can customize or remove this prompt message entirely, allowing you to tailor the text to your preferences for a unique experience each time you use the template. - ```{.json .code-overflow-wrap} + ```{.json .code-overflow-wrap filename="cookiecutter.json"} "__prompts__": { "project_name": "Project directory name [Example: project_short_description_202X]", "author": "Author of the project", @@ -471,7 +471,7 @@ The metadata file will be filled accordingly. 3. Modify the `metadata.yml` file so that it includes the metadata recorded by the `cookiecutter.json` file. Hint below: - ```{.json .code-overflow-wrap} + ```{.yml .code-overflow-wrap filename="metadata.yml"} project: {{ cookiecutter.project_name }} author: {{ cookiecutter.author }} date: {{ cookiecutter.date }} @@ -479,7 +479,7 @@ The metadata file will be filled accordingly. ``` 4. Modify the `README.md` file so that it includes the short description recorded by the `cookiecutter.json` file and the metadata at the top of the markdown file (top between lines of dashed). - ```{.md .code-overflow-wrap} + ```{.md .code-overflow-wrap filename="README.md"} --- title: {{ cookiecutter.project_name }} date: "{{ cookiecutter.date }}" @@ -524,27 +524,43 @@ Avoid long and complicated names and ensure your file names are both informative ## 4. Create a catalog of your data folder -The next step is to collect all the NGS datasets that you have created in the manner explained above. Since your folders all should contain the `metadata.yml` file in the same place with the same metadata, it should be very easy to iteratively go through all the folders and merge all the metadata.yml files into a one single table. This table can be then browsed easily with Microsoft Excel, for example. If you are interested in making a Shiny app or Python Panel tool to interactively browse the catalog, check out this [lesson](./04_metadata.qmd). +The next step is to collect all the datasets that you have created in the manner explained above. Since your folders all should contain the `metadata.yml` file in the same place with the same metadata, it should be very easy to iteratively go through all the folders and merge all the metadata.yml files into a one single table. he table can be easily viewed in your terminal or even with Microsoft Excel. :::{.callout-exercise} # Exercise 4: create a metadata.tsv catalog -We will make a small script in R (or you can make one with Python) that recursively goes through all the folders inside an input path (like your `Assays` folder), fetches all the `metadata.yml` files, and merges them. Finally, it will write a TSV file as an output. +We will make a small script in R (or you can make one with Python) that recursively goes through all the folders inside an input path (like your `Assays` folder), fetches all the `metadata.yml` files, merges them and writes a TSV file as an output. 1. Create a folder called `dataset` and change directory `cd dataset` -2. Fork [this repository](https://github.com/hds-sandbox/cc-data-template): a Cookiecutter template designed for NGS datasets. -While you are welcome to create your own template from scratch, we recommend using this one to save time. +2. Fork [this repository](https://github.com/hds-sandbox/cc-data-template): a Cookiecutter template designed for NGS datasets.*While you are welcome to create your own template from scratch, we recommend using this one to save time.* 3. Run the `cookiecutter cc-data-template` command at least twice to create multiple datasets or projects. Use different values each time to simulate various scenarios (do this in the dataset directory that you have previously created). -Execute the script below using R (or create your own script in Python). Adjust the `folder_path` variable so that it matches the path to the Assays folder. The resulting table will be saved in the same `folder_path`. -4. Open your `database_YYYYMMDD.tsv` table in a text editor from the command-line, or view it in Excel for better visualization. +4. Execute the script below using R (or create your own script in Python). **Adjust the `folder_path`** variable so that it matches the path to the Assays folder. The resulting table will be saved in the same `folder_path`. +5. Open your `database_YYYYMMDD.tsv` table in a text editor from the command-line, or view it in Excel for better visualization. + +- Solution A. From a TSV +:::{.callout-hint} ```{.r .code-overflow-wrap} +# R version 4.3.2 +# RScript to read all yaml files in directory and save the metadata into a dataframe +quiet <- function(package_name) { + # Suppress warnings and messages while checking and installing the package + suppressMessages(suppressWarnings({ + # Check if the package is available and load it + if (!requireNamespace(package_name, quietly = TRUE)) { + install.packages(package_name) + } + # Load the package + library(package_name, character.only = TRUE) + })) +} + +# Check and install necessary libraries +quiet("yaml") +quiet("dplyr") +quiet("lubridate") -library(yaml) -library(dplyr) -library(lubridate) -# Function to read a YAML file and transform it into a dataframe format. read_yaml <- function(file_path) { # Read the YAML file and convert it to a data frame df <- yaml::yaml.load_file(file_path) %>% as.data.frame(stringsAsFactors = FALSE) @@ -566,88 +582,292 @@ get_metadata <- function(folder_path) { } # Specify the folder path -folder_path <- "/path/to/your/folder" +folder_path <- "./" #/path/to/your/folder # Fetch metadata from the specified folder -metadata <- get_metadata(folder_path) +df <- get_metadata(folder_path) # Save the data frame as a TSV file output_file <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".tsv") -write.table(metadata, file = output_file, sep = "\t", quote = FALSE, row.names = FALSE) +write.table(df, file = output_file, sep = "\t", quote = FALSE, row.names = FALSE) # Print confirmation message cat("Database saved as", output_file, "\n") ``` ::: -## 5. Version control of your data analysis using Git and GitHub -Version control is a systematic approach to tracking changes made to a project over time. It provides a structured means of documenting alterations, allowing you to revisit and understand the evolution of your work. In research data management and data analytics, version control is very important and gives you a lot of advantages. +**Exercise 4, option B: create a SQLite database ** -[Git](https://git-scm.com/about) is a distributed version control system that enables developers and researchers to efficiently manage their project's history, collaborate seamlessly, and ensure data integrity. At its core, Git operates through the following principles and mechanisms: -On the other hand, [GitHub](https://github.com/) is a web-based platform that enhances Git's capabilities by providing a collaborative and centralized hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects. +Alternatively, create a SQLite database from a metadata. If you opt for this option in the exercise, you must still complete the first three steps outlined above. Read more from the [RSQLite documentation](https://www.rdocumentation.org/packages/RSQLite/versions/2.3.6). -:::{.callout-tip title="Create a GitHub organization for your lab or department"} -GitHub allows users to create organizations and teams that will collaborate or create repositories under the same umbrella organization. If you would like to create an educational organization in GitHub, you can do so for free! For example, you could create a GitHub account for your lab. +- Solution B. SQLite database -To create a GitHub organization, follow these [instructions](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch) +:::{.callout-hint} +```{.r .code-overflow-wrap} +print("Assuming the libraries from Exercise 4 are already loaded and a dataframe has been generated from the YAML files...") + +# check_and_install() form Exercise 4, and load the other packages. +quiet("DBI") +quiet("RSQLite") + +# Initialize a temporary in memory database and copy the data.frame into it + +db_file_path <- paste0("database_", format(Sys.Date(), "%Y%m%d"), ".sqlite") +con <- dbConnect(RSQLite::SQLite(), db_file_path) + +dbWriteTable(con, "metadata", df, overwrite=TRUE) #row.names = FALSE,append = -After you have created the GitHub organization, make sure that you create your repositories under the organization space and not your user! +# Print confirmation message +cat("Database saved as", db_file_path, "\n") + +# Close the database connection +dbDisconnect(con) + +``` +::: ::: -### Creating a git repo online and copying your project folder +### Shiny apps -Version controlling your data analysis folders, a.k.a. `Project` folder, is very easy once you have set up your Cookiecutter templates. The simplest way of doing this is to first create a remote GitHub repository from the webpage (or from the Desktop app, if you are using it) with a proper project name. Then `git clone` that repository you just made into your `Projects` main folder. Then, use cookiecutter to create a project folder template and copy-paste the contents of the folder template to your cloned repo. Remember to fill up your metadata and description files! If you wish, you could already git add, commit, and push the first changes to the folders and continue from there on. +To get the most out of your metadata file and the ones from other colleagues, you can combine them and explore them by creating an interactive catalog browser. You can create interactive web apps straight from R or Python. Whether you have generated a tabulated-file or a sqlite database, browse through the metadata using [Shiny](https://shiny.posit.co/). Shiny apps are perfect for researchers because they enable you to create interactive visualizations and dashboards with dynamic data inputs and outputs without needing extensive web development knowledge. Shiny provides a variety of user interface components such as forms, tables, graphs, and maps to help you organize and present your data effectively. It also allows you to filter, sort, and segment data for deeper insights. -Go back to the course material [lesson 5](./05_VC.qmd) and read the differences between converting folders to git repositories and cloning a folder to an existing git repository. -:::{.callout-tip title="Tips to write good commit messages"} -If you would like to know more about Git commits and the best way to make clear Git messages, check out [this post](https://www.conventionalcommits.org/en/v1.0.0/)! +:::{.callout-tip} +- For R Enthusiasts + +Explore [demos](https://shiny.posit.co/r/gallery/#feature-demos) from the R Shiny community to kickstart your projects or for inspiration. + +- For python Enthusiasts + +Shiny for Python provides live, interactive code throughout its entire tutorial. Additionally, it offers a great tool called [Playground](https://shinylive.io/py/examples/#basic-app), where you can code and test your own app to explore how different features render. ::: -### GitHub Pages -Once you have created your repository (and put it in GitHub), you have now the opportunity to add your data analysis reports that you created, in either Jupyter Notebooks, Rmarkdowns, or HTML reports, in a [GitHub Page website](https://pages.github.com/). Creating a GitHub page is very simple, and we really recommend that you follow the nice tutorial that GitHub has put for you. Nonetheless, we will see the main steps in the exercise below. +:::{.callout-exercise} +# Exercise 5: Skill Booster, build an interactive catalog browser + +Build an interactive web app straight from R or Python. Below, you will find an example of an R shiny app. In either case, you will need to define a user interface (UI) and a server function. The UI specifies the layout and appearance of the app, including input controls and output displays. The server function contains the app's logic, handling data manipulation, and responding to user interactions. Once you set up the UI and server, you can launch the app! + +Here's the UI and server function structure for an R Shiny app: + +```{.r .code-overflow-wrap} +# Don't forget to load shiny and DT libraries! + +# Specify the layout +ui <- fluidPage( + titlePanel(...) + # Define the appearance of the app + sidebarLayout( + sidebarPanel(...) + mainPanel(...) + ) +) + +server <- function(input, output, session) { + # Define a reactive expression for data based on user inputs + data <- reactive({ + req(input$dataInput) # Ensure data input is available + # Load or manipulate data here + }) + + # Define an output table based on data + output$dataTable <- renderTable({ + data() # Render the data as a table + }) + + # Observe a button click event and perform an action + observeEvent(input$actionButton, { + # Perform an action when the button is clicked + }) + + # Define cleanup tasks when the app stops + onStop(function() { + # Close connections or save state if necessary + }) +} +# Run the app +shinyApp(ui, server) +``` +If you need more assistance, take a look at the code below (Hint). + +:::{.callout-hint} +```{.r .code-overflow-wrap} +# R version 4.3.2 +print("Assuming the libraries from Exercise 4 are already loaded and a dataframe has been generated from the YAML files...") + +# check_and_install() form Exercise 4. +quiet("shiny") +quiet("DT") + +# UI +ui <- fluidPage( + titlePanel("TSV File Viewer"), + + sidebarLayout( + sidebarPanel( + fileInput("file", "Choose a TSV file", accept = c(".tsv")), + selectInput("filter_column", "Filter by Column:", choices = c("n_samples", "technology"), selected = "technology"), + textInput("filter_value", "Filter Value:", value = ""), + # if only numbers, numericInput() + radioButtons("sort_order", "Sort Order:", choices = c("Ascending", "Descending"), selected = "Ascending") + ), + + mainPanel( + DTOutput("table") + ) + ) +) + +# Server +server <- function(input, output) { + + data <- reactive({ + req(input$file) + df <- read.delim(input$file$datapath, sep = "\t") + print(str(df)) + + # Filter the DataFrame based on user input + if (input$filter_column != "" && input$filter_value != "") { + # Check if the column is numeric, and filter for value + if (is.numeric(df[[input$filter_column]])) { + df <- df[df[[input$filter_column]] >= as.numeric(input$filter_value), ] + } + # Check if the column is a string + else if (is.character(df[[input$filter_column]])) { + df <- df[df[[input$filter_column]] == input$filter_value, ] + } + } + + # Sort the DataFrame based on user input + sort_order <- if (input$sort_order == "Ascending") TRUE else FALSE + df <- df[order(df[[input$filter_column]], decreasing = !sort_order), ] + df + }) + + output$table <- renderDT({ + datatable(data()) + }) +} + +# Run the app +shinyApp(ui, server) +``` +::: +In the optional exercise below, you'll find a code example for using an SQLite database as input instead of a tabulated file. +::: -There are many different ways to create your web pages. We recommend using Mkdocs and Mkdocs materials as a framework to create a nice webpage simply. The folder templates that we used as an example in the previous exercise already contain everything you need to start a webpage. Nonetheless, you will need to understand the basics of [MkDocs](https://www.mkdocs.org/) and [MkDocs materials](https://squidfunk.github.io/mkdocs-material/) to design a webpage to your liking. MkDocs is a static webpage generator that is very easy to use, while MkDocs materials is an extension of the tool that gives you many more options to customize your website. Check out their web pages to get started! :::{.callout-exercise} -# Exercise 5: make a project folder and publish a data analysis webpage +# Exercise (optional) +Once you've finished the previous exercise, consider implementing these additional ideas to maximize the utility of your catalog browser. -1. Configure your main GitHub Page and its repo +- Use SQLite databases as input +- Add a functionality to only select certain columns `uiOutput("column_select")` +- Filter columns by value using `column_filter_select()` +- Add multiple tabs using `tabsetPanel()` +- Add buttons to order numeric columns ascending or descending using `radioButtons()` +- Use SQL aggregation functions (e.g., SUM, COUNT, AVG) to perform custom data summaries and calculations. +- Add a tab `tabPanel()` to create a project directory interactively (and fill up the metadata fields), tips: `dir.create()`, `data.frame()`, `write.table()` +- Modify existing entries +- Visualize results using [Cirrocumulus](https://cirrocumulus.readthedocs.io/en/latest/), an interactive visualization tool for large-scale single-cell genomics data. - The first step is to set up the main GitHub Page site and the repository that will host it. This is very simple, as you will only need to follow [these steps](https://pages.github.com/). In a Markdown document, outline the primary objectives of the organization and provide an overview of ongoing research projects. - After you have created the *organization/username*github.io, it is time to configure your `Project` repository webpage using MkDocs! +If you need some assistance, take a look at the code below (Hint). -2. Start a new project from Cookiecutter or use one from the previous exercise. +:::{.callout-hint} +Explore an example with advanced features such as a two-tab layout, filtering by numeric values and matching strings, and a color-customized dashboard [here](./scripts/shiny_sqlite_advanced.r){ target="_blank"}. +::: +::: - If you use a `Project` repo from the first exercise, go to the next paragraph. Using Cookiecutter, create a new data analysis project. Remember to fill up your metadata and description files! After you have created the folder, it would be best to initialize a Git repo following the instructions from the [previous section](#creating-a-git-repo-online-and-copying-your-project-folder). +## 5. Version control using Git and GitHub - Next, link your data of interest (or create a small fake dataset) and make an example of a data analysis notebook/report (this could be just a scatter plot of a random matrix of values). Depending on your setup, you might be using Jupyter Notebooks or Rmarkdowns. The extensions that we have installed using `pip` allow you to directly add a Jupyter Notebook file to the `mkdocs.yml` navigation section. On the other hand, if you are using Rmarkdown, you will have to knit your document into either an HTML page or a GitHub document. - - For the purposes of this exercise, we have already included a basic `index.md` markdown file that can serve as the intro page of your repo, and a `jupyter_example.ipynb` with some code in it. You are welcome to modify them further to test them out! +Version control involves systematically tracking changes to a project over time, offering a structured way to document revisions and understand the progression of your work. In research data management and data analytics, it plays a critical role and provides numerous benefits. -3. Use MkDocs to create your webpage +[Git](https://git-scm.com/about) is a distributed version control system that helps developers and researchers efficiently manage project history, collaborate seamlessly, and maintain data integrity. On the other hand, [GitHub](https://github.com/) is a web-based platform that builds on Git's functionality by providing a centralized, collaborative hub for hosting Git repositories. It offers several key functionalities, such as tracking issues, security features to safeguard your repos, and GitHub Pages that allow you to create websites to showcase your projects. - When you are happy with your files and are ready to publish them, make sure to add, commit, and push the changes to the remote. Then, build up your webpage using MkDocs and the [`mkdocs gh-deploy`](https://www.mkdocs.org/user-guide/deploying-your-docs/) command from the same directory where the `mkdocs.yml` file is. For example, if your `mkdocs.yml` for your `Project` folder is in `/Users/JARH/Projects/project1_JARH_20231010/mkdocs.yml`, do `cd /Users/JARH/Projects/project1_JARH_20231010/` and then `mkdocs gh-deploy`. - This requires a couple of changes in your GitHub organization settings. +:::{.callout-tip title="Create a GitHub organization for your lab or department"} +GitHub users can create organizations, allowing groups to collaborate or create repositories under the same organization umbrella. You can create an educational organization on Github for free, by setting up a Github account for your lab. - Remember to make sure that your markdowns, images, reports, etc., are included in the `docs` folder and properly set up in the navigation section of your `mkdocs.yml` file. +Follow these [instructions](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch) to create a GitHub organization. - Finally, we only need to set up the GitHub `Project` repo settings. +Once you've established your GitHub organization, be sure to create your repositories within the organization's space rather than under your personal user account. This keeps your projects centralized and accessible to the entire group. Best practices for managing an organization on GitHub include setting clear access permissions, regularly reviewing roles and memberships, and organizing repositories effectively to keep your projects structured and easy to navigate. -4. Publishing your GitHub Page - - Go to your GitHub repo settings and configure the Page section. Since you are using the `mkdocs gh-deploy` command to publish your site in the `gh-pages` branch (as explained the the mkdocs documentation), we need to change where GitHub is fetching the website. You will need to configure the settings of this repository in GitHub so that the Page is taken from the `gh-pages` branch and the `root` folder. +::: + +### Setting up a GitHub repository for your project folder + +Version controlling your data analysis folders becomes straightforward once you've established your Cookiecutter templates. After you've created several folder structures and metadata using your Cookiecutter template, you can manage version control by either converting those folders into Git repositories or copying a folder into an existing Git repository. Both approaches are explained in [Lesson 5](https://hds-sandbox.github.io/RDM_NGS_course/develop/05_VC.html#from-project-folders-to-git-repositories). + +:::{.callout-exercise} +# Exercise 6: initialize a repository from an existing folder: +1. Initialize the repository: Begin by running the command `git init` in your project directory. This command sets up a new Git repository in the current directory and is executed only once, even for collaborative projects. See ([`git init`](https://git-scm.com/docs/git-init)) for more details. +2. Create a remote repository: Once the local repository is initialized, create an empty new repository on GitHub (website or Github Desktop). +3. Connect the remote repository: Add the GitHub repository URL to your local repository using the command `git remote add origin `. This associates the remote repository with the name "origin." +4. Commit changes: If you have files you want to add to your repository, stage them using `git add .`, then create a commit to save a snapshot of your changes with `git commit -m "add local folder"`. +5. Push to GitHub: To synchronize your local repository with the remote repository and establish a tracking relationship, push your commits to the GitHub repository using `git push -u origin main`. +::: + +:::{.callout-tip title="Tips to write good commit messages"} +If you would like to know more about Git commits and the best way to make clear Git messages, check out [this post](https://www.conventionalcommits.org/en/v1.0.0/)! +::: + +### GitHub Pages + +After creating your repository and hosting it on GitHub, you can now add your data analysis reports—such as Jupyter Notebooks, R Markdown files, or HTML reports—to a [GitHub Page website](https://pages.github.com/). Setting up a GitHub Page is straightforward, and we recommend following GitHub's helpful tutorial. However, we will go through the key steps in the exercise below. There are several ways to create your web pages, but we suggest using Quarto as a framework to build a sleek, professional-looking website with ease. The folder templates from the previous exercise already contain the necessary elements to launch a webpage. Familiarizing yourself with the basics of Quarto will help you design a webpage that suits your preferences. Other common options include [MkDocs](https://squidfunk.github.io/mkdocs-material/). If you want to use MkDocs instead, click [here](./examples/mkdocs_pages.qmd) and follow the instructions. - ![GitHub Pages setup](./images/git_pages.png) +:::{.callout-tip} +Here are some useful links to get started with Github Pages: + +- [Github Pages](https://pages.github.com/) +- [Quarto Github Pages](https://quarto.org/docs/publishing/github-pages.html) +::: + +:::{.callout-exercise} +# Exercise 7: Create a Github Page using Quarto +1. Head over to GitHub and create a new public repository named username.github.io, where username is your username (or organization name) on GitHub. *If the first part of the repository doesn’t exactly match your username, it won’t work, so make sure to get it right.* +2. Go to the folder where you want to store your project, and clone the new repository: `git clone https://github.com/username/username.github.io` (or use Github Desktop) +3. Create a new file named `_quarto.yml` + + ```{.yml filename="_quarto.yml"} + project: + type: website + ``` - - Branch should be `gh-pages` - - Folder should be `root` +4. Open the terminal + ```{.bash filename="Terminal"} + # Add a .nojekyll file to the root of the repository not to do additional processing of your published site + touch .nojekyll #copy NUL .nojekyll for windows - After a couple of minutes, your webpage should be ready! You should be able to see your webpage through the link provided in the Page section! + # Render and push it to Github + quarto render + git commit -m "Publish site to docs/" + git push + ``` +5. If you do not have a `gh-pages`, you can create one as follows + + ```{.bash filename="Terminal"} + git checkout --orphan gh-pages + git reset --hard # make sure all changes are committed before running this! + git commit --allow-empty -m "Initialising gh-pages branch" + git push origin gh-pages + ``` +6. Before attempting to publish you should ensure that the Source branch for your repository is `gh-pages` and that the site directory is set to the repository root (/) + + ![](./images/github_pages_quarto.png) + +7. It is important to not check your `_site` directory into version control, add the output directory of your project to `.gitignore` + + ```{.bash filename=".gitignore"} + /.quarto/ + /_site/ + ``` +8. Now is time to publish your website + + ```{.bash filename=".Terminal"} + quarto publish gh-pages + ``` -Now it is also possible to include this repository webpage in your main webpage *organization*github.io by including the link of the repo website (https://*organization*github.io/*repo-name*) in the navigation section of the `mkdocs.yml` file in the main *organization*github.io repo. +9. Once you’ve completed a local publish, add a publish.yml GitHub Action to your project by creating this YAML file and saving it to `.github/workflows/publish.yml`. Read how to do it [here](https://quarto.org/docs/publishing/github-pages.html#github-action) ::: ## 6. Archive GitHub repositories on Zenodo diff --git a/develop/scripts/shiny_sqlite_advanced.R b/develop/scripts/shiny_sqlite_advanced.R new file mode 100644 index 00000000..99946538 --- /dev/null +++ b/develop/scripts/shiny_sqlite_advanced.R @@ -0,0 +1,169 @@ +#!/usr/bin/env Rscript + +# Author: Alba Refoyo Martinez +# Copyright: Copyright 2024, University of Copenhagen +# Email: gsd818@ku.dk +# License: MIT +# R version: 4.3.2 + +# Define the UI +ui <- fluidPage( + titlePanel("SQLite R Shiny App"), + + # Use tabsetPanel to add multiple tabs + tabsetPanel( + # Existing tab for browsing the SQLite database + tabPanel("Browse Database", + sidebarLayout( + sidebarPanel( + fileInput("db_file", "Select SQLite Database File", accept = c(".sqlite")), + uiOutput("table_select"), + uiOutput("column_filter_select"), + textInput("filter_value", "Find by value", ""), + actionButton("refresh", "Refresh Tables") + # UI output for selecting columns (populated based on the selected table) + # uiOutput("column_select"), + ), + mainPanel( + DTOutput("tableData") + ) + )), + + # New tab for creating a project directory and filling metadata fields + tabPanel("Create Project Directory", + sidebarLayout( + sidebarPanel( + textInput("project_name", "Project Name:", value = "MyProject"), + textInput("metadata_field1", "Metadata Field 1:", value = ""), + textInput("metadata_field2", "Metadata Field 2:", value = ""), + actionButton("create_project", "Create Project") + ), + mainPanel( + textOutput("message") # To display feedback messages + ) + ) + ) + ) +) + +# Define the server +server <- function(input, output, session) { + # Reactive value to hold the database connection + db_conn <- reactiveVal(NULL) + + # Observe changes in the file input + observeEvent(input$db_file, { + # Check if a file is uploaded + if (!is.null(input$db_file)) { + # Get the path to the uploaded file + db_path <- input$db_file$datapath + + # Disconnect any existing connection + if (!is.null(db_conn())) { + dbDisconnect(db_conn()) + } + + # Establish a new connection to the SQLite database + conn <- dbConnect(RSQLite::SQLite(), dbname = db_path) + db_conn(conn) + + # Update the list of tables + updateTableChoices() + } + }) + + # Function to update the list of tables in the database + updateTableChoices <- function() { + # Ensure there's a database connection + if (!is.null(db_conn())) { + # Retrieve the list of tables in the database + tables <- dbListTables(db_conn()) + # Update the choices in the select input + updateSelectInput(session, "table", choices = tables) + } + } + + # Observe the refresh button + observeEvent(input$refresh, { + updateTableChoices() + }) + + # Render the select input for tables + output$table_select <- renderUI({ + selectInput("table", "Select a table", choices = character(0)) + }) + + # Render the select input for columns (choices populated based on the selected table) + # output$column_select <- renderUI({ + # req(input$table) + # # Read data from the selected table + # data <- dbReadTable(db_conn(), input$table) + # # Get the column names from the data + # columns <- names(data) + # # Create a select input for the column choices + # selectInput("columns", "Select columns", choices = columns, multiple = TRUE) + # }) + + + # Render the select input for columns to filter by + output$column_filter_select <- renderUI({ + req(input$table) + data <- dbReadTable(db_conn(), input$table) + columns <- names(data) + selectInput("column_filter", "Filter by column", choices = columns) + }) + + # Display data from the selected table + output$tableData <- renderDT({ + req(input$table) + data <- dbReadTable(db_conn(), input$table) + + # If filtering by columns, ensure they are selected + # req(input$columns) + #filtered_data <- data[, input$columns, drop = FALSE] + + if (!is.null(input$column_filter) && input$filter_value != "") { + filtered_data <- data[data[[input$column_filter]] == input$filter_value, ] + } else { + filtered_data <- data + } + + datatable(filtered_data) + }) + + # Observe the create_project button + observeEvent(input$create_project, { + project_name <- input$project_name + metadata_field1 <- input$metadata_field1 + metadata_field2 <- input$metadata_field2 + + # Define the project directory path + project_dir <- file.path(getwd(), project_name) + + # Check if the directory already exists + if (dir.exists(project_dir)) { + output$message <- renderText("Directory already exists. Please choose a different project name.") + } else { + # Create the directory + dir.create(project_dir) + + # Save the metadata fields to a TSV file in the project directory + metadata <- data.frame(Field1 = metadata_field1, Field2 = metadata_field2) + metadata_file <- file.path(project_dir, "metadata.tsv") + write.table(metadata, metadata_file, sep = "\t", row.names = FALSE, col.names = TRUE) + + # Provide feedback to the user + output$message <- renderText(paste("Project created successfully in", project_dir)) + } + }) + + # Close the database connection when the app is stopped + onStop(function() { + if (!is.null(db_conn())) { + dbDisconnect(db_conn()) + } + }) +} + +# Run the app +shinyApp(ui = ui, server = server) \ No newline at end of file diff --git a/index.qmd b/index.qmd index 3756ad00..682ea8f6 100644 --- a/index.qmd +++ b/index.qmd @@ -21,6 +21,9 @@ summary: Index page, intro to course # You should hide the navigation if there are no subsections # You should hide the Table of Contents if there are no important titles --> +:::{.callout-warning title="Practical RDM workshop"} +We offer workshops on practical RDM for biodata. Keep an eye on the upcoming events on the [Sandbox website](https://hds-sandbox.github.io/news/news.html). +::: ## Research Data Management for biological data The course "Research Data Management (RDM) for biological data" is designed to provide participants with foundational knowledge and practical skills in handling the extensive data generated by modern studies, with a focus on Next Generation Sequencing (NGS) data. It emphasizes the importance of Open Science and FAIR principles in managing data effectively. This course covers essential principles and best practices guidelines in data organization, metadata annotation, version control, and data preservation. These principles are explored from a computational perspective, ensuring participants gain hands-on experience in applying them to real-world scenarios in their research labs. Additionally, the course delves into FAIR principles and Open Science, promoting collaboration and reproducibility in research endeavors. By the course's conclusion, attendees will possess essential tools and techniques to address the data challenges prevalent in today's NGS research landscape, as well as in other related fields to health and bioinformatics. diff --git a/practical_workflows.qmd b/practical_workflows.qmd index 07b24eb7..0b722eb1 100644 --- a/practical_workflows.qmd +++ b/practical_workflows.qmd @@ -25,7 +25,7 @@ summary: workflow - Create reproducible analyses that can be adapted to new data with little effort ::: -# Workflows +# FAIR Workflows Data analysis typically involves the use of different tools, algorithms, and scripts. It often requires multiple steps to transform, filter, aggregate, and visualize data. The process can be time-consuming because each tool may demand specific inputs and parameter settings. As analyses become more complex, the importance of reproducible and scalable automated workflow management increases. Workflow management encompasses tasks such as parallelization, resumption, logging, and data provenance. @@ -167,10 +167,12 @@ Use git repositories to save your projects and pipelines! ## Nextflow +# FAIR environments + ## Sources - [Snakemake tutorial](https://snakemake.readthedocs.io/en/stable/tutorial/tutorial.html#tutorial) - [Snakemake turorial slides by Johannes Koster](https://slides.com/johanneskoester/snakemake-tutorial) - https://bioconda.github.io - Köster, Johannes and Rahmann, Sven. "Snakemake - A scalable bioinformatics workflow engine". Bioinformatics 2012. - Köster, Johannes. "Parallelization, Scalability, and Reproducibility in Next-Generation Sequencing Analysis", PhD thesis, TU Dortmund 2014. - +- [faircookbook worflows](https://faircookbook.elixir-europe.org/content/recipes/applied-examples/fair-workflows.html) \ No newline at end of file