OmicsLake 総合ガイド

はじめに

OmicsLakeは、バイオインフォマティクスデータ解析のための 包括的なバージョン管理・依存関係追跡システムを提供する Rパッケージです。 このビネットでは、全ての主要機能を実例とともに紹介します。

全コードを実行する前に

このビネットは、パッケージチェック時の安定性のため既定で非評価設定です。 ローカルで全チャンクを実行するには、以下を先に設定してください。

options(omicslake.vignette.eval = TRUE)

RNA-seqの代表フロー(count -> edgeR -> limma-voom -> ORA)を即時に試す場合は、以下のスクリプトを使えます。

bash tools/run_demo_count_edger_limma_voom_ora.sh

レイヤー別の代表ユースケース(SE/SCE/MAE/Spectra/QFeatures/MsExperiment) は次のビネットに整理しています。

  • vignettes/omicslake_layer_use_cases.Rmd

パッケージの主な機能

  • プロジェクト管理: DuckDBベースのプロジェクト初期化と管理
  • データ保存: テーブルとRオブジェクトの保存
  • バージョン管理: タグ付け、履歴管理、バージョン比較
  • 依存関係追跡: データ解析フローの依存関係を自動追跡
  • 可視化: 依存関係グラフの視覚化
  • Bioconductor統合: SE/SCE/MAE/Spectra/QFeatures/MsExperimentのサポート

1. 基本操作

1.1 プロジェクトの初期化

library(OmicsLake)

# プロジェクトを初期化
ol_init("de_analysis")

ol_init() は指定した名前でプロジェクトを作成し、DuckDBデータベースを初期化します。

1.2 テーブルの書き込みと読み込み

# サンプルデータの作成
set.seed(123)
raw_counts <- data.frame(
    gene_id = paste0("GENE", 1:100),
    sample1 = rpois(100, 100),
    sample2 = rpois(100, 100),
    sample3 = rpois(100, 120),
    sample4 = rpois(100, 120)
)

# テーブルとして保存
ol_write("raw_counts", raw_counts, mode = "create")

# テーブルの読み込み
counts <- ol_read("raw_counts")
head(counts)

# テーブル一覧の確認
ol_list_tables()

出力の見方: ol_list_tables() は現在のプロジェクトに保存されているすべてのテーブル名を返します。

1.3 SQLクエリによる高度な分析 (ol_query)

ol_query() を使用すると、DuckDBの全機能 (JOIN、集計、ウィンドウ関数など)を活用した 高度なデータ分析が可能です。

# 基本的なクエリ
result <- ol_query("SELECT * FROM raw_counts WHERE sample1 > 100")
head(result)

