### Install and Initialize scran.js Source: https://github.com/kanaverse/scran.js/blob/master/README.md Installs the scran.js npm package and initializes the library with a specified number of threads. Initialization must be completed before performing any analysis steps. For older Node.js versions, the 'localFile: true' option might be necessary. ```javascript npm install scran.js ``` ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); // for old Node versions, set localFile: true ``` -------------------------------- ### Install Development Dependencies and Run Tests Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/developer_notes.md Installs development dependencies for Scran.js and executes the test suite. For RDS reading function tests, ensure R is installed and run the generate.R script. ```shell npm install --include=dev npm run test ``` ```shell CHECK_RDS=1 npm run test -- tests/rds ``` -------------------------------- ### CMake Project Setup for scran.js Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Initializes the CMake project for scran.js, setting the minimum version, project name, version, description, and language. It also configures the C++ standard to C++17. ```cmake cmake_minimum_required(VERSION 3.14) project(scran_wasm VERSION 1.0.0 DESCRIPTION "Methods for single-cell RNA-seq data analysis" LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) ``` -------------------------------- ### Build Scran.js for Node.js and Browser Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/developer_notes.md This script builds Scran.js for either Node.js or browser environments. It generates Wasm files and associated Javascript bindings in separate directories. Ensure Emscripten, CMake, and Node.js (v24.0.0+) are installed. ```shell # For Node.js: ./build.sh main # For the browser: ./build.sh browser ``` -------------------------------- ### Initialize scran.js WebAssembly Module Source: https://context7.com/kanaverse/scran.js/llms.txt Initializes the scran.js WebAssembly module, enabling multi-threading for analysis. It allows setting the number of threads and provides functions to check available threads and current heap size. Remember to terminate workers when analysis is complete. ```javascript import * as scran from "scran.js"; // Initialize with 4 threads (default) await scran.initialize({ numberOfThreads: 4 }); // Check available threads const threads = scran.maximumThreads(); console.log(`Available threads: ${threads}`); // Get current heap size const heap = scran.heapSize(); console.log(`Wasm heap size: ${heap} bytes`); // Terminate workers when done scran.terminate(); ``` -------------------------------- ### Fetch External Dependencies with CMake Source: https://github.com/kanaverse/scran.js/blob/master/extern/CMakeLists.txt This snippet demonstrates how CMake's FetchContent module is used to declare and download external libraries from Git repositories. It specifies the repository URL and the exact tag to ensure reproducible builds. Dependencies include various bioinformatics and data manipulation libraries. ```cmake cmake_minimum_required(VERSION 3.14 FATAL_ERROR) include(FetchContent) FetchContent_Declare( aarand GIT_REPOSITORY https://github.com/LTLA/aarand GIT_TAG v1.1.0 ) FetchContent_Declare( subpar GIT_REPOSITORY https://github.com/LTLA/subpar GIT_TAG v0.4.1 ) FetchContent_Declare( sanisizer GIT_REPOSITORY https://github.com/LTLA/sanisizer GIT_TAG v0.1.4 ) FetchContent_Declare( tatami GIT_REPOSITORY https://github.com/tatami-inc/tatami GIT_TAG v4.0.3 ) FetchContent_Declare( tatami_stats GIT_REPOSITORY https://github.com/tatami-inc/tatami_stats GIT_TAG v2.0.1 ) FetchContent_Declare( tatami_mult GIT_REPOSITORY https://github.com/tatami-inc/tatami_mult GIT_TAG v0.1.3 ) FetchContent_Declare( tatami_chunked GIT_REPOSITORY https://github.com/tatami-inc/tatami_chunked GIT_TAG v2.1.0 ) FetchContent_Declare( eminem GIT_REPOSITORY https://github.com/tatami-inc/eminem GIT_TAG v1.2.0 ) FetchContent_Declare( tatami_mtx GIT_REPOSITORY https://github.com/tatami-inc/tatami_mtx GIT_TAG v2.1.0 ) FetchContent_Declare( tatami_hdf5 GIT_REPOSITORY https://github.com/tatami-inc/tatami_hdf5 GIT_TAG v2.0.5 ) FetchContent_Declare( tatami_layered GIT_REPOSITORY https://github.com/tatami-inc/tatami_layered GIT_TAG v2.1.0 ) FetchContent_Declare( eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen GIT_TAG 5.0.0 ) FetchContent_Declare( irlba GIT_REPOSITORY https://github.com/LTLA/CppIrlba GIT_TAG v3.0.0 ) FetchContent_Declare( kmeans GIT_REPOSITORY https://github.com/LTLA/CppKmeans GIT_TAG v4.0.4 ) FetchContent_Declare( annoy GIT_REPOSITORY https://github.com/spotify/annoy GIT_TAG v1.17.2 ) FetchContent_Declare( knncolle GIT_REPOSITORY https://github.com/knncolle/knncolle GIT_TAG v3.0.0 ) FetchContent_Declare( knncolle_annoy GIT_REPOSITORY https://github.com/knncolle/knncolle_annoy GIT_TAG v0.2.0 ) FetchContent_Declare( scran_qc GIT_REPOSITORY https://github.com/libscran/scran_qc GIT_TAG v0.2.0 ) FetchContent_Declare( scran_norm GIT_REPOSITORY https://github.com/libscran/scran_norm GIT_TAG v0.2.0 ) FetchContent_Declare( scran_blocks GIT_REPOSITORY https://github.com/libscran/scran_blocks GIT_TAG v0.1.1 ) FetchContent_Declare( WeightedLowess GIT_REPOSITORY https://github.com/LTLA/CppWeightedLowess GIT_TAG v2.1.4 ) FetchContent_Declare( topicks GIT_REPOSITORY https://github.com/libscran/topicks GIT_TAG v0.2.2 ) FetchContent_Declare( scran_variances GIT_REPOSITORY https://github.com/libscran/scran_variances GIT_TAG v0.2.1 ) FetchContent_Declare( scran_pca GIT_REPOSITORY https://github.com/libscran/scran_pca GIT_TAG v0.3.0 ) FetchContent_Declare( mumosa GIT_REPOSITORY https://github.com/libscran/mumosa GIT_TAG v0.2.1 ) FetchContent_Declare( raiigraph GIT_REPOSITORY https://github.com/LTLA/raiigraph GIT_TAG v1.2.0 ) FetchContent_Declare( scran_graph_cluster GIT_REPOSITORY https://github.com/libscran/scran_graph_cluster GIT_TAG v0.3.0 ) FetchContent_Declare( scran_markers GIT_REPOSITORY https://github.com/libscran/scran_markers GIT_TAG v0.3.0 ) FetchContent_Declare( scran_aggregate GIT_REPOSITORY https://github.com/libscran/scran_aggregate GIT_TAG v0.2.0 ) FetchContent_Declare( phyper GIT_REPOSITORY https://github.com/libscran/phyper GIT_TAG v0.1.1 ) FetchContent_Declare( gsdecon GIT_REPOSITORY https://github.com/libscran/gsdecon GIT_TAG v0.2.0 ) FetchContent_Declare( qdtsne GIT_REPOSITORY https://github.com/libscran/qdtsne GIT_TAG v3.0.1 ) FetchContent_Declare( umappp GIT_REPOSITORY https://github.com/libscran/umappp GIT_TAG v3.2.0 ) FetchContent_Declare( mnncorrect GIT_REPOSITORY https://github.com/libscran/mnncorrect GIT_TAG v3.0.1 ) FetchContent_Declare( byteme GIT_REPOSITORY https://github.com/LTLA/byteme GIT_TAG v2.0.1 ) FetchContent_Declare( singlepp_loaders GIT_REPOSITORY https://github.com/SingleR-inc/singlepp_loaders GIT_TAG v0.2.0 ) FetchContent_Declare( singlepp GIT_REPOSITORY https://github.com/SingleR-inc/singlepp GIT_TAG v3.0.1 ) FetchContent_Declare( rds2cpp GIT_REPOSITORY https://github.com/LTLA/rds2cpp GIT_TAG v1.2.0 ) # Forcing the Eigen build to create the installation files, ``` -------------------------------- ### Advanced K-Means Clustering Initialization (Scran.js) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/kmeans_clustering.md Performs k-means clustering with custom initialization methods and seeds. This allows for more control over the clustering process, using options like 'kmeans++' for initialization and specifying a seed for reproducibility. ```javascript let clustpp = scran.clusterKmeans(pcs, 20, { initMethod: "kmeans++", initSeed: 42 }); ``` -------------------------------- ### Create Include Directory and Download Header Source: https://github.com/kanaverse/scran.js/blob/master/extern/CMakeLists.txt Ensures the 'include' directory exists in the current source directory and downloads the 'clrm1.hpp' header file from a GitHub repository if it doesn't already exist. This is crucial for including necessary C++ headers during compilation. ```cmake if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include) endif() if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include/clrm1.hpp) file(DOWNLOAD https://raw.githubusercontent.com/libscran/clrm1/refs/tags/v0.2.0/package/src/clrm1.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/clrm1.hpp) endif() ``` -------------------------------- ### Perform K-Means Clustering (Scran.js) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/kmeans_clustering.md Performs k-means clustering on a Principal Component Analysis (PCA) matrix. It requires the PCA results and the desired number of clusters. The default initialization method is PCA partitioning. ```javascript let clustering = scran.clusterKmeans(pcs, 20); ``` -------------------------------- ### Perform Basic scRNA-seq Analysis with Scran.js Source: https://github.com/kanaverse/scran.js/blob/master/README.md This Node.js code snippet demonstrates a complete basic analysis workflow for single-cell RNA sequencing data using the scran.js library. It covers initializing the library, loading a count matrix, performing quality control, normalizing counts, identifying highly variable genes, running PCA, building a neighbor graph, clustering cells, and detecting marker genes. Dependencies include the scran.js library. Inputs are a Matrix Market file and parameters for analysis. Outputs include various analysis results like clustering and markers. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); // Reading in the count matrix. let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); // Performing QC. let qc_metrics = scran.perCellRnaQcMetrics(mat, [ /* specify mito subset here */ ]); let qc_thresholds = scran.suggestRnaQcFilters(qc_metrics); let filtered = scran.filterCells(mat, qc_thresholds.filter(qc_metrics)); // Log-normalizing. let normalized = scran.normalizeCounts(filtered); // Modelling per-gene variance and selecting top HVGs. let varmodel = scran.modelGeneVariances(normalized); let hvgs = scran.chooseHvgs(varmodel, { number: 4000 }); // Performing the PCA. let pcs = scran.runPca(normalized, { features: hvgs }); // Building the neighbor search index on the PCs. let index = scran.buildNeighborSearchIndex(pcs); // Performing the clustering. let cluster_graph = scran.buildSnnGraph(index, { neighbors: 10 }); let clustering = scran.clusterGraph(cluster_graph); // Performing the t-SNE and UMAP. let tsne_res = scran.runTsne(index); let umap_res = scran.runUmap(index); // Detecting some markers. let markers = scran.scoreMarkers(normalized, clustering.membership()); ``` -------------------------------- ### Build Neighbor Search Index and Find Neighbors with Scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Builds a neighbor search index from PCA results for efficient k-nearest neighbor queries. It then finds the nearest neighbors and serializes the results. Requires scran.js and a matrix.mtx.gz file. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let normalized = scran.normalizeCounts(mat); let varModel = scran.modelGeneVariances(normalized); let hvgs = scran.chooseHvgs(varModel, { number: 4000 }); let pcs = scran.runPca(normalized, { features: hvgs }); // Build neighbor search index from PCA results let index = scran.buildNeighborSearchIndex(pcs, { approximate: true }); console.log(`Index built for ${index.numberOfCells()} cells in ${index.numberOfDims()} dimensions`); // Find k nearest neighbors let k = 15; let neighbors = scran.findNearestNeighbors(index, k); console.log(`Found ${neighbors.numberOfNeighbors()} neighbors for each of ${neighbors.numberOfCells()} cells`); // Serialize neighbors for further use let serialized = neighbors.serialize(); console.log(`Runs: ${serialized.runs.length}, Indices: ${serialized.indices.length}`); scran.free(mat); scran.free(normalized); scran.free(varModel); scran.free(pcs); scran.free(index); scran.free(neighbors); ``` -------------------------------- ### Fetch and Make Available External Libraries Source: https://github.com/kanaverse/scran.js/blob/master/extern/CMakeLists.txt Uses CMake's FetchContent module to download and make available various external libraries required by the Scran.js project. This ensures all dependencies are present before building. ```cmake FetchContent_MakeAvailable(aarand) FetchContent_MakeAvailable(subpar) FetchContent_MakeAvailable(sanisizer) FetchContent_MakeAvailable(tatami) FetchContent_MakeAvailable(tatami_stats) FetchContent_MakeAvailable(tatami_mult) FetchContent_MakeAvailable(tatami_chunked) FetchContent_MakeAvailable(tatami_hdf5) FetchContent_MakeAvailable(eminem) FetchContent_MakeAvailable(tatami_mtx) FetchContent_MakeAvailable(tatami_layered) FetchContent_MakeAvailable(kmeans) FetchContent_MakeAvailable(knncolle) FetchContent_MakeAvailable(annoy) FetchContent_MakeAvailable(knncolle_annoy) FetchContent_MakeAvailable(scran_blocks) FetchContent_MakeAvailable(scran_qc) FetchContent_MakeAvailable(scran_norm) FetchContent_MakeAvailable(WeightedLowess) FetchContent_MakeAvailable(topicks) FetchContent_MakeAvailable(scran_variances) FetchContent_MakeAvailable(eigen) FetchContent_MakeAvailable(irlba) FetchContent_MakeAvailable(scran_pca) FetchContent_MakeAvailable(raiigraph) FetchContent_MakeAvailable(scran_graph_cluster) FetchContent_MakeAvailable(scran_markers) FetchContent_MakeAvailable(scran_aggregate) FetchContent_MakeAvailable(gsdecon) FetchContent_MakeAvailable(mumosa) FetchContent_MakeAvailable(phyper) FetchContent_MakeAvailable(umappp) FetchContent_MakeAvailable(qdtsne) FetchContent_MakeAvailable(mnncorrect) FetchContent_MakeAvailable(byteme) FetchContent_MakeAvailable(singlepp) FetchContent_MakeAvailable(singlepp_loaders) FetchContent_MakeAvailable(rds2cpp) ``` -------------------------------- ### Load Sparse Matrices from Matrix Market Format with scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Loads count matrices from Matrix Market (.mtx) files, supporting both raw and gzip-compressed data. Data can be loaded directly from a file path (Node.js) or from a buffer, making it compatible with browser environments. It also allows extracting matrix dimensions before loading and provides methods to access matrix properties. Ensure to free the memory occupied by the matrix when it's no longer needed. ```javascript import * as scran from "scran.js"; import * as fs from "fs"; await scran.initialize({ numberOfThreads: 4 }); // Load from file path (Node.js) let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); // Or load from buffer (browser-compatible) let buffer = fs.readFileSync("matrix.mtx.gz"); let mat2 = scran.initializeSparseMatrixFromMatrixMarket(buffer); // Extract dimensions before loading let dims = scran.extractMatrixMarketDimensions(buffer); console.log(`Rows: ${dims.rows}, Columns: ${dims.columns}, Non-zeros: ${dims.lines}`); // Access matrix properties console.log(`Matrix has ${mat.numberOfRows()} genes and ${mat.numberOfColumns()} cells`); // Free memory when done scran.free(mat); scran.free(mat2); ``` -------------------------------- ### Read Count Matrix from Matrix Market File Source: https://github.com/kanaverse/scran.js/blob/master/README.md Demonstrates how to read a count matrix from a gzipped Matrix Market file using Node.js. The file is read into a buffer, and then scran.js's initializeSparseMatrixFromMatrixMarket function is used to parse it into a sparse matrix format. ```javascript import * as fs from "fs"; import * as scran from "scran.js"; let buffer = fs.readFileSync("matrix.mtx.gz"); let mat = scran.initializeSparseMatrixFromMatrixMarket(buffer); ``` -------------------------------- ### K-Means Clustering with Scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Performs k-means clustering on PCA results using different initialization and refinement methods. It allows specifying the number of clusters, initialization strategy, and refinement options. Requires scran.js and a matrix.mtx.gz file. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let normalized = scran.normalizeCounts(mat); let varModel = scran.modelGeneVariances(normalized); let hvgs = scran.chooseHvgs(varModel, { number: 4000 }); let pcs = scran.runPca(normalized, { features: hvgs }); // K-means clustering let k = 10; let kmeans = scran.clusterKmeans(pcs, k, { initMethod: "var-part", // "var-part", "kmeans++", or "random" initSeed: 42, refineMethod: "hartigan-wong", // or "lloyd" refineHartiganWongIterations: 10 }); // Access results let clusters = kmeans.clusters(); let sizes = kmeans.sizes(); let centers = kmeans.centers(); console.log(`K-means: ${kmeans.numberOfClusters()} clusters, ${kmeans.iterations()} iterations`); console.log(`Cluster sizes: ${Array.from(sizes).join(", ")}`); console.log(`Status: ${kmeans.status()}`); scran.free(mat); scran.free(normalized); scran.free(varModel); scran.free(pcs); scran.free(kmeans); ``` -------------------------------- ### Generate JSDoc Documentation Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/developer_notes.md Generates JSDoc documentation for the Scran.js project. The output will be an index file located at 'docs/built/index.html'. ```shell npm run jsdoc ``` -------------------------------- ### Memory Management with scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Demonstrates proper memory management for WebAssembly objects created by scran.js using try/finally blocks to prevent memory leaks. It initializes objects, performs operations, and ensures all allocated Wasm memory is freed before termination. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); // Example with proper memory management let result; let mat; let normalized; try { mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); normalized = scran.normalizeCounts(mat); // Extract data we need (copies to JS heap) result = { numGenes: normalized.numberOfRows(), numCells: normalized.numberOfColumns() }; } finally { // Always free Wasm objects scran.free(mat); scran.free(normalized); } console.log(`Result: ${result.numGenes} genes, ${result.numCells} cells`); // Check heap usage console.log(`Heap size: ${scran.heapSize()} bytes`); // Terminate when done with all analysis scran.terminate(); ``` -------------------------------- ### Defining Executable and Source Files in CMake Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Defines the main executable target 'scran_wasm' and lists all the C++ source files that will be compiled into it. This includes files for matrix operations, initialization, quality control, normalization, and more. ```cmake add_executable( scran_wasm src/NumericMatrix.cpp src/cbind.cpp src/subset.cpp src/delayed.cpp src/matrix_stats.cpp src/initialize_from_arrays.cpp src/initialize_from_rds.cpp src/initialize_from_mtx.cpp src/initialize_from_hdf5.cpp src/transpose_matrix.cpp src/rds_utils.cpp src/hdf5_utils.cpp src/write_sparse_matrix_to_hdf5.cpp src/quality_control_rna.cpp src/quality_control_adt.cpp src/quality_control_crispr.cpp src/normalize_counts.cpp src/compute_clrm1_factors.cpp src/model_gene_variances.cpp src/run_pca.cpp src/mnn_correct.cpp src/scale_by_neighbors.cpp src/NeighborIndex.cpp src/run_tsne.cpp src/run_umap.cpp src/build_snn_graph.cpp src/cluster_graph.cpp src/cluster_kmeans.cpp src/score_markers.cpp src/run_singlepp.cpp src/score_gsdecon.cpp src/hypergeometric_test.cpp src/aggregate_across_cells.cpp src/get_error_message.cpp ) ``` -------------------------------- ### Suggest QC Filters and Filter Cells with scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Automatically determines thresholds for filtering low-quality cells based on QC metrics using the median absolute deviation (MAD) method. It then applies these filters to identify high-quality cells and returns a filtered version of the original sparse matrix. The function `suggestRnaQcFilters` provides the thresholds, and `filterCells` performs the actual filtering. It's crucial to free the memory associated with the QC metrics, filters, original matrix, and the filtered matrix after use. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let mitoSubset = new Array(mat.numberOfRows()).fill(false); for (let i = 0; i < 100; i++) mitoSubset[i] = true; // Compute QC metrics let qcMetrics = scran.perCellRnaQcMetrics(mat, [mitoSubset]); // Suggest filtering thresholds (3 MADs by default) let qcFilters = scran.suggestRnaQcFilters(qcMetrics, { numberOfMADs: 3 }); // View thresholds console.log(`Sum threshold: ${qcFilters.sum()[0]}`); console.log(`Detected threshold: ${qcFilters.detected()[0]}`); console.log(`Mito proportion threshold: ${qcFilters.subsetProportion(0)[0]}`); // Get boolean array of high-quality cells let keepCells = qcFilters.filter(qcMetrics); // Filter the matrix let filtered = scran.filterCells(mat, keepCells); console.log(`Kept ${filtered.numberOfColumns()} of ${mat.numberOfColumns()} cells`); // Free memory scran.free(qcMetrics); scran.free(qcFilters); scran.free(mat); scran.free(filtered); ``` -------------------------------- ### Train Cell Type Reference (JavaScript) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/cell_type_annotation.md Builds a cell type reference model for annotation. This function requires the test dataset's feature names, the loaded reference object, and the reference dataset's feature names. The output is a trained reference object used for labeling cells. ```javascript let built = scran.trainLabelCellsReference(testfeatures, loaded, reffeatures); ``` -------------------------------- ### Graph-Based Clustering with Scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Constructs a shared nearest neighbor (SNN) graph from PCA results and performs community detection clustering using multilevel (Louvain-like) or Leiden algorithms. It also demonstrates Walktrap clustering. Requires scran.js and a matrix.mtx.gz file. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let normalized = scran.normalizeCounts(mat); let varModel = scran.modelGeneVariances(normalized); let hvgs = scran.chooseHvgs(varModel, { number: 4000 }); let pcs = scran.runPca(normalized, { features: hvgs }); let index = scran.buildNeighborSearchIndex(pcs); // Build SNN graph let graph = scran.buildSnnGraph(index, { neighbors: 10, scheme: "rank" // "rank", "number", or "jaccard" }); // Cluster using multilevel (Louvain-like) algorithm let clustering = scran.clusterGraph(graph, { method: "multilevel", multiLevelResolution: 1.0 }); // Access clustering results let membership = clustering.membership(); let numClusters = new Set(membership).size; console.log(`Found ${numClusters} clusters`); console.log(`Modularity: ${clustering.modularity().toFixed(3)}`); // Alternative: Leiden clustering let leidenClustering = scran.clusterGraph(graph, { method: "leiden", leidenResolution: 1.0, leidenObjective: "modularity" }); // Alternative: Walktrap clustering let walktrapClustering = scran.clusterGraph(graph, { method: "walktrap", walktrapSteps: 4 }); scran.free(mat); scran.free(normalized); scran.free(varModel); scran.free(pcs); scran.free(index); scran.free(graph); scran.free(clustering); scran.free(leidenClustering); scran.free(walktrapClustering); ``` -------------------------------- ### Include Directories for scran.js Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Configures the include directories for the 'scran_wasm' target. It specifies 'extern/include' as a private include directory, allowing the project to find its own header files. ```cmake target_include_directories( scran_wasm PRIVATE extern/include ) ``` -------------------------------- ### Finding Required Packages in CMake Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Configures CMake to find necessary external libraries such as igraph, HDF5, and ZLIB. It uses CMAKE_FIND_ROOT_PATH_BOTH to ensure correct path resolution, especially with Emscripten. ```cmake # Need the CMAKE_FIND_ROOT_PATH_BOTH to override Emscripten's overrides (see emscripten/issues#6595) find_package(igraph REQUIRED CONFIG CMAKE_FIND_ROOT_PATH_BOTH) find_package(HDF5 REQUIRED COMPONENTS C CXX CONFIG CMAKE_FIND_ROOT_PATH_BOTH) find_package(ZLIB REQUIRED) ``` -------------------------------- ### Conditional Compilation for Node.js Environment Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Configures build options based on the 'COMPILE_NODE' variable. If true, it sets Emscripten options for Node.js environments, including raw filesystem access and specific exported runtime methods. Otherwise, it configures for web and worker environments. ```cmake set(COMPILE_NODE OFF CACHE BOOL "Compile for Node.js") if (COMPILE_NODE) # Exporting HEAP8 for compatibility with old wasmarrays.js. target_link_options(scran_wasm PRIVATE -sENVIRONMENT=node -sNODERAWFS=1 -sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,PThread ) else () target_link_options(scran_wasm PRIVATE -sENVIRONMENT=web,worker -sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,PThread,FS ) endif() ``` -------------------------------- ### Compute Per-Cell RNA QC Metrics with scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Computes essential quality control metrics for single-cell RNA data, including total UMI counts, the number of detected genes, and the proportion of reads mapping to specified subsets (e.g., mitochondrial genes). The function takes a sparse matrix and a list of boolean arrays defining gene subsets as input. Results can be accessed via methods like `sum()`, `detected()`, and `subsetProportion()`. Remember to free the memory used by the QC metrics object. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); // Define mitochondrial gene subset (boolean array for each row) let mitoSubset = new Array(mat.numberOfRows()).fill(false); // Assume genes 0-99 are mitochondrial for (let i = 0; i < 100; i++) { mitoSubset[i] = true; } // Compute QC metrics let qcMetrics = scran.perCellRnaQcMetrics(mat, [mitoSubset]); // Access results let sums = qcMetrics.sum(); // Total UMI counts per cell let detected = qcMetrics.detected(); // Number of detected genes per cell let mitoProp = qcMetrics.subsetProportion(0); // Mitochondrial proportion console.log(`Cell 0: ${sums[0]} counts, ${detected[0]} genes, ${(mitoProp[0] * 100).toFixed(1)}% mito`); console.log(`Number of cells: ${qcMetrics.numberOfCells()}`); console.log(`Number of subsets: ${qcMetrics.numberOfSubsets()}`); // Free memory scran.free(qcMetrics); scran.free(mat); ``` -------------------------------- ### Run Complete scRNA-seq Analysis Pipeline with scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Executes a full scRNA-seq analysis pipeline, including data loading from Matrix Market format, quality control filtering, normalization, highly variable gene selection, PCA, SNN graph construction, clustering, t-SNE and UMAP for visualization, and marker gene detection. It utilizes scran.js for all computational steps and emphasizes proper memory management by freeing resources after use. ```javascript import * as scran from "scran.js"; import * as fs from "fs"; await scran.initialize({ numberOfThreads: 4 }); // 1. Load data let buffer = fs.readFileSync("matrix.mtx.gz"); let mat = scran.initializeSparseMatrixFromMatrixMarket(buffer); console.log(`Loaded: ${mat.numberOfRows()} genes x ${mat.numberOfColumns()} cells`); // 2. Quality control let mitoGenes = new Array(mat.numberOfRows()).fill(false); for (let i = 0; i < 100; i++) mitoGenes[i] = true; // First 100 are mito let qcMetrics = scran.perCellRnaQcMetrics(mat, [mitoGenes]); let qcFilters = scran.suggestRnaQcFilters(qcMetrics); let keepCells = qcFilters.filter(qcMetrics); let filtered = scran.filterCells(mat, keepCells); console.log(`After QC: ${filtered.numberOfColumns()} cells`); // 3. Normalization let normalized = scran.normalizeCounts(filtered); // 4. Feature selection let varModel = scran.modelGeneVariances(normalized); let hvgs = scran.chooseHvgs(varModel, { number: 4000 }); // 5. Dimensionality reduction let pcs = scran.runPca(normalized, { features: hvgs, numberOfPCs: 25 }); let index = scran.buildNeighborSearchIndex(pcs); // 6. Clustering let graph = scran.buildSnnGraph(index, { neighbors: 10 }); let clustering = scran.clusterGraph(graph); let clusters = clustering.membership(); console.log(`Found ${new Set(clusters).size} clusters`); // 7. Visualization let tsne = scran.runTsne(index, { maxIterations: 1000 }); let umap = scran.runUmap(index, { epochs: 500 }); // 8. Marker detection let markers = scran.scoreMarkers(normalized, clusters); // Output results let results = { clusters: Array.from(clusters), tsne: { x: Array.from(tsne.x), y: Array.from(tsne.y) }, umap: { x: Array.from(umap.x), y: Array.from(umap.y) } }; console.log("Analysis complete!"); // Cleanup scran.free(mat); scran.free(qcMetrics); scran.free(qcFilters); scran.free(filtered); scran.free(normalized); scran.free(varModel); scran.free(pcs); scran.free(index); scran.free(graph); scran.free(clustering); scran.free(markers); scran.terminate(); ``` -------------------------------- ### Load Cell Type Reference from Buffers (JavaScript) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/cell_type_annotation.md Loads a cell type reference dataset from provided ArrayBuffer objects. This function takes rank, marker, and label buffers as input and returns a loaded reference object. It is a prerequisite for training the cell type reference. ```javascript let loaded = scran.loadLabelCellsReferenceFromBuffers(rankbuf, markbuf, labbuf); ``` -------------------------------- ### Compiler Options for scran_wasm Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Sets public compile options for the 'scran_wasm' target, including optimization level (-O3), multithreading support (-pthread), and various warning flags for improved code quality and robustness. ```cmake target_compile_options( scran_wasm PUBLIC -O3 -pthread -Wall -Wpedantic -Wextra -sMEMORY64 ) ``` -------------------------------- ### Configure Eigen CMake Package Build Source: https://github.com/kanaverse/scran.js/blob/master/extern/CMakeLists.txt Sets a CMake option to control the building of the Eigen C++ library as a CMake package. This is useful for managing Eigen's integration within larger CMake projects. ```cmake option(EIGEN_BUILD_CMAKE_PACKAGE "Build the Eigen Cmake package" ON) ``` -------------------------------- ### Linking Libraries for scran.js Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Specifies the libraries to be linked with the 'scran_wasm' target. This includes various 'tatami' libraries, scran-specific modules, k-nearest neighbor libraries, dimensionality reduction libraries, and external dependencies like igraph and HDF5. ```cmake target_link_libraries( scran_wasm tatami_hdf5 tatami_mtx tatami_layered scran_qc scran_norm scran_variances scran_pca scran_aggregate scran_markers knncolle knncolle_annoy qdtsne umappp mumosa mnncorrect igraph::igraph scran_graph_cluster kmeans singlepp singlepp_loaders hdf5-static hdf5_cpp-static rds2cpp phyper gsdecon ) ``` -------------------------------- ### Annotate Cell Types with SingleR using scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Annotates cell types by leveraging reference datasets and the SingleR algorithm. It loads count matrices, reference data from buffers, trains a classifier, and then predicts cell labels. Ensure reference files (ranks, markers, labels) are accessible. ```javascript import * as scran from "scran.js"; import * as fs from "fs"; await scran.initialize({ numberOfThreads: 4 }); // Load test data let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let testFeatures = ["Gene1", "Gene2", "Gene3", ...]; // Gene names from test data // Load reference files (from https://github.com/clusterfork/singlepp-references) let rankBuffer = fs.readFileSync("reference_ranks.csv.gz"); let markerBuffer = fs.readFileSync("reference_markers.gmt.gz"); let labelBuffer = fs.readFileSync("reference_labels.csv.gz"); // Load reference dataset let loadedRef = scran.loadLabelCellsReferenceFromBuffers(rankBuffer, markerBuffer, labelBuffer); console.log(`Reference: ${loadedRef.numberOfSamples()} samples, ${loadedRef.numberOfFeatures()} features, ${loadedRef.numberOfLabels()} labels`); // Reference feature names let refFeatures = ["GeneA", "GeneB", "GeneC", ...]; // From reference metadata // Train classifier let trainedRef = scran.trainLabelCellsReference(testFeatures, loadedRef, refFeatures, { top: 20, // Top markers per comparison approximate: true }); console.log(`Trained with ${trainedRef.numberOfFeatures()} shared features`); // Classify cells let results = scran.labelCells(mat, trainedRef, { quantile: 0.8 }); // Access results let predicted = results.predicted(); // Best label index per cell let delta = results.delta(); // Confidence (score difference) let scoresCell0 = results.scoreForCell(0); // All scores for cell 0 console.log(`Cell 0 predicted label: ${predicted[0]}, delta: ${delta[0].toFixed(3)}`); scran.free(mat); scran.free(loadedRef); scran.free(trainedRef); scran.free(results); ``` -------------------------------- ### Emscripten Linker Options for scran.js Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Sets Emscripten-specific linker options for 'scran_wasm'. These options control optimization, memory growth, stack size, filesystem support, multithreading, and export of functions/names for use in JavaScript. ```cmake target_link_options(scran_wasm PRIVATE -O3 --bind -sALLOW_MEMORY_GROWTH=1 --minify=0 -sMEMORY64 -sMAXIMUM_MEMORY=16GB # current maximum, otherwise Emscripten complains. -sSTACK_SIZE=2MB -sUSE_ZLIB=1 -sMODULARIZE=1 -sEXPORT_NAME=loadScran -sFORCE_FILESYSTEM=1 # for HDF5 file access. -sEXPORT_ES6 -pthread -sPTHREAD_POOL_SIZE=Module.scran_custom_nthreads -sEXPORTED_FUNCTIONS=_malloc,_free ) ``` -------------------------------- ### Integrate Cell Labels from Multiple References (JavaScript) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/cell_type_annotation.md Generates a single set of cell type labels by integrating results from multiple references. This function takes the input matrix, an array of cell labels from individual references, and the integrated reference object. It returns the final integrated cell labels. ```javascript let interlabels = scran.integrateLabelCells(mat, [labels_A, labels_B], inter); ``` -------------------------------- ### Setting Output Name for scran.js Source: https://github.com/kanaverse/scran.js/blob/master/CMakeLists.txt Sets the output name for the 'scran_wasm' target to 'scran'. This determines the final filename of the compiled WebAssembly module. ```cmake set_target_properties(scran_wasm PROPERTIES OUTPUT_NAME scran) ``` -------------------------------- ### Integrate Multiple Cell Type References (JavaScript) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/cell_type_annotation.md Integrates cell labels from multiple reference datasets. This function first classifies the test dataset against each reference individually and then combines the results. It requires test features, an array of loaded references, an array of reference features, and an array of trained references. ```javascript let interbuilt = scran.integrateLabelCellsReferences( testfeatures, [loaded_A, loaded_B], [reffeatures_A, reffeatures_B], [built_A, built_B] ); ``` -------------------------------- ### Log-Normalize Counts with Scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Normalizes raw gene counts using library size factors and applies log-transformation. Supports automatic or custom size factors and optional centering for blocked data. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); // Basic normalization with automatic size factors from library sizes let normalized = scran.normalizeCounts(mat); // With custom size factors let customSizeFactors = new Float64Array(mat.numberOfColumns()); for (let i = 0; i < customSizeFactors.length; i++) { customSizeFactors[i] = 1.0; // Replace with actual size factors } let normalizedCustom = scran.normalizeCounts(mat, { sizeFactors: customSizeFactors, log: true, // Default: log-transform allowZeros: false // Error on zero size factors }); // Center size factors for blocked data let block = new Int32Array(mat.numberOfColumns()).fill(0); // Single block let centered = scran.centerSizeFactors(customSizeFactors, { block: block, toLowestBlock: true }); console.log(`Normalized matrix: ${normalized.numberOfRows()} x ${normalized.numberOfColumns()}`); scran.free(mat); scran.free(normalized); scran.free(normalizedCustom); ``` -------------------------------- ### Detect Marker Genes with scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Identifies potential marker genes for each cluster by scoring them based on various effect sizes. It utilizes normalized counts, cluster memberships, and computes statistics like log-fold change, AUC, and Cohen's d. The function also provides utilities to select top markers. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let normalized = scran.normalizeCounts(mat); let varModel = scran.modelGeneVariances(normalized); let hvgs = scran.chooseHvgs(varModel, { number: 4000 }); let pcs = scran.runPca(normalized, { features: hvgs }); let index = scran.buildNeighborSearchIndex(pcs); let graph = scran.buildSnnGraph(index); let clustering = scran.clusterGraph(graph); // Score markers for each cluster let markers = scran.scoreMarkers(normalized, clustering.membership(), { threshold: 0, // Minimum log-fold change computeAuc: true, // Compute AUC computeMedian: false, computeMaximum: false }); console.log(`Markers computed for ${markers.numberOfGroups()} groups`); // Get statistics for cluster 0 let group = 0; let meanExpr = markers.mean(group); let detected = markers.detected(group); let cohensD = markers.cohensD(group, { summary: "mean" }); let auc = markers.auc(group, { summary: "mean" }); let logFC = markers.deltaMean(group, { summary: "mean" }); // Find top markers by Cohen's d let topMarkers = scran.chooseTopMarkers(cohensD, 10, { useLargest: true }); console.log(`Top 10 marker genes for cluster ${group}: ${topMarkers.join(", ")}`); // Print top marker statistics topMarkers.forEach(geneIdx => { console.log(`Gene ${geneIdx}: Cohen's d=${cohensD[geneIdx].toFixed(2)}, AUC=${auc[geneIdx].toFixed(2)}, logFC=${logFC[geneIdx].toFixed(2)}`); }); scran.free(mat); scran.free(normalized); scran.free(varModel); scran.free(pcs); scran.free(index); scran.free(graph); scran.free(clustering); scran.free(markers); ``` -------------------------------- ### Label Cells with Trained Reference (JavaScript) Source: https://github.com/kanaverse/scran.js/blob/master/docs/related/cell_type_annotation.md Assigns cell type labels to cells in a given matrix using a trained reference. The function takes the input matrix and the trained reference object. It returns an array of indices corresponding to the label names. ```javascript let labels = scran.labelCells(mat, built); ``` -------------------------------- ### Model Gene Variances and Select HVGs with Scran.js Source: https://context7.com/kanaverse/scran.js/llms.txt Models the mean-variance relationship of genes from normalized counts and selects highly variable genes (HVGs). It provides access to mean, variance, fitted values, and residuals. ```javascript import * as scran from "scran.js"; await scran.initialize({ numberOfThreads: 4 }); let mat = scran.initializeSparseMatrixFromMatrixMarket("matrix.mtx.gz"); let normalized = scran.normalizeCounts(mat); // Model gene variance let varModel = scran.modelGeneVariances(normalized, { span: 0.3 }); // Access variance statistics let means = varModel.means(); // Mean expression per gene let variances = varModel.variances(); // Variance per gene let fitted = varModel.fitted(); // Fitted values from trend let residuals = varModel.residuals(); // Residuals (biological variance) console.log(`Gene 0: mean=${means[0].toFixed(3)}, var=${variances[0].toFixed(3)}, resid=${residuals[0].toFixed(3)}`); // Select top HVGs based on residuals let hvgs = scran.chooseHvgs(varModel, { number: 4000, // Select top 4000 HVGs minimum: 0 // Minimum residual threshold }); // Count selected HVGs let numHvgs = hvgs.reduce((a, b) => a + b, 0); console.log(`Selected ${numHvgs} highly variable genes`); scran.free(mat); scran.free(normalized); scran.free(varModel); ```