# Dual Inlet

    # libraries
    library(isoorbi) #load isoorbi R package
    library(forcats) #better ordering of factor variables in plots
    library(dplyr) # for mutating data frames
    #> Warning: package 'dplyr' was built under R version 4.2.3
    library(ggplot2) # for data visualization

# A basic data processing example

    # Read .isox test data
    df <-
      system.file("extdata", "testfile_dual_inlet_new.isox", package = "isoorbi") |>
      orbi_read_isox() |> # reads .isox test data
      orbi_simplify_isox() |> # optionally: keeps only most important columns; equivalent to simplify check box in IsoX
      # check for issues
      orbi_flag_satellite_peaks() |> # removes minor signals that were reported by IsoX in the same tolerance window where the peak of interest is
      orbi_flag_weak_isotopocules(min_percent = 10) |> # removes signals of isotopocules that were not detected at least in min_percent scans
      orbi_flag_outliers(agc_fold_cutoff = 2) |> # removes outlying scans that have more than 2 times or less than 1/2 times the average number of ions in the Orbitrap analyzer; another method: agc_window (see function documentation for more details)
      orbi_define_basepeak(basepeak_def = "M0") # sets one isotopocule in the dataset as the base peak (denominator) for ratio calculation

No satellite peaks, no weak isotopocules, a few AGC fold outliers:

    df |> orbi_plot_raw_data(isotopocule = "15N", y = tic * it.ms, y_scale = "log")

# Define dual inlet blocks

    # define blocks
    df_w_blocks <-
      df |>
      # general definition
      orbi_define_blocks_for_dual_inlet(
        ref_block_time.min = 10, # the reference block is 10 min long
        sample_block_time.min = 10, # the sample block is 10 min long
        startup_time.min = 5, # there is 5 min of data before the reference block starts, to stabilize spray conditions
        change_over_time.min = 2, # it takes 2 min to make sure the right solution is measured after switching the valve
        sample_block_name = "sample",
        ref_block_name = "reference"
      ) |>
      # fine adjustments
      orbi_adjust_block(block = 1, shift_start_time.min = 2) |> # the 1st reference block is shorter by 2 min, cut from the start
      orbi_adjust_block(block = 4, set_start_time.min = 38, set_end_time.min = 44) # the start and end of the 2nd reference block are manually set

    # get blocks info
    blocks_info <- df_w_blocks |> orbi_get_blocks_info()
    blocks_info |> knitr::kable()

filename | data_group | block | sample_name | data_type | segment | start_scan.no | end_scan.no | start_time.min | end_time.min
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
20230518_05_USGS32_vs_USGS34 | 1 | 0 | reference | startup | NA | 5 | 820 | 0.031 | 4.985
20230518_05_USGS32_vs_USGS34 | 2 | 1 | reference | unused | NA | 825 | 1150 | 5.015 | 6.990
20230518_05_USGS32_vs_USGS34 | 3 | 1 | reference | data | NA | 1155 | 2465 | 7.021 | 14.982
20230518_05_USGS32_vs_USGS34 | 4 | 2 | sample | changeover | NA | 2470 | 2795 | 15.016 | 16.990
20230518_05_USGS32_vs_USGS34 | 5 | 2 | sample | data | NA | 2800 | 4110 | 17.021 | 24.982
20230518_05_USGS32_vs_USGS34 | 6 | 3 | reference | changeover | NA | 4115 | 4440 | 25.016 | 26.991
20230518_05_USGS32_vs_USGS34 | 7 | 3 | reference | data | NA | 4445 | 5755 | 27.022 | 34.984
20230518_05_USGS32_vs_USGS34 | 8 | 4 | sample | changeover | NA | 5760 | 6085 | 35.017 | 36.992
20230518_05_USGS32_vs_USGS34 | 9 | 4 | sample | unused | NA | 6090 | 6250 | 37.023 | 37.995
20230518_05_USGS32_vs_USGS34 | 10 | 4 | sample | data | NA | 6255 | 7235 | 38.025 | 43.982
20230518_05_USGS32_vs_USGS34 | 11 | 4 | sample | unused | NA | 7240 | 7400 | 44.012 | 44.984
20230518_05_USGS32_vs_USGS34 | 12 | 5 | reference | changeover | NA | 7405 | 7730 | 45.018 | 46.994
20230518_05_USGS32_vs_USGS34 | 13 | 5 | reference | data | NA | 7735 | 9045 | 47.024 | 54.985
20230518_05_USGS32_vs_USGS34 | 14 | 6 | sample | changeover | NA | 9050 | 9375 | 55.019 | 56.994
20230518_05_USGS32_vs_USGS34 | 15 | 6 | sample | data | NA | 9380 | 10690 | 57.024 | 64.985
20230518_05_USGS32_vs_USGS34 | 16 | 7 | reference | changeover | NA | 10695 | 11020 | 65.019 | 66.994
20230518_05_USGS32_vs_USGS34 | 17 | 7 | reference | data | NA | 11025 | 12335 | 67.025 | 74.985