# 集計クエリ
summary <- ol_query("
    SELECT
    COUNT(*) as total_genes,
    AVG(sample1) as avg_sample1,
    MAX(sample1) as max_sample1
    FROM raw_counts
")
print(summary)

JOINとサブクエリ

# テーブルのJOIN(例:遺伝子情報との結合)
ol_write("gene_annotations", data.frame(
    gene_id = paste0("gene", 1:5),
    name = paste0("GeneA", 1:5),
    chromosome = c("chr1", "chr2", "chr1", "chr3", "chr2")
))

joined <- ol_query("
    SELECT r.gene_id, r.sample1, a.name, a.chromosome
    FROM raw_counts r
    JOIN gene_annotations a ON r.gene_id = a.gene_id
    WHERE r.sample1 > 50
")
head(joined)

遅延評価とdplyrとの統合

# collect=FALSE で遅延評価
if (requireNamespace("dplyr", quietly = TRUE)) {
    lazy_tbl <- ol_query("SELECT * FROM raw_counts", collect = FALSE)

    # dplyrパイプラインで処理
    result <- lazy_tbl %>%
        dplyr::filter(sample1 > 100) %>%
        dplyr::select(gene_id, sample1, sample2) %>%
        dplyr::arrange(dplyr::desc(sample1)) %>%
        dplyr::collect()

    head(result)
}

注意: テーブル名は ol. プレフィックスなしで参照できます(例: genes でOK、ol.genes も使用可能)。 ## 1.4 集計・ウィンドウ関数による高度な分析

フェーズ2の関数を使用すると、 一般的な集計やウィンドウ関数の操作がより簡単になります。 これらの関数は、DuckDBの高度な分析機能を活用して、 遺伝子発現データの統計処理を効率化します。

遺伝子発現統計の計算

# サンプル全体の統計
overall_stats <- ol_aggregate("raw_counts",
    mean_sample1 = list(func = "avg", col = "sample1"),
    median_sample1 = list(func = "median", col = "sample1"),
    sd_sample1 = list(func = "stddev", col = "sample1")
)
print(overall_stats)

# グループごとの統計(例:サンプル1が高発現 vs 低発現)
# まず高発現/低発現のカテゴリを追加
ol_query("
    CREATE OR REPLACE TABLE raw_counts_categorized AS
    SELECT *,
    CASE WHEN sample1 > 100 THEN 'high' ELSE 'low' END as expr_category
    FROM raw_counts
")

grouped_stats <- ol_aggregate("raw_counts_categorized",
    group_by = "expr_category",
    count = list(func = "count", col = "*"),
    mean_s1 = list(func = "avg", col = "sample1"),
    mean_s2 = list(func = "avg", col = "sample2")
)
print(grouped_stats)

遺伝子のランキング

# 発現量で遺伝子をランク付け
ranked_genes <- ol_add_rank("raw_counts",
    rank_by = "sample1",
    method = "row_number",
    descending = TRUE,
    as_column = "expression_rank"
)
head(ranked_genes)

# トップ10遺伝子を取得
top_genes <- ol_top_n("raw_counts",
    n = 10,
    order_by = "sample1",
    descending = TRUE
)
print(top_genes)

# サンプルごとのトップ5遺伝子
# まずデータを縦型に変換
ol_query("
    CREATE OR REPLACE TABLE raw_counts_long AS
    SELECT gene_id, 'sample1' as sample, sample1 as expression FROM raw_counts
    UNION ALL
    SELECT gene_id, 'sample2' as sample, sample2 as expression FROM raw_counts
    UNION ALL
    SELECT gene_id, 'sample3' as sample, sample3 as expression FROM raw_counts
    UNION ALL
    SELECT gene_id, 'sample4' as sample, sample4 as expression FROM raw_counts
")

top_per_sample <- ol_top_n("raw_counts_long",
    n = 5,
    order_by = "expression",
    partition_by = "sample",
    descending = TRUE
)
print(top_per_sample)

移動平均と累積和

# 移動平均(スムージング)
# 遺伝子IDでソートして3遺伝子の移動平均を計算
smoothed <- ol_moving_avg("raw_counts",
    column = "sample1",
    window_size = 3,
    order_by = "gene_id",
    as_column = "sample1_smoothed"
)
head(smoothed, 10)

# より大きなウィンドウサイズ
smoothed_5 <- ol_moving_avg("raw_counts",
    column = "sample1",
    window_size = 5,
    order_by = "gene_id",
    as_column = "sample1_ma5"
)
head(smoothed_5, 10)

# 累積和(遺伝子IDでソートして累積カウント)
cumulative <- ol_cumulative_sum("raw_counts",
    column = "sample1",
    order_by = "gene_id",
    as_column = "sample1_cumsum"
)
head(cumulative, 10)
tail(cumulative)

# サンプルごとの累積和(縦型データを使用)
cumulative_per_sample <- ol_cumulative_sum("raw_counts_long",
    column = "expression",
    partition_by = "sample",
    order_by = "gene_id",
    as_column = "cumulative_expr"
)
head(cumulative_per_sample, 20)

遅延評価との組み合わせ

# 集計関数も遅延評価をサポート
if (requireNamespace("dplyr", quietly = TRUE)) {
    # 遅延評価で統計を計算
    lazy_stats <- ol_aggregate("raw_counts",
        mean_s1 = list(func = "avg", col = "sample1"),
        collect = FALSE
    )

    # さらにdplyrで処理
    result <- lazy_stats %>%
        dplyr::collect()
    print(result)

    # ランキングと組み合わせ
    lazy_ranked <- ol_add_rank("raw_counts",
        rank_by = "sample1",
        as_column = "rank",
        collect = FALSE
    )

    top_ranked <- lazy_ranked %>%
        dplyr::filter(rank <= 10) %>%
        dplyr::select(gene_id, sample1, rank) %>%
        dplyr::arrange(rank) %>%
        dplyr::collect()
    print(top_ranked)
}

これらの関数を使用することで、 複雑なSQLを書かずに一般的な分析パターンを簡単に実行できます。

1.5 Rオブジェクトの保存と読み込み

# 正規化係数を計算(例)
norm_factors <- list(
    method = "TMM",
    factors = runif(100, 0.8, 1.2)
)

# Rオブジェクトとして保存
ol_save("norm_factors", norm_factors)

# オブジェクトの読み込み
loaded_factors <- ol_read_object("norm_factors")
str(loaded_factors)

# オブジェクト一覧の確認
ol_list_objects()

出力の見方: ol_list_objects() は保存されているすべてのRオブジェクト名を返します。

2. 依存関係の追跡

2.1 依存関係を指定してデータを保存

# 正規化されたカウントを計算(depends_on で依存関係を指定)
normalized_counts <- raw_counts
for (i in 2:5) {
    normalized_counts[[i]] <- normalized_counts[[i]] * norm_factors$factors
}

# 依存関係を指定して保存
ol_write("normalized_counts", normalized_counts,
    depends_on = c("raw_counts", "norm_factors")
)

# DEパラメータを保存
de_params <- list(
    method = "DESeq2",
    alpha = 0.05,
    lfc_threshold = 1.0
)
ol_save("de_params", de_params)

# DE結果を計算(簡略化した例)
de_results <- data.frame(
    gene_id = paste0("GENE", 1:20),
    log2FC = rnorm(20, 0, 2),
    pvalue = runif(20, 0, 0.1),
    padj = runif(20, 0, 0.1)
)

# DE結果を依存関係付きで保存
ol_save("de_results", de_results,
    depends_on = c("normalized_counts", "de_params")
)

2.2 依存関係の確認

# 上流の依存関係(このオブジェクトが依存しているもの)
upstream <- ol_get_dependencies("de_results", direction = "upstream")
print(upstream)

# 下流の依存関係(このオブジェクトに依存しているもの)
downstream <- ol_get_dependencies("raw_counts", direction = "downstream")
print(downstream)

# 完全な系統樹を表示
lineage <- ol_show_lineage("de_results", direction = "upstream")
print(lineage)

出力の見方:

  • ol_get_dependencies(): 直接の依存関係をdata.frameで返します
  • ol_show_lineage(): 再帰的に全ての祖先/子孫を探索し、完全な系統樹を返します

2.3 Parquet ファイルのインポート・エクスポート

OmicsLakeは、DuckDBの高性能Parquetサポートを活用して、 テーブルを効率的にParquetファイルにエクスポートしたり、 Parquetファイルからインポートしたりできます。

Parquetエクスポート

# 基本的なエクスポート(デフォルトはSnappy圧縮)
ol_export_parquet("genes", "genes.parquet")

# zstd圧縮でエクスポート(高圧縮率)
ol_export_parquet("genes", "genes_zstd.parquet",
    compression = "zstd",
    compression_level = 3
)

# 行グループサイズを指定してエクスポート
ol_export_parquet("genes", "genes_optimized.parquet",
    compression = "zstd",
    row_group_size = 50000
)

# 圧縮なしでエクスポート(最速)
ol_export_parquet("genes", "genes_uncompressed.parquet",
    compression = "uncompressed"
)

Parquetインポート

# Parquetファイルからテーブルを作成
ol_import_parquet("genes.parquet", "imported_genes", mode = "create")

# 既存のテーブルを上書き
ol_import_parquet("genes_new.parquet", "genes", mode = "overwrite")

# 既存のテーブルにデータを追加
ol_import_parquet("genes_batch2.parquet", "genes", mode = "append")

# 複数のParquetファイルを一度にインポート
ol_import_parquet(c("genes_part1.parquet", "genes_part2.parquet"),
    "all_genes",
    mode = "create"
)

# 依存関係を記録してインポート
ol_import_parquet("processed_genes.parquet",
    "final_genes",
    depends_on = "raw_genes",
    mode = "create"
)

パフォーマンスのヒント

圧縮アルゴリズムの選択: - snappy: バランスが良く、デフォルト推奨 - zstd: 最高の圧縮率、読み書き速度も良好 - lz4: 最速の圧縮・解凍 - brotli: 最高の圧縮率だが遅い - uncompressed: 圧縮なし、最速だがファイルサイズ大

行グループサイズ: - 小さい値(10,000-50,000): メモリ効率が良い、フィルタリングに有利 - 大きい値(100,000-500,000): 圧縮率が高い、スキャン性能に有利 - デフォルト(100,000): バランスが良い

# 大規模データセットの最適化例
ol_export_parquet("large_dataset",
    "large_dataset.parquet",
    compression = "zstd",
    compression_level = 1, # 最速のzstd
    row_group_size = 250000
)

3. バージョン管理

3.1 タグ付けとラベル付け

# オブジェクトにタグを付ける
ol_tag_object("de_results", "baseline_analysis")

# プロジェクト全体にラベルを付ける(全テーブル・オブジェクトにタグが付く)
ol_label("experiment_v1")

# タグ一覧の確認
ol_list_tags()

# プロジェクトラベル一覧
ol_list_labels()

3.2 複数バージョンの作成

# パラメータを変更して再解析
de_params_v2 <- list(
    method = "DESeq2",
    alpha = 0.01,
    lfc_threshold = 1.5
)
ol_save("de_params", de_params_v2)

# 新しいパラメータでDE結果を再計算
de_results_v2 <- data.frame(
    gene_id = paste0("GENE", 1:10),
    log2FC = rnorm(10, 0, 2.5),
    pvalue = runif(10, 0, 0.01),
    padj = runif(10, 0, 0.01)
)
ol_save("de_results", de_results_v2,
    depends_on = c("normalized_counts", "de_params")
)

# 新バージョンにタグ付け
ol_tag_object("de_results", "strict_analysis")

# 別の解析手法を試す
de_params_edger <- list(
    method = "edgeR",
    alpha = 0.05,
    lfc_threshold = 1.0
)
ol_save("de_params", de_params_edger)

de_results_edger <- data.frame(
    gene_id = paste0("GENE", c(1:12, 25:30)),
    log2FC = rnorm(18, 0, 2),
    pvalue = runif(18, 0, 0.1),
    padj = runif(18, 0, 0.1)
)
ol_save("de_results", de_results_edger,
    depends_on = c("normalized_counts", "de_params")
)
ol_tag_object("de_results", "edger_analysis")

3.3 バージョン一覧と比較

# 全バージョンをリスト表示
versions <- ol_list_object_versions("de_results")
print(versions)

# バージョン間の比較
comparison <- ol_compare_versions("de_results")
print(comparison)

# 特定のタグ間の比較
tag_comparison <- ol_compare_versions("de_results",
    versions = c("baseline_analysis", "strict_analysis")
)
print(tag_comparison)

出力の見方:

  • version_ts: バージョンのタイムスタンプ
  • tags: そのバージョンに付けられたタグ
  • size_bytes: オブジェクトのサイズ(バイト)
  • dependencies: そのバージョンの依存関係
  • size_change: 前のバージョンからのサイズ変化
  • time_since_previous: 前のバージョンからの経過時間
  • deps_added: 新しく追加された依存関係
  • deps_removed: 削除された依存関係

3.4 特定バージョンの読み込み

# タグを指定して読み込み
baseline_results <- ol_read_object(
    "de_results",
    ref = "@tag(baseline_analysis)"
)
strict_results <- ol_read_object("de_results", ref = "@tag(strict_analysis)")

cat("Baseline analysis:", nrow(baseline_results), "genes\n")
cat("Strict analysis:", nrow(strict_results), "genes\n")

4. コミットと履歴管理

4.1 コミットの作成

# 解析の節目でコミットを作成
commit_id <- ol_commit(
    note = "Completed initial DE analysis with three methods",
    params = list(
        methods = c("DESeq2_baseline", "DESeq2_strict", "edgeR"),
        date = as.character(Sys.Date())
    )
)

cat("Commit ID:", commit_id, "\n")

4.2 履歴の確認

# コミット履歴を表示
commits <- ol_log_commits(n = 10)
print(commits)

# 特定のテーブルの履歴
table_log <- ol_log("raw_counts")
print(table_log)

5. 依存関係の可視化

5.1 依存関係グラフの作成

# igraphパッケージが必要
if (requireNamespace("igraph", quietly = TRUE)) {
    # 上流の依存関係を可視化
    ol_plot_lineage("de_results",
        direction = "upstream",
        layout = "sugiyama",
        main = "DE Results - Upstream Dependencies"
    )

    # 双方向の依存関係を可視化
    ol_plot_lineage("normalized_counts",
        direction = "both",
        layout = "tree",
        main = "Normalized Counts - Full Lineage"
    )
}

可視化の見方:

  • 青色のノード: テーブル
  • オレンジ色のノード: Rオブジェクト
  • 赤色のノード: 指定したフォーカルノード
  • 矢印: 依存関係の方向(親→子)

6. プロジェクトの復元

6.1 ラベルを使った状態の復元

# 新しいテーブルを追加
filtered_results <- de_results[de_results$padj < 0.05, ]
ol_write("filtered_de", filtered_results)

# 以前のラベル状態に戻る
ol_checkout("experiment_v1")

# filtered_deテーブルは存在しなくなる
current_tables <- ol_list_tables()
cat(
    "Tables after checkout:",
    paste(current_tables$table_name, collapse = ", "),
    "\n"
)

ol_checkout() は指定したラベル時点の全テーブルとオブジェクトの状態を復元します。

7. 高度な機能

7.1 データのフィルタリング読み込み

# 再度raw_countsを作成(checkoutで消えた可能性があるため)
ol_write("raw_counts", raw_counts, mode = "overwrite")

# 特定の列のみを選択して読み込み
selected <- ol_fread("raw_counts",
    select = c("gene_id", "sample1", "sample2"),
    nrows = 10
)
head(selected)

# 条件でフィルタリング
filtered <- ol_fread("raw_counts",
    filter = "sample1 > 100"
)
head(filtered)

7.2 遅延評価での読み込み

if (requireNamespace("dplyr", quietly = TRUE)) {
    # collect = FALSE で遅延評価
    lazy_tbl <- ol_read("raw_counts", collect = FALSE)

    # dplyrで処理
    result <- lazy_tbl %>%
        dplyr::filter(sample1 > 100) %>%
        dplyr::select(gene_id, sample1) %>%
        dplyr::collect()

    head(result)
}

7.3 テーブルの削除

# 不要なテーブルを削除
ol_drop("filtered_de")

8. Bioconductor統合

8.1 SummarizedExperimentの作成

if (requireNamespace("SummarizedExperiment", quietly = TRUE)) {
    # ロングフォーマットのデータを作成
    long_counts <- data.frame(
        feature = rep(paste0("GENE", 1:100), each = 4),
        sample = rep(paste0("sample", 1:4), times = 100),
        value = rpois(400, 100)
    )
    ol_write("long_counts", long_counts, mode = "overwrite")

    # SummarizedExperimentとして読み込み
    se <- ol_read_se("long_counts",
        feature_col = "feature",
        sample_col = "sample",
        value_col = "value",
        backing = "memory"
    )

    print(se)
}

8.2 MultiAssayExperimentの作成

if (requireNamespace("MultiAssayExperiment", quietly = TRUE)) {
    # 複数のアッセイデータを準備
    rna_data <- data.frame(
        feature = rep(paste0("GENE", 1:50), each = 4),
        sample = rep(paste0("sample", 1:4), times = 50),
        value = rpois(200, 100)
    )
    ol_write("rna_assay", rna_data, mode = "overwrite")

    protein_data <- data.frame(
        feature = rep(paste0("PROT", 1:30), each = 4),
        sample = rep(paste0("sample", 1:4), times = 30),
        value = rnorm(120, 50, 10)
    )
    ol_write("protein_assay", protein_data, mode = "overwrite")

    # MultiAssayExperimentとして読み込み
    mae <- ol_read_mae(
        assays = list(
            rna = list(name = "rna_assay"),
            protein = list(name = "protein_assay")
        ),
        backing = "memory"
    )

    print(mae)
}

9. 実践的なワークフロー例

9.1 完全な差次発現解析ワークフロー

# 1. プロジェクト初期化
ol_init("rnaseq_project")

# 2. 生データの保存
set.seed(456)
raw_data <- data.frame(
    gene_id = paste0("GENE", 1:200),
    control_1 = rpois(200, 100),
    control_2 = rpois(200, 100),
    control_3 = rpois(200, 100),
    treated_1 = rpois(200, 120),
    treated_2 = rpois(200, 120),
    treated_3 = rpois(200, 120)
)
ol_write("raw_expression", raw_data)

# 3. QCパラメータの保存
qc_params <- list(
    min_counts = 10,
    min_samples = 3,
    method = "standard"
)
ol_save("qc_parameters", qc_params)

# 4. QC後のデータ
qc_data <- raw_data[rowSums(raw_data[, -1] > 10) >= 3, ]
ol_write(
    "qc_filtered",
    qc_data,
    depends_on = c("raw_expression", "qc_parameters")
)

# 5. 正規化パラメータ
norm_params <- list(
    method = "TMM",
    log_transform = TRUE
)
ol_save("norm_parameters", norm_params)

# 6. 正規化データ
norm_data <- qc_data
for (i in 2:ncol(norm_data)) {
    norm_data[[i]] <- log2(norm_data[[i]] + 1)
}
ol_write("normalized", norm_data,
    depends_on = c("qc_filtered", "norm_parameters")
)

# 7. 統計解析パラメータ
stats_params <- list(
    test = "t-test",
    alpha = 0.05,
    correction = "BH"
)
ol_save("stats_parameters", stats_params)

# 8. 統計解析結果
set.seed(789)
de_final <- data.frame(
    gene_id = sample(qc_data$gene_id, 30),
    log2fc = rnorm(30, 1, 0.5),
    pvalue = runif(30, 0, 0.05),
    padj = runif(30, 0, 0.05)
)
ol_save("final_de_results", de_final,
    depends_on = c("normalized", "stats_parameters")
)

# 9. 解析をコミット
ol_commit(
    note = "Complete RNA-seq differential expression analysis",
    params = list(
        samples = 6,
        genes_tested = nrow(qc_data),
        significant = nrow(de_final),
        date = as.character(Sys.Date())
    )
)

# 10. ラベルを作成
ol_label("final_analysis_v1")

# 11. 完全な系統を確認
full_lineage <- ol_show_lineage("final_de_results", direction = "upstream")
print(full_lineage)

# 12. 依存関係を可視化
if (requireNamespace("igraph", quietly = TRUE)) {
    ol_plot_lineage("final_de_results",
        direction = "upstream",
        layout = "sugiyama",
        main = "RNA-seq Analysis Pipeline"
    )
}

10. まとめ

主要な関数一覧

プロジェクト管理

  • ol_init(): プロジェクト初期化
  • ol_label(): プロジェクト全体のラベル付け
  • ol_checkout(): ラベル状態への復元

データ保存・読み込み

  • ol_write(): テーブルの保存
  • ol_read(): テーブルの読み込み
  • ol_save(): Rオブジェクトの保存
  • ol_read_object(): Rオブジェクトの読み込み
  • ol_load(): ol_read()のエイリアス
  • ol_fread(): フィルタリング付き読み込み

バージョン管理

  • ol_tag(): テーブルのタグ付け
  • ol_tag_object(): オブジェクトのタグ付け
  • ol_list_object_versions(): バージョン一覧
  • ol_compare_versions(): バージョン比較

履歴管理

  • ol_commit(): コミットの作成
  • ol_log(): テーブル履歴の表示
  • ol_log_commits(): コミット履歴の表示

依存関係

  • ol_get_dependencies(): 依存関係の取得
  • ol_show_lineage(): 完全な系統樹の表示
  • ol_plot_lineage(): 依存関係グラフの可視化

一覧表示

  • ol_list_tables(): テーブル一覧
  • ol_list_objects(): オブジェクト一覧
  • ol_list_tags(): タグ一覧
  • ol_list_labels(): ラベル一覧

Bioconductor

  • ol_read_se(): SummarizedExperiment作成
  • ol_read_mae(): MultiAssayExperiment作成

その他

  • ol_drop(): テーブル削除

ベストプラクティス

  1. 依存関係を明示的に指定: depends_on パラメータを使って解析フローを記録
  2. 重要な節目でラベル作成: 再現可能性のため、重要な時点で ol_label()
  3. を実行
  4. タグを活用: 異なる解析方法やパラメータには明確なタグを付ける
  5. コミットメッセージを詳細に: 解析の内容と結果を ol_commit() に記録
  6. 可視化で確認: 複雑な解析フローは ol_plot_lineage() で視覚化
  7. バージョン比較を活用: ol_compare_versions()
  8. でパラメータ変更の影響を追跡

Session Information

sessionInfo()