# Raw data plots

## Plot 1: default block highlights + outliers

    # ions
    df_w_blocks |>
      orbi_plot_raw_data(
        isotopocules = "15N",
        y = ions.incremental
      )

    # ratios - you can see that even the AGC outliers still create decent ratios
    df_w_blocks |>
      orbi_plot_raw_data(
        isotopocules = "15N",
        y = ratio
      )

## Plot 2: highlight blocks in data + no outliers

    df_w_blocks |>
      orbi_plot_raw_data(
        isotopocules = "15N",
        y = ratio,
        color = NULL,
        add_all_blocks = TRUE,
        show_outliers = FALSE
      ) +
      # add other ggplot elements, e.g. more specific axis labels
      labs(x = "time [min]", y = "15N/M0 ratio")

## Plot 3: highlight sample blocks on top

    df_w_blocks |>
      orbi_plot_raw_data(
        isotopocules = "15N",
        y = ratio,
        add_all_blocks = TRUE,
        show_outliers = FALSE,
        color = factor(block)
      ) +
      labs(x = "time [min]", y = "15N/M0 ratio", color = "block #")

# Data summaries

    # calculate summary
    df_summary <-
      df_w_blocks |>
      # segment (optional)
      orbi_segment_blocks(into_segments = 3) |>
      # calculate results, including for the unused parts of the data blocks
      orbi_summarize_results(
        ratio_method = "sum",
        include_unused_data = TRUE
      )

## Plot 1: ratios summary by block and segment

    # plot all isotopocules using a ggplot from scratch
    df_summary |>
      filter(data_type == "data") |>
      mutate(block_seg = sprintf("%s.%s", block, segment) |> fct_inorder()) |>
      # data
      ggplot() +
      aes(
        x = block_seg,
        y = ratio, ymin = ratio - ratio_sem, ymax = ratio + ratio_sem,
        color = sample_name
      ) +
      geom_pointrange() +
      facet_grid(isotopocule ~ ., scales = "free_y") +
      # scales
      scale_color_brewer(palette = "Set1") +
      theme_bw() +
      labs(x = "block.segment", y = "ratio")

## Plot 2: ratios with block backgrounds and raw data

    # make a plot for 15N
    plot2 <- df_w_blocks |>
      filter(isotopocule == "15N") |>
      mutate(panel = "raw ratios") |>
      # raw data plot
      orbi_plot_raw_data(
        y = ratio,
        color = NULL,
        add_all_blocks = TRUE,
        show_outliers = FALSE
      ) +
       # ratio summary data
      geom_pointrange(
        data = function(df) {
          df_summary |>
            filter(as.character(isotopocule) == df$isotopocule[1]) |>
            mutate(panel = "summary")
        },
        map = aes(
          x = mean_time.min, y = ratio,
          ymin = ratio - ratio_sem, ymax = ratio + ratio_sem,
          shape = sample_name
        ),
        size = 0.5
      ) +
      facet_grid(panel ~ ., switch = "y") +
      theme(strip.placement = "outside") +
      labs(y = NULL, title = "15N/M0")

    plot2

    # same but with 18O
    plot2 %+%
      (df_w_blocks |> filter(isotopocule == "18O") |> mutate(panel = "raw ratios")) +
      labs(title = "18O/M0")