diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ + diff --git a/404.html b/404.html new file mode 100644 index 0000000..ed99fc9 --- /dev/null +++ b/404.html @@ -0,0 +1,96 @@ + + + + + + + +Page not found (404) • SeuratIntegrate + + + + + + + + + + + + + + + + Skip to contents + + +
+
+
+ +Content not found. Please use links in the navbar. + +
+
+ + + +
+ + + + + + + diff --git a/LICENSE-text.html b/LICENSE-text.html new file mode 100644 index 0000000..94ae9fc --- /dev/null +++ b/LICENSE-text.html @@ -0,0 +1,66 @@ + +License • SeuratIntegrate + Skip to contents + + +
+
+
+ +
YEAR: 2024
+COPYRIGHT HOLDER: Centre de Bioinformatique de Bordeaux (CBiB)
+
+ +
+ + +
+ + + + + + + diff --git a/LICENSE.html b/LICENSE.html new file mode 100644 index 0000000..d947467 --- /dev/null +++ b/LICENSE.html @@ -0,0 +1,70 @@ + +MIT License • SeuratIntegrate + Skip to contents + + +
+
+
+ +
+ +

Copyright (c) 2024 Centre de Bioinformatique de Bordeaux (CBiB)

+

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+ +
+ + +
+ + + + + + + diff --git a/apple-touch-icon.png b/apple-touch-icon.png new file mode 100644 index 0000000..27b056b Binary files /dev/null and b/apple-touch-icon.png differ diff --git a/articles/SeuratIntegrate.html b/articles/SeuratIntegrate.html new file mode 100644 index 0000000..0f84321 --- /dev/null +++ b/articles/SeuratIntegrate.html @@ -0,0 +1,894 @@ + + + + + + + +Introduction to SeuratIntegrate • SeuratIntegrate + + + + + + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + + +
+

Introduction +

+

SeuratIntegrate is an R package that aims to extend the pool of +single-cell RNA sequencing (scRNA-seq) integration methods available in +Seurat. Moreover, +SeuratIntegrate provides a set of tools to evaluate the performance of +the integrations produced.

+
+

Integrations +

+

SeuratIntegrate provides access to R and Python methods to correct +batch effect:

+ + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Comprehensive overview of the integration methods provided by +SeuratIntegrate
MethodTypeImplementationUnderlying algorithmReference
ComBatR logo +sva +(Bioconductor)Empirical Bayes adjustmentJohnson et al., +2007
HarmonyR logo +harmony +(CRAN)Iterative embedding correctionKorsunsky et al., +2019
MNNR logo +batchelor +(Bioconductor)Mutual Nearest NeighborsHaghverdi +et al., 2018
BBKNNPython logo +bbknn +(GitHub)Batch-balanced nearest neighborsPolański et al., +2020
scVIPython logo +scvi-tools +(GitHub)Variational autoencoderLopez et al., +2018
scANVIPython logo +scvi-tools +(GitHub)Semi-supervised variational autoencoderXu et +al., 2021
ScanoramaPython logo +scanorama (GitHub)Manifold alignmentHie et al., +2019
trVAEPython logo +scArches (GitHub)Conditional variational autoencoderLotfollahi et al., +2020
+

SeuratIntegrate provides a new interface to integrate the layers of +an object: DoIntegrate(). Moreover, SeuratIntegrate is +compatible with CCA and RPCA (included in Seurat) and +FastMNN (from SeuratWrappers)

+
+
+

Scoring +

+

SeuratIntegrate incorporates 11 scoring metrics: 6 quantify the +degree of batch mixing batch correction (batch +correction), while 5 assess the preservation of biological +differences bio-conservation (bio-conservation) based +on ground truth cell type labels.

+

Below is a table summarising each score’s input and type:

+ + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table summarising the inputs required for each score, and the +type of scores it belongs to.
Score nameRequire a cell type variableRequire a clustering variableInputScore type
Cell cycle regressionDimension reductionbio-conservation
PCA regressionDimension reductionbatch correction
PCA densityDimension reductionbatch correction
ASW batchcell-type variableDimension reductionbatch correction
ASWcell-type variableDimension reductionbio-conservation
ARIcell-type variableclustering variablebio-conservation
NMIcell-type variableclustering variablebio-conservation
cLISIcell-type variable +Dimension reduction or +KNN graph +bio-conservation
iLISIcell-type variable +Dimension reduction or +KNN graph +batch correction
kBETcell-type variable +Dimension reduction or +KNN graph +batch correction
Graph connectivity +cell-type variable +(per.component = TRUE)KNN graphbatch correction
+

Most scores are computed on an embedding DimReduc object +(Seurat::DimReduc object) or a graph Graph or Neighbor object (Seurat::Neighbor or +Seurat::Graph object). The exceptions are ARI and NMI, +which compare two categorical variables thus don’t need anything else +than a cell-type and a cluster assignment variables.d anything else than +a cell-type and a cluster assignment variables.

+

Most scores are based on a cell type label variable. This consists in +an estimate of each cell’s type obtained by analysing each batch +separately or by using an automatic cell annotation algorithm. This +estimate of cell types must be of sufficient quality to be considered +suitable as ground truth.

+
+
+
+

Setup +

+ +

We will use the small dataset of 200 immune liver cells and around +6,500 genes included in SeuratIntegrate.

+
+data("liver_small")
+
+dim(liver_small)  # genes x cells
+
## [1] 6534  200
+

It comprises 4 donors from 2 studies. Among the donors, 2 are healthy +and 2 are suffering from a hepatocellular carcinoma (HCC).

+
+ +
+

Importantly, the Seurat object’s metadata also embeds cell type +annotation variables.

+
+liver_small[[]][,c(13, 15:17)]
+
+ +
+

Note that albeit not compulsory, a high quality cell-type +annotation is very important to evaluate the performance of +integrations because many scoring metrics use them as ground truth. +Moreover, it helps in verifying whether technical effects (usually +called batch effects) overweight true biological differences.

+

Here, we use the last one and save it:

+
+cell.var <- "manual_cell_type_short"
+

We are going to test 3 integration methods that output different +types of objects. We will use ComBat (corrected counts), BBKNN +(corrected knn graph) and Harmony (corrected dimension reduction). BBKNN +is a Python method, so we need to have a conda environment to be able to +use it. Right now, we don’t have such an environment:

+ +

Unset conda environments

+

Hopefully, SeuratIntegrate facilitates the task with +UpdateEnvCache():

+
+UpdateEnvCache("bbknn")
+
+Note: Similarly, you can call UpdateEnvCache() +with all other Python methods (“scvi”, “scanorama”, “trVAE”) to set up +their corresponding conda environments. +
+

If the process is successful, the cache of conda environments should +have been updated:

+ +

Conda environment set for BBKNN

+

We also want to make sure we have a conda environment with a +umap-learn version compatible with Seurat:

+
+reticulate::conda_create('umap_0.5.4', packages = 'umap=0.5.4')
+
+
+

Preprocessing with Seurat +

+

To ensure that SeuratIntegrate works well, it is indispensable to +split the Seurat object. This process distributes cells into +single-batch layers such that each batch is normalized independently. We +account for potential technical variability between samples by +designating “ID_sample” as the batch variable.

+
+batch.var <- "ID_sample"  # save for later
+
+liver_small <- split(liver_small, f = liver_small$ID_sample)
+liver_small <- SCTransform(liver_small)
+
+liver_small <- RunPCA(liver_small)
+liver_small <- FindNeighbors(liver_small, dims = 1:20, k.param = 15L)
+liver_small <- RunUMAP(liver_small, dims = 1:20, n.neighbors = 15)
+
+DimPlot(liver_small, group.by = c("First_author", "ID_sample"))
+

UMAP of unintegrated liver data with cells colored by first author and sample id (i.e. batch)

+
+DimPlot(liver_small, group.by = cell.var)
+

UMAP of unintegrated liver data with cells colored by cell type label

+
+
+

Integration with SeuratIntegrate +

+
+liver_small <-
+  DoIntegrate(object = liver_small,
+              
+            # integrations
+              CombatIntegration(),
+              bbknnIntegration(orig = "pca", ndims.use = 20),
+              SeuratIntegrate::HarmonyIntegration(orig = "pca", dims = 1:20),
+              
+            # additional parameters
+              use.hvg = TRUE,
+              use.future = c(FALSE, TRUE, FALSE)
+)
+
## Integration 1 in 3: integrating using 'CombatIntegration'
+## Integration 2 in 3: integrating using 'bbknnIntegration'
+## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
+## 
+## Number of nodes: 200
+## Number of edges: 1784
+## 
+## Running Louvain algorithm...
+## Maximum modularity in 10 random starts: 0.6251
+## Number of communities: 5
+## Elapsed time: 0 seconds
+## Integration 3 in 3: integrating using 'SeuratIntegrate::HarmonyIntegration'
+

If we take a look at our Seurat object, we can note that it has been +enriched with many objects:

+
+print(liver_small)
+cat("\n#####\n\n")
+print(Graphs(liver_small))
+
## An object of class Seurat 
+## 22602 features across 200 samples within 4 assays 
+## Active assay: SCT (6534 features, 3000 variable features)
+##  3 layers present: counts, data, scale.data
+##  3 other assays present: RNA, combat.reconstructed, bbknn.ridge
+##  4 dimensional reductions calculated: pca, umap, pca.bbknn, harmony
+## 
+## #####
+## 
+## [1] "SCT_nn"                              
+## [2] "SCT_snn"                             
+## [3] "bbknn_scale.data_connectivities"     
+## [4] "bbknn_scale.data_distances"          
+## [5] "bbknn_ridge.residuals_connectivities"
+## [6] "bbknn_ridge.residuals_distances"
+

Important outputs are:

+
    +
  • New assay combat.reconstructed +
  • +
  • New reduction harmony +
  • +
  • New graphs bbknn_ridge.residuals_[…] +
  • +
+
+
+

Post-processing +

+

The type of output is important to consider, because scoring metrics +are not compatible with all output types. The simplest strategy is to +process each output separately in order to obtain at least a PCA out of +it, or even a knn graph (indispensable to compute clusters). Note that +several scores cannot be computed on knn graphs, hence knn graph outputs +(e.g. BBKNN) can only be evaluated by a reduced set of metrics.

+

Below is a summary for each output type (bracketed steps are not +always necessary):

+ +

Here, we will use SymmetrizeKnn() between +FindNeighbors() and FindOptimalClusters() +because return.neighbor = TRUE. This is useful to keep the +distances between cells in the KNN graph. Although not +compulsory, this is used to stay in line with BBKNN’s output. To prevent +the community detection algorithm to output a high fraction of +singletons, we “symmetrize” the matrix which makes the graph +“undirected”.

+
+# corrected counts outputs
+DefaultAssay(liver_small) <- "combat.reconstructed"
+VariableFeatures(liver_small) <- VariableFeatures(liver_small[["SCT"]])
+liver_small <- ScaleData(liver_small)
+
+liver_small <- RunPCA(liver_small, npcs = 50L, reduction.name = "pca.combat")
+liver_small <- FindNeighbors(liver_small, reduction = "pca.combat", dims = 1:20,
+                     return.neighbor = TRUE, graph.name = "knn.combat")
+liver_small <- SymmetrizeKnn(liver_small, graph.name = "knn.combat")
+liver_small <- FindOptimalClusters(liver_small, graph.name = "knn.combat_symmetric",
+                           cluster.name = "combat_{cell.var}_{metric}",
+                           cell.var = cell.var,
+                           optimisation.metric = c("nmi", "ari")) # default, compute both
+
+DefaultAssay(liver_small) <- "SCT"
+
+# dimension reduction outputs
+liver_small <- FindNeighbors(liver_small, reduction = "pca", dims = 1:20, k.param = 20L,
+                     return.neighbor = TRUE, graph.name = "knn.unintegrated")
+liver_small <- SymmetrizeKnn(liver_small, graph.name = "knn.unintegrated")
+liver_small <- FindOptimalClusters(liver_small, graph.name = "knn.unintegrated_symmetric",
+                           cluster.name = "unintegrated_{cell.var}_{metric}",
+                           cell.var = cell.var)
+
+
+liver_small <- FindNeighbors(liver_small, reduction = "harmony", dims = 1:20,
+                     return.neighbor = TRUE, graph.name = "knn.harmony")
+liver_small <- SymmetrizeKnn(liver_small, graph.name = "knn.harmony")
+liver_small <- FindOptimalClusters(liver_small, graph.name = "knn.harmony_symmetric", cell.var = cell.var,
+                           cluster.name = "harmony_{cell.var}_{metric}")
+
+# graph outputs
+liver_small <- SymmetrizeKnn(liver_small, graph.name = "bbknn_ridge.residuals_distances")
+liver_small <- FindOptimalClusters(liver_small, graph.name = "bbknn_ridge.residuals_distances_symmetric",
+                           cell.var = cell.var, cluster.name = "bbknn_{cell.var}_{metric}")
+
+
+

Scoring +

+

Now that we have post-processed each integration’s output, we can +compute multiple scores to estimate the accuracy of the +integrations.

+
+

Scores not requiring a cell type variable +

+

Those scores are run on a dimension reduction (such as a PCA) and are +not compatible with graph outputs. They are cell-type free score thus do +not require a cell-type label variable.

+
+liver_small <- AddScoreRegressPC(liver_small, integration = "unintegrated",
+                                 batch.var = batch.var, reduction = "pca")
+liver_small <- AddScoreRegressPC(liver_small, integration = "combat",
+                                 batch.var = batch.var, reduction = "pca.combat")
+liver_small <- AddScoreRegressPC(liver_small, integration = "harmony",
+                                 batch.var = batch.var, reduction = "harmony")
+
+liver_small <- AddScoreDensityPC(liver_small, integration = "unintegrated",
+                                 batch.var = batch.var, reduction = "pca")
+liver_small <- AddScoreDensityPC(liver_small, integration = "combat",
+                                 batch.var = batch.var, reduction = "pca.combat")
+liver_small <- AddScoreRegressPC(liver_small, integration = "harmony",
+                                 batch.var = batch.var, reduction = "harmony")
+
+liver_small <- CellCycleScoringPerBatch(liver_small, batch.var = batch.var,
+                                        s.features = cc.genes$s.genes,
+                                        g2m.features = cc.genes$g2m.genes)
+liver_small <- AddScoreRegressPC.CellCycle(liver_small, integration = "unintegrated",
+                                           batch.var = batch.var, what = "pca",
+                                           compute.cc = FALSE, dims.use = 1:20)
+liver_small <- AddScoreRegressPC.CellCycle(liver_small, integration = "combat",
+                                           batch.var = batch.var, what = "pca.combat",
+                                           compute.cc = FALSE, dims.use = 1:20)
+liver_small <- AddScoreRegressPC.CellCycle(liver_small, integration = "harmony",
+                                           batch.var = batch.var, what = "harmony",
+                                           compute.cc = FALSE, dims.use = 1:20)
+
+
+

Scores based on silhouette width +

+

Those scores return an average silhouette width (ASW), either per +cell type label or per batch. They are run on a dimension reduction +(such as a PCA) and are not compatible with graph outputs. They are +based on a cell-type label variable. However, +ScoreASWBatch() can be run in a cell-type label independent +manner with per.cell.var = FALSE.

+
+liver_small <- AddScoreASW(liver_small, integration = "unintegrated",
+                           cell.var = cell.var, what = "pca")
+liver_small <- AddScoreASW(liver_small, integration = "combat",
+                           cell.var = cell.var, what = "pca.combat")
+liver_small <- AddScoreASW(liver_small, integration = "harmony",
+                           cell.var = cell.var, what = "harmony")
+
+liver_small <- AddScoreASWBatch(liver_small, integration = "unintegrated",
+                                batch.var = batch.var, cell.var = cell.var,
+                                what = "pca")
+liver_small <- AddScoreASWBatch(liver_small, integration = "combat",
+                                batch.var = batch.var, cell.var = cell.var,
+                                what = "pca.combat")
+liver_small <- AddScoreASWBatch(liver_small, integration = "harmony",
+                                batch.var = batch.var, cell.var = cell.var,
+                                what = "harmony")
+
+
+

Scores working on a graph +

+

Those scores are graph outputs. They require a cell-type label +variable.

+
+liver_small <- AddScoreConnectivity(liver_small, integration = "unintegrated",
+                                    graph.name = "knn.unintegrated_symmetric",
+                                    cell.var = cell.var)
+liver_small <- AddScoreConnectivity(liver_small, integration = "combat",
+                                    graph.name = "knn.combat_symmetric",
+                                    cell.var = cell.var)
+liver_small <- AddScoreConnectivity(liver_small, integration = "harmony",
+                                    graph.name = "knn.harmony_symmetric",
+                                    cell.var = cell.var)
+liver_small <- AddScoreConnectivity(liver_small, integration = "bbknn",
+                                    graph.name = "bbknn_ridge.residuals_distances_symmetric",
+                                    cell.var = cell.var)
+
+liver_small <- AddScoreLISI(liver_small, integration = "unintegrated",
+                            batch.var = batch.var, cell.var = cell.var,
+                            reduction = "pca")
+liver_small <- AddScoreLISI(liver_small, integration = "combat",
+                            batch.var = batch.var, cell.var = cell.var,
+                            reduction = "pca.combat")
+liver_small <- AddScoreLISI(liver_small, integration = "harmony",
+                            batch.var = batch.var, cell.var = cell.var,
+                            reduction = "harmony")
+liver_small <- AddScoreLISI(liver_small, integration = "bbknn",
+                            batch.var = batch.var, cell.var = cell.var,
+                            reduction = NULL,
+                            graph.name = "bbknn_ridge.residuals_distances_symmetric")
+
+
+

Scores comparing two categorical variables +

+

Those scores compare two categorical variables. Thus, they don’t need +anything else than a cell-type and a cluster assignment variables +(computed during Post-processing with +FindOptimalClusters()).

+
+liver_small <- AddScoreARI(liver_small, integration = "unintegrated",
+                           cell.var = cell.var,
+                           clust.var = paste("unintegrated", cell.var, "ari", sep = "_"))
+liver_small <- AddScoreARI(liver_small, integration = "combat",
+                           cell.var = cell.var,
+                           clust.var = paste("combat", cell.var, "ari", sep = "_"))
+liver_small <- AddScoreARI(liver_small, integration = "harmony",
+                           cell.var = cell.var,
+                           clust.var = paste("harmony", cell.var, "ari", sep = "_"))
+liver_small <- AddScoreARI(liver_small, integration = "bbknn",
+                           cell.var = cell.var,
+                           clust.var = paste("bbknn", cell.var, "ari", sep = "_"))
+
+liver_small <- AddScoreNMI(liver_small, integration = "unintegrated",
+                           cell.var = cell.var,
+                           clust.var = paste("unintegrated", cell.var, "nmi", sep = "_"))
+liver_small <- AddScoreNMI(liver_small, integration = "combat",
+                           cell.var = cell.var,
+                           clust.var = paste("combat", cell.var, "nmi", sep = "_"))
+liver_small <- AddScoreNMI(liver_small, integration = "harmony",
+                           cell.var = cell.var,
+                           clust.var = paste("harmony", cell.var, "nmi", sep = "_"))
+liver_small <- AddScoreNMI(liver_small, integration = "bbknn",
+                           cell.var = cell.var,
+                           clust.var = paste("bbknn", cell.var, "nmi", sep = "_"))
+
+
+

Scaling and comparison +

+

Now that we have obtained several scores per integration, we can +compare their performances. First, let’s scale the scores between zero +and one and standardize their direction (the closer to one, always the +better). This step makes things easier to compare and improves +interpretability.

+
+liver_small <- ScaleScores(liver_small)
+

Now, let’s plot the integrations.

+
+PlotScores(liver_small)
+

Dot plot to compare performance of integrations based on scores

+

We can observe that 3 overall scores have been computed, namely batch +correction, bio-conservation and overall (the average of the last two). +To balance each score’s contribution to the overall scores, a min-max +rescaling is applied on each score after scaling, stretching the +original score’s bounds to zero and one.

+

It can be disabled to preview the original scores:

+
+PlotScores(liver_small, rescale = FALSE)
+

Dot plot of scores without min-max rescaling

+

We can also hide scores or integrations. For instance, “PCA.density” +and “PCA.regression” are hardly informative. Let’s exclude them and see +how it affects overall scores:

+
+PlotScores(liver_small, rescale = FALSE, exclude.score = c("PCA.density", "PCA.regression"))
+

Dot plot of scores without min-max rescaling, excluding non-informative scores

+

Interestingly, we obtained the same ranking of integrations as in the +first figure.

+
+
+
+

Projecting integrations on UMAPs +

+

It is also possible to project the cells on a UMAP computed for each +integration’s output, as a complementary (visual) inspection of +integration performances.

+
+liver_small <- RunUMAP(liver_small, dims = 1:20, reduction = "pca.combat",
+                       reduction.name = "umap.combat")
+liver_small <- RunUMAP(liver_small, dims = 1:20, reduction = "harmony",
+                       reduction.name = "umap.harmony")
+
+library(future)
+plan(multisession)
+liver_small %<-% {
+  reticulate::use_condaenv('umap_0.5.4')
+  RunUMAP(liver_small, graph = "bbknn_ridge.residuals_connectivities",
+          umap.method = "umap-learn", n.epochs = 200L,
+          reduction.name = "umap.bbknn") }
+liver_small
+plan(sequential)
+
+DimPlot(liver_small, group.by = c(batch.var, cell.var), reduction = "umap")
+
+UMAP of unintegrated data

+UMAP of unintegrated data +

+
+
+DimPlot(liver_small, group.by = c(batch.var, cell.var), reduction = "umap.combat")
+
+UMAP of ComBat integration

+UMAP of ComBat integration +

+
+
+DimPlot(liver_small, group.by = c(batch.var, cell.var), reduction = "umap.bbknn")
+
+UMAP of BBKNN integration

+UMAP of BBKNN integration +

+
+
Session info +
  ## R version 4.4.2 (2024-10-31)
+  ## Platform: x86_64-pc-linux-gnu
+  ## Running under: Linux Mint 21
+  ## 
+  ## Matrix products: default
+  ## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
+  ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
+  ## 
+  ## locale:
+  ##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
+  ##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
+  ##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=en_US.UTF-8   
+  ##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
+  ##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
+  ## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
+  ## 
+  ## time zone: Europe/Paris
+  ## tzcode source: system (glibc)
+  ## 
+  ## attached base packages:
+  ## [1] stats     graphics  grDevices utils     datasets  methods   base     
+  ## 
+  ## other attached packages:
+  ## [1] future_1.34.0         dplyr_1.1.4           SeuratIntegrate_0.4.0
+  ## [4] Seurat_5.1.0          SeuratObject_5.0.2    sp_2.1-4             
+  ## 
+  ## loaded via a namespace (and not attached):
+  ##   [1] RcppAnnoy_0.0.22            splines_4.4.2              
+  ##   [3] later_1.4.1                 batchelor_1.20.0           
+  ##   [5] tibble_3.2.1                polyclip_1.10-7            
+  ##   [7] XML_3.99-0.17               fastDummies_1.7.4          
+  ##   [9] lifecycle_1.0.4             edgeR_4.2.2                
+  ##  [11] globals_0.16.3              lattice_0.22-6             
+  ##  [13] MASS_7.3-61                 backports_1.5.0            
+  ##  [15] magrittr_2.0.3              limma_3.60.6               
+  ##  [17] plotly_4.10.4               sass_0.4.9                 
+  ##  [19] rmarkdown_2.29              jquerylib_0.1.4            
+  ##  [21] yaml_2.3.10                 httpuv_1.6.15              
+  ##  [23] glmGamPoi_1.16.0            sctransform_0.4.1          
+  ##  [25] spam_2.11-0                 spatstat.sparse_3.1-0      
+  ##  [27] reticulate_1.40.0           DBI_1.2.3                  
+  ##  [29] cowplot_1.1.3               pbapply_1.7-2              
+  ##  [31] RColorBrewer_1.1-3          ResidualMatrix_1.14.1      
+  ##  [33] abind_1.4-8                 zlibbioc_1.50.0            
+  ##  [35] Rtsne_0.17                  GenomicRanges_1.56.2       
+  ##  [37] purrr_1.0.2                 BiocGenerics_0.50.0        
+  ##  [39] tweenr_2.0.3                rappdirs_0.3.3             
+  ##  [41] sva_3.52.0                  GenomeInfoDbData_1.2.12    
+  ##  [43] IRanges_2.38.1              S4Vectors_0.42.1           
+  ##  [45] ggrepel_0.9.6               irlba_2.3.5.1              
+  ##  [47] listenv_0.9.1               spatstat.utils_3.1-1       
+  ##  [49] genefilter_1.86.0           goftest_1.2-3              
+  ##  [51] RSpectra_0.16-2             annotate_1.82.0            
+  ##  [53] spatstat.random_3.3-2       fitdistrplus_1.2-1         
+  ##  [55] parallelly_1.41.0           pkgdown_2.1.1              
+  ##  [57] DelayedMatrixStats_1.26.0   leiden_0.4.3.1             
+  ##  [59] codetools_0.2-20            DelayedArray_0.30.1        
+  ##  [61] ggforce_0.4.2               scuttle_1.14.0             
+  ##  [63] tidyselect_1.2.1            UCSC.utils_1.0.0           
+  ##  [65] farver_2.1.2                ScaledMatrix_1.12.0        
+  ##  [67] matrixStats_1.4.1           stats4_4.4.2               
+  ##  [69] spatstat.explore_3.3-3      jsonlite_1.8.9             
+  ##  [71] BiocNeighbors_1.22.0        progressr_0.15.1           
+  ##  [73] ggridges_0.5.6              survival_3.8-3             
+  ##  [75] systemfonts_1.1.0           tools_4.4.2                
+  ##  [77] ragg_1.3.3                  ica_1.0-3                  
+  ##  [79] Rcpp_1.0.13-1               glue_1.8.0                 
+  ##  [81] gridExtra_2.3               SparseArray_1.4.8          
+  ##  [83] mgcv_1.9-1                  xfun_0.49                  
+  ##  [85] MatrixGenerics_1.16.0       GenomeInfoDb_1.40.1        
+  ##  [87] withr_3.0.2                 fastmap_1.2.0              
+  ##  [89] digest_0.6.37               rsvd_1.0.5                 
+  ##  [91] R6_2.5.1                    mime_0.12                  
+  ##  [93] textshaping_0.4.1           colorspace_2.1-1           
+  ##  [95] scattermore_1.2             tensor_1.5                 
+  ##  [97] RSQLite_2.3.9               spatstat.data_3.1-4        
+  ##  [99] RhpcBLASctl_0.23-42         tidyr_1.3.1                
+  ## [101] generics_0.1.3              data.table_1.16.4          
+  ## [103] httr_1.4.7                  htmlwidgets_1.6.4          
+  ## [105] S4Arrays_1.4.1              uwot_0.2.2                 
+  ## [107] pkgconfig_2.0.3             gtable_0.3.6               
+  ## [109] blob_1.2.4                  lmtest_0.9-40              
+  ## [111] SingleCellExperiment_1.26.0 XVector_0.44.0             
+  ## [113] htmltools_0.5.8.1           dotCall64_1.2              
+  ## [115] scales_1.3.0                Biobase_2.64.0             
+  ## [117] png_0.1-8                   lisi_1.0                   
+  ## [119] harmony_1.2.3               spatstat.univar_3.1-1      
+  ## [121] knitr_1.49                  rstudioapi_0.17.1          
+  ## [123] reshape2_1.4.4              nlme_3.1-166               
+  ## [125] cachem_1.1.0                zoo_1.8-12                 
+  ## [127] stringr_1.5.1               KernSmooth_2.23-24         
+  ## [129] parallel_4.4.2              miniUI_0.1.1.1             
+  ## [131] AnnotationDbi_1.66.0        desc_1.4.3                 
+  ## [133] pillar_1.10.0               grid_4.4.2                 
+  ## [135] vctrs_0.6.5                 RANN_2.6.2                 
+  ## [137] promises_1.3.2              BiocSingular_1.20.0        
+  ## [139] distances_0.1.11            beachmat_2.20.0            
+  ## [141] xtable_1.8-4                cluster_2.1.8              
+  ## [143] evaluate_1.0.1              locfit_1.5-9.10            
+  ## [145] cli_3.6.3                   compiler_4.4.2             
+  ## [147] rlang_1.1.4                 crayon_1.5.3               
+  ## [149] future.apply_1.11.3         labeling_0.4.3             
+  ## [151] plyr_1.8.9                  forcats_1.0.0              
+  ## [153] fs_1.6.5                    stringi_1.8.4              
+  ## [155] viridisLite_0.4.2           deldir_2.0-4               
+  ## [157] BiocParallel_1.38.0         Biostrings_2.72.1          
+  ## [159] munsell_0.5.1               lazyeval_0.2.2             
+  ## [161] spatstat.geom_3.3-4         Matrix_1.7-1               
+  ## [163] RcppHNSW_0.6.0              patchwork_1.3.0            
+  ## [165] bit64_4.5.2                 sparseMatrixStats_1.16.0   
+  ## [167] ggplot2_3.5.1               statmod_1.5.0              
+  ## [169] KEGGREST_1.44.1             shiny_1.10.0               
+  ## [171] SummarizedExperiment_1.34.0 ROCR_1.0-11                
+  ## [173] memoise_2.0.1               igraph_2.1.2               
+  ## [175] broom_1.0.7                 bslib_0.8.0                
+  ## [177] bit_4.5.0.1
+
+
+
+
+ + + + +
+ + + + + + + diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-13-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-13-1.png new file mode 100644 index 0000000..0b61340 Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-13-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-14-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-14-1.png new file mode 100644 index 0000000..097bf1a Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-14-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-21-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-21-1.png new file mode 100644 index 0000000..a94b7ab Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-21-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-22-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-22-1.png new file mode 100644 index 0000000..3ee70be Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-22-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-23-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-23-1.png new file mode 100644 index 0000000..70226d8 Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-23-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-25-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-25-1.png new file mode 100644 index 0000000..8b417a1 Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-25-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-26-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-26-1.png new file mode 100644 index 0000000..4d47ad7 Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-26-1.png differ diff --git a/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-27-1.png b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-27-1.png new file mode 100644 index 0000000..40dfc4c Binary files /dev/null and b/articles/SeuratIntegrate_files/figure-html/unnamed-chunk-27-1.png differ diff --git a/articles/SeuratIntegrate_files/pagedtable-1.1/css/pagedtable.css b/articles/SeuratIntegrate_files/pagedtable-1.1/css/pagedtable.css new file mode 100644 index 0000000..8764d88 --- /dev/null +++ b/articles/SeuratIntegrate_files/pagedtable-1.1/css/pagedtable.css @@ -0,0 +1,142 @@ +.pagedtable { + overflow: auto; + padding-left: 8px; + padding-right: 8px; +} + +.pagedtable-wrapper { + border: 1px solid #ccc; + border-radius: 4px; + margin-bottom: 10px; +} + +.pagedtable table { + width: 100%; + max-width: 100%; + margin: 0; +} + +.pagedtable th { + padding: 0 5px 0 5px; + border: none; + border-bottom: 2px solid #dddddd; + + min-width: 45px; +} + +.pagedtable-empty th { + display: none; +} + +.pagedtable td { + padding: 0 4px 0 4px; +} + +.pagedtable .even { + background-color: rgba(140, 140, 140, 0.1); +} + +.pagedtable-padding-col { + display: none; +} + +.pagedtable a { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.pagedtable-index-nav { + cursor: pointer; + padding: 0 5px 0 5px; + float: right; + border: 0; +} + +.pagedtable-index-nav-disabled { + cursor: default; + text-decoration: none; + color: #999; +} + +a.pagedtable-index-nav-disabled:hover { + text-decoration: none; + color: #999; +} + +.pagedtable-indexes { + cursor: pointer; + float: right; + border: 0; +} + +.pagedtable-index-current { + cursor: default; + text-decoration: none; + font-weight: bold; + color: #333; + border: 0; +} + +a.pagedtable-index-current:hover { + text-decoration: none; + font-weight: bold; + color: #333; +} + +.pagedtable-index { + width: 30px; + display: inline-block; + text-align: center; + border: 0; +} + +.pagedtable-index-separator-left { + display: inline-block; + color: #333; + font-size: 9px; + padding: 0 0 0 0; + cursor: default; +} + +.pagedtable-index-separator-right { + display: inline-block; + color: #333; + font-size: 9px; + padding: 0 4px 0 0; + cursor: default; +} + +.pagedtable-footer { + padding-top: 4px; + padding-bottom: 5px; +} + +.pagedtable-not-empty .pagedtable-footer { + border-top: 2px solid #dddddd; +} + +.pagedtable-info { + overflow: hidden; + color: #999; + white-space: nowrap; + text-overflow: ellipsis; +} + +.pagedtable-header-name { + overflow: hidden; + text-overflow: ellipsis; +} + +.pagedtable-header-type { + color: #999; + font-weight: 400; +} + +.pagedtable-na-cell { + font-style: italic; + opacity: 0.3; +} diff --git a/articles/SeuratIntegrate_files/pagedtable-1.1/js/pagedtable.js b/articles/SeuratIntegrate_files/pagedtable-1.1/js/pagedtable.js new file mode 100644 index 0000000..52ada2b --- /dev/null +++ b/articles/SeuratIntegrate_files/pagedtable-1.1/js/pagedtable.js @@ -0,0 +1,1151 @@ +// Production steps of ECMA-262, Edition 5, 15.4.4.18 +// Reference: http://es5.github.io/#x15.4.4.18 +if (!Array.prototype.forEach) { + + Array.prototype.forEach = function(callback, thisArg) { + + var T, k; + + if (this === null) { + throw new TypeError(' this is null or not defined'); + } + + // 1. Let O be the result of calling toObject() passing the + // |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get() internal + // method of O with the argument "length". + // 3. Let len be toUint32(lenValue). + var len = O.length >>> 0; + + // 4. If isCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + ' is not a function'); + } + + // 5. If thisArg was supplied, let T be thisArg; else let + // T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let k be 0 + k = 0; + + // 7. Repeat, while k < len + while (k < len) { + + var kValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty + // internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal + // method of O with argument Pk. + kValue = O[k]; + + // ii. Call the Call internal method of callback with T as + // the this value and argument list containing kValue, k, and O. + callback.call(T, kValue, k, O); + } + // d. Increase k by 1. + k++; + } + // 8. return undefined + }; +} + +// Production steps of ECMA-262, Edition 5, 15.4.4.19 +// Reference: http://es5.github.io/#x15.4.4.19 +if (!Array.prototype.map) { + + Array.prototype.map = function(callback, thisArg) { + + var T, A, k; + + if (this == null) { + throw new TypeError(' this is null or not defined'); + } + + // 1. Let O be the result of calling ToObject passing the |this| + // value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal + // method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== 'function') { + throw new TypeError(callback + ' is not a function'); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let A be a new array created as if by the expression new Array(len) + // where Array is the standard built-in constructor with that name and + // len is the value of len. + A = new Array(len); + + // 7. Let k be 0 + k = 0; + + // 8. Repeat, while k < len + while (k < len) { + + var kValue, mappedValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal + // method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal + // method of O with argument Pk. + kValue = O[k]; + + // ii. Let mappedValue be the result of calling the Call internal + // method of callback with T as the this value and argument + // list containing kValue, k, and O. + mappedValue = callback.call(T, kValue, k, O); + + // iii. Call the DefineOwnProperty internal method of A with arguments + // Pk, Property Descriptor + // { Value: mappedValue, + // Writable: true, + // Enumerable: true, + // Configurable: true }, + // and false. + + // In browsers that support Object.defineProperty, use the following: + // Object.defineProperty(A, k, { + // value: mappedValue, + // writable: true, + // enumerable: true, + // configurable: true + // }); + + // For best browser support, use the following: + A[k] = mappedValue; + } + // d. Increase k by 1. + k++; + } + + // 9. return A + return A; + }; +} + +var PagedTable = function (pagedTable) { + var me = this; + + var source = function(pagedTable) { + var sourceElems = [].slice.call(pagedTable.children).filter(function(e) { + return e.hasAttribute("data-pagedtable-source"); + }); + + if (sourceElems === null || sourceElems.length !== 1) { + throw("A single data-pagedtable-source was not found"); + } + + return JSON.parse(sourceElems[0].innerHTML); + }(pagedTable); + + var options = function(source) { + var options = typeof(source.options) !== "undefined" && + source.options !== null ? source.options : {}; + + var columns = typeof(options.columns) !== "undefined" ? options.columns : {}; + var rows = typeof(options.rows) !== "undefined" ? options.rows : {}; + + var positiveIntOrNull = function(value) { + return parseInt(value) >= 0 ? parseInt(value) : null; + }; + + return { + pages: positiveIntOrNull(options.pages), + rows: { + min: positiveIntOrNull(rows.min), + max: positiveIntOrNull(rows.max), + total: positiveIntOrNull(rows.total) + }, + columns: { + min: positiveIntOrNull(columns.min), + max: positiveIntOrNull(columns.max), + total: positiveIntOrNull(columns.total) + } + }; + }(source); + + var Measurer = function() { + + // set some default initial values that will get adjusted in runtime + me.measures = { + padding: 12, + character: 8, + height: 15, + defaults: true + }; + + me.calculate = function(measuresCell) { + if (!me.measures.defaults) + return; + + var measuresCellStyle = window.getComputedStyle(measuresCell, null); + + var newPadding = parsePadding(measuresCellStyle.paddingLeft) + + parsePadding(measuresCellStyle.paddingRight); + + var sampleString = "ABCDEFGHIJ0123456789"; + var newCharacter = Math.ceil(measuresCell.clientWidth / sampleString.length); + + if (newPadding <= 0 || newCharacter <= 0) + return; + + me.measures.padding = newPadding; + me.measures.character = newCharacter; + me.measures.height = measuresCell.clientHeight; + me.measures.defaults = false; + }; + + return me; + }; + + var Page = function(data, options) { + var me = this; + + var defaults = { + max: 7, + rows: 10 + }; + + var totalPages = function() { + return Math.ceil(data.length / me.rows); + }; + + me.number = 0; + me.max = options.pages !== null ? options.pages : defaults.max; + me.visible = me.max; + me.rows = options.rows.min !== null ? options.rows.min : defaults.rows; + me.total = totalPages(); + + me.setRows = function(newRows) { + me.rows = newRows; + me.total = totalPages(); + }; + + me.setPageNumber = function(newPageNumber) { + if (newPageNumber < 0) newPageNumber = 0; + if (newPageNumber >= me.total) newPageNumber = me.total - 1; + + me.number = newPageNumber; + }; + + me.setVisiblePages = function(visiblePages) { + me.visible = Math.min(me.max, visiblePages); + me.setPageNumber(me.number); + }; + + me.getVisiblePageRange = function() { + var start = me.number - Math.max(Math.floor((me.visible - 1) / 2), 0); + var end = me.number + Math.floor(me.visible / 2) + 1; + var pageCount = me.total; + + if (start < 0) { + var diffToStart = 0 - start; + start += diffToStart; + end += diffToStart; + } + + if (end > pageCount) { + var diffToEnd = end - pageCount; + start -= diffToEnd; + end -= diffToEnd; + } + + start = start < 0 ? 0 : start; + end = end >= pageCount ? pageCount : end; + + var first = false; + var last = false; + + if (start > 0 && me.visible > 1) { + start = start + 1; + first = true; + } + + if (end < pageCount && me.visible > 2) { + end = end - 1; + last = true; + } + + return { + first: first, + start: start, + end: end, + last: last + }; + }; + + me.getRowStart = function() { + var rowStart = page.number * page.rows; + if (rowStart < 0) + rowStart = 0; + + return rowStart; + }; + + me.getRowEnd = function() { + var rowStart = me.getRowStart(); + return Math.min(rowStart + me.rows, data.length); + }; + + me.getPaddingRows = function() { + var rowStart = me.getRowStart(); + var rowEnd = me.getRowEnd(); + return data.length > me.rows ? me.rows - (rowEnd - rowStart) : 0; + }; + }; + + var Columns = function(data, columns, options) { + var me = this; + + me.defaults = { + min: 5 + }; + + me.number = 0; + me.visible = 0; + me.total = columns.length; + me.subset = []; + me.padding = 0; + me.min = options.columns.min !== null ? options.columns.min : me.defaults.min; + me.max = options.columns.max !== null ? options.columns.max : null; + me.widths = {}; + + var widthsLookAhead = Math.max(100, options.rows.min); + var paddingColChars = 10; + + me.emptyNames = function() { + columns.forEach(function(column) { + if (columns.label !== null && columns.label !== "") + return false; + }); + + return true; + }; + + var parsePadding = function(value) { + return parseInt(value) >= 0 ? parseInt(value) : 0; + }; + + me.calculateWidths = function(measures) { + columns.forEach(function(column) { + var maxChars = Math.max( + column.label.toString().length, + column.type.toString().length + ); + + for (var idxRow = 0; idxRow < Math.min(widthsLookAhead, data.length); idxRow++) { + maxChars = Math.max(maxChars, data[idxRow][column.name.toString()].length); + } + + me.widths[column.name] = { + // width in characters + chars: maxChars, + // width for the inner html columns + inner: maxChars * measures.character, + // width adding outer styles like padding + outer: maxChars * measures.character + measures.padding + }; + }); + }; + + me.getWidth = function() { + var widthOuter = 0; + for (var idxCol = 0; idxCol < me.subset.length; idxCol++) { + var columnName = me.subset[idxCol].name; + widthOuter = widthOuter + me.widths[columnName].outer; + } + + widthOuter = widthOuter + me.padding * paddingColChars * measurer.measures.character; + + if (me.hasMoreLeftColumns()) { + widthOuter = widthOuter + columnNavigationWidthPX + measurer.measures.padding; + } + + if (me.hasMoreRightColumns()) { + widthOuter = widthOuter + columnNavigationWidthPX + measurer.measures.padding; + } + + return widthOuter; + }; + + me.updateSlice = function() { + if (me.number + me.visible >= me.total) + me.number = me.total - me.visible; + + if (me.number < 0) me.number = 0; + + me.subset = columns.slice(me.number, Math.min(me.number + me.visible, me.total)); + + me.subset = me.subset.map(function(column) { + Object.keys(column).forEach(function(colKey) { + column[colKey] = column[colKey] === null ? "" : column[colKey].toString(); + }); + + column.width = null; + return column; + }); + }; + + me.setVisibleColumns = function(columnNumber, newVisibleColumns, paddingCount) { + me.number = columnNumber; + me.visible = newVisibleColumns; + me.padding = paddingCount; + + me.updateSlice(); + }; + + me.incColumnNumber = function(increment) { + me.number = me.number + increment; + }; + + me.setColumnNumber = function(newNumber) { + me.number = newNumber; + }; + + me.setPaddingCount = function(newPadding) { + me.padding = newPadding; + }; + + me.getPaddingCount = function() { + return me.padding; + }; + + me.hasMoreLeftColumns = function() { + return me.number > 0; + }; + + me.hasMoreRightColumns = function() { + return me.number + me.visible < me.total; + }; + + me.updateSlice(0); + return me; + }; + + var data = source.data; + var page = new Page(data, options); + var measurer = new Measurer(data, options); + var columns = new Columns(data, source.columns, options); + + var table = null; + var tableDiv = null; + var header = null; + var footer = null; + var tbody = null; + + // Caches pagedTable.clientWidth, specially for webkit + var cachedPagedTableClientWidth = null; + + var onChangeCallbacks = []; + + var clearSelection = function() { + if(document.selection && document.selection.empty) { + document.selection.empty(); + } else if(window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + } + }; + + var columnNavigationWidthPX = 5; + + var renderColumnNavigation = function(increment, backwards) { + var arrow = document.createElement("div"); + arrow.setAttribute("style", + "border-top: " + columnNavigationWidthPX + "px solid transparent;" + + "border-bottom: " + columnNavigationWidthPX + "px solid transparent;" + + "border-" + (backwards ? "right" : "left") + ": " + columnNavigationWidthPX + "px solid;"); + + var header = document.createElement("th"); + header.appendChild(arrow); + header.setAttribute("style", + "cursor: pointer;" + + "vertical-align: middle;" + + "min-width: " + columnNavigationWidthPX + "px;" + + "width: " + columnNavigationWidthPX + "px;"); + + header.onclick = function() { + columns.incColumnNumber(backwards ? -1 : increment); + + me.animateColumns(backwards); + renderFooter(); + + clearSelection(); + triggerOnChange(); + }; + + return header; + }; + + var maxColumnWidth = function(width) { + var padding = 80; + var columnMax = Math.max(cachedPagedTableClientWidth - padding, 0); + + return parseInt(width) > 0 ? + Math.min(columnMax, parseInt(width)) + "px" : + columnMax + "px"; + }; + + var clearHeader = function() { + var thead = pagedTable.querySelectorAll("thead")[0]; + thead.innerHTML = ""; + }; + + var renderHeader = function(clear) { + cachedPagedTableClientWidth = pagedTable.clientWidth; + + var fragment = document.createDocumentFragment(); + + header = document.createElement("tr"); + fragment.appendChild(header); + + if (columns.number > 0) + header.appendChild(renderColumnNavigation(-columns.visible, true)); + + columns.subset = columns.subset.map(function(columnData) { + var column = document.createElement("th"); + column.setAttribute("align", columnData.align); + column.style.textAlign = columnData.align; + + column.style.maxWidth = maxColumnWidth(null); + if (columnData.width) { + column.style.minWidth = + column.style.maxWidth = maxColumnWidth(columnData.width); + } + + var columnName = document.createElement("div"); + columnName.setAttribute("class", "pagedtable-header-name"); + if (columnData.label === "") { + columnName.innerHTML = " "; + } + else { + columnName.appendChild(document.createTextNode(columnData.label)); + } + column.appendChild(columnName); + + var columnType = document.createElement("div"); + columnType.setAttribute("class", "pagedtable-header-type"); + if (columnData.type === "") { + columnType.innerHTML = " "; + } + else { + columnType.appendChild(document.createTextNode("<" + columnData.type + ">")); + } + column.appendChild(columnType); + + header.appendChild(column); + + columnData.element = column; + + return columnData; + }); + + for (var idx = 0; idx < columns.getPaddingCount(); idx++) { + var paddingCol = document.createElement("th"); + paddingCol.setAttribute("class", "pagedtable-padding-col"); + header.appendChild(paddingCol); + } + + if (columns.number + columns.visible < columns.total) + header.appendChild(renderColumnNavigation(columns.visible, false)); + + if (typeof(clear) == "undefined" || clear) clearHeader(); + var thead = pagedTable.querySelectorAll("thead")[0]; + thead.appendChild(fragment); + }; + + me.animateColumns = function(backwards) { + var thead = pagedTable.querySelectorAll("thead")[0]; + + var headerOld = thead.querySelectorAll("tr")[0]; + var tbodyOld = table.querySelectorAll("tbody")[0]; + + me.fitColumns(backwards); + + renderHeader(false); + + header.style.opacity = "0"; + header.style.transform = backwards ? "translateX(-30px)" : "translateX(30px)"; + header.style.transition = "transform 200ms linear, opacity 200ms"; + header.style.transitionDelay = "0"; + + renderBody(false); + + if (headerOld) { + headerOld.style.position = "absolute"; + headerOld.style.transform = "translateX(0px)"; + headerOld.style.opacity = "1"; + headerOld.style.transition = "transform 100ms linear, opacity 100ms"; + headerOld.setAttribute("class", "pagedtable-remove-head"); + if (headerOld.style.transitionEnd) { + headerOld.addEventListener("transitionend", function() { + var headerOldByClass = thead.querySelector(".pagedtable-remove-head"); + if (headerOldByClass) thead.removeChild(headerOldByClass); + }); + } + else { + thead.removeChild(headerOld); + } + } + + if (tbodyOld) table.removeChild(tbodyOld); + + tbody.style.opacity = "0"; + tbody.style.transition = "transform 200ms linear, opacity 200ms"; + tbody.style.transitionDelay = "0ms"; + + // force relayout + window.getComputedStyle(header).opacity; + window.getComputedStyle(tbody).opacity; + + if (headerOld) { + headerOld.style.transform = backwards ? "translateX(20px)" : "translateX(-30px)"; + headerOld.style.opacity = "0"; + } + + header.style.transform = "translateX(0px)"; + header.style.opacity = "1"; + + tbody.style.opacity = "1"; + } + + me.onChange = function(callback) { + onChangeCallbacks.push(callback); + }; + + var triggerOnChange = function() { + onChangeCallbacks.forEach(function(onChange) { + onChange(); + }); + }; + + var clearBody = function() { + if (tbody) { + table.removeChild(tbody); + tbody = null; + } + }; + + var renderBody = function(clear) { + cachedPagedTableClientWidth = pagedTable.clientWidth + + var fragment = document.createDocumentFragment(); + + var pageData = data.slice(page.getRowStart(), page.getRowEnd()); + + pageData.forEach(function(dataRow, idxRow) { + var htmlRow = document.createElement("tr"); + htmlRow.setAttribute("class", (idxRow % 2 !==0) ? "even" : "odd"); + + if (columns.hasMoreLeftColumns()) + htmlRow.appendChild(document.createElement("td")); + + columns.subset.forEach(function(columnData) { + var cellName = columnData.name; + var dataCell = dataRow[cellName]; + var htmlCell = document.createElement("td"); + + if (dataCell === "NA") htmlCell.setAttribute("class", "pagedtable-na-cell"); + if (dataCell === "__NA__") dataCell = "NA"; + + var cellText = document.createTextNode(dataCell); + htmlCell.appendChild(cellText); + if (dataCell.length > 50) { + htmlCell.setAttribute("title", dataCell); + } + htmlCell.setAttribute("align", columnData.align); + htmlCell.style.textAlign = columnData.align; + htmlCell.style.maxWidth = maxColumnWidth(null); + if (columnData.width) { + htmlCell.style.minWidth = htmlCell.style.maxWidth = maxColumnWidth(columnData.width); + } + htmlRow.appendChild(htmlCell); + }); + + for (var idx = 0; idx < columns.getPaddingCount(); idx++) { + var paddingCol = document.createElement("td"); + paddingCol.setAttribute("class", "pagedtable-padding-col"); + htmlRow.appendChild(paddingCol); + } + + if (columns.hasMoreRightColumns()) + htmlRow.appendChild(document.createElement("td")); + + fragment.appendChild(htmlRow); + }); + + for (var idxPadding = 0; idxPadding < page.getPaddingRows(); idxPadding++) { + var paddingRow = document.createElement("tr"); + + var paddingCellRow = document.createElement("td"); + paddingCellRow.innerHTML = " "; + paddingCellRow.setAttribute("colspan", "100%"); + paddingRow.appendChild(paddingCellRow); + + fragment.appendChild(paddingRow); + } + + if (typeof(clear) == "undefined" || clear) clearBody(); + tbody = document.createElement("tbody"); + tbody.appendChild(fragment); + + table.appendChild(tbody); + }; + + var getLabelInfo = function() { + var pageStart = page.getRowStart(); + var pageEnd = page.getRowEnd(); + var totalRows = data.length; + + var totalRowsLabel = options.rows.total ? options.rows.total : totalRows; + var totalRowsLabelFormat = totalRowsLabel.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,'); + + var infoText = (pageStart + 1) + "-" + pageEnd + " of " + totalRowsLabelFormat + " rows"; + if (totalRows < page.rows) { + infoText = totalRowsLabel + " row" + (totalRows != 1 ? "s" : ""); + } + if (columns.total > columns.visible) { + var totalColumnsLabel = options.columns.total ? options.columns.total : columns.total; + + infoText = infoText + " | " + (columns.number + 1) + "-" + + (Math.min(columns.number + columns.visible, columns.total)) + + " of " + totalColumnsLabel + " columns"; + } + + return infoText; + }; + + var clearFooter = function() { + footer = pagedTable.querySelectorAll("div.pagedtable-footer")[0]; + footer.innerHTML = ""; + + return footer; + }; + + var createPageLink = function(idxPage) { + var pageLink = document.createElement("a"); + pageLinkClass = idxPage === page.number ? "pagedtable-index pagedtable-index-current" : "pagedtable-index"; + pageLink.setAttribute("class", pageLinkClass); + pageLink.setAttribute("data-page-index", idxPage); + pageLink.onclick = function() { + page.setPageNumber(parseInt(this.getAttribute("data-page-index"))); + renderBody(); + renderFooter(); + + triggerOnChange(); + }; + + pageLink.appendChild(document.createTextNode(idxPage + 1)); + + return pageLink; + } + + var renderFooter = function() { + footer = clearFooter(); + + var next = document.createElement("a"); + next.appendChild(document.createTextNode("Next")); + next.onclick = function() { + page.setPageNumber(page.number + 1); + renderBody(); + renderFooter(); + + triggerOnChange(); + }; + if (data.length > page.rows) footer.appendChild(next); + + var pageNumbers = document.createElement("div"); + pageNumbers.setAttribute("class", "pagedtable-indexes"); + + var pageRange = page.getVisiblePageRange(); + + if (pageRange.first) { + var pageLink = createPageLink(0); + pageNumbers.appendChild(pageLink); + + var pageSeparator = document.createElement("div"); + pageSeparator.setAttribute("class", "pagedtable-index-separator-left"); + pageSeparator.appendChild(document.createTextNode("...")) + pageNumbers.appendChild(pageSeparator); + } + + for (var idxPage = pageRange.start; idxPage < pageRange.end; idxPage++) { + var pageLink = createPageLink(idxPage); + + pageNumbers.appendChild(pageLink); + } + + if (pageRange.last) { + var pageSeparator = document.createElement("div"); + pageSeparator.setAttribute("class", "pagedtable-index-separator-right"); + pageSeparator.appendChild(document.createTextNode("...")) + pageNumbers.appendChild(pageSeparator); + + var pageLink = createPageLink(page.total - 1); + pageNumbers.appendChild(pageLink); + } + + if (data.length > page.rows) footer.appendChild(pageNumbers); + + var previous = document.createElement("a"); + previous.appendChild(document.createTextNode("Previous")); + previous.onclick = function() { + page.setPageNumber(page.number - 1); + renderBody(); + renderFooter(); + + triggerOnChange(); + }; + if (data.length > page.rows) footer.appendChild(previous); + + var infoLabel = document.createElement("div"); + infoLabel.setAttribute("class", "pagedtable-info"); + infoLabel.setAttribute("title", getLabelInfo()); + infoLabel.appendChild(document.createTextNode(getLabelInfo())); + footer.appendChild(infoLabel); + + var enabledClass = "pagedtable-index-nav"; + var disabledClass = "pagedtable-index-nav pagedtable-index-nav-disabled"; + previous.setAttribute("class", page.number <= 0 ? disabledClass : enabledClass); + next.setAttribute("class", (page.number + 1) * page.rows >= data.length ? disabledClass : enabledClass); + }; + + var measuresCell = null; + + var renderMeasures = function() { + var measuresTable = document.createElement("table"); + measuresTable.style.visibility = "hidden"; + measuresTable.style.position = "absolute"; + measuresTable.style.whiteSpace = "nowrap"; + measuresTable.style.height = "auto"; + measuresTable.style.width = "auto"; + + var measuresRow = document.createElement("tr"); + measuresTable.appendChild(measuresRow); + + measuresCell = document.createElement("td"); + var sampleString = "ABCDEFGHIJ0123456789"; + measuresCell.appendChild(document.createTextNode(sampleString)); + + measuresRow.appendChild(measuresCell); + + tableDiv.appendChild(measuresTable); + } + + me.init = function() { + tableDiv = document.createElement("div"); + pagedTable.appendChild(tableDiv); + var pagedTableClass = data.length > 0 ? + "pagedtable pagedtable-not-empty" : + "pagedtable pagedtable-empty"; + + if (columns.total == 0 || (columns.emptyNames() && data.length == 0)) { + pagedTableClass = pagedTableClass + " pagedtable-empty-columns"; + } + + tableDiv.setAttribute("class", pagedTableClass); + + renderMeasures(); + measurer.calculate(measuresCell); + columns.calculateWidths(measurer.measures); + + table = document.createElement("table"); + table.setAttribute("cellspacing", "0"); + table.setAttribute("class", "table table-condensed"); + tableDiv.appendChild(table); + + table.appendChild(document.createElement("thead")); + + var footerDiv = document.createElement("div"); + footerDiv.setAttribute("class", "pagedtable-footer"); + tableDiv.appendChild(footerDiv); + + // if the host has not yet provided horizontal space, render hidden + if (tableDiv.clientWidth <= 0) { + tableDiv.style.opacity = "0"; + } + + me.render(); + + // retry seizing columns later if the host has not provided space + function retryFit() { + if (tableDiv.clientWidth <= 0) { + setTimeout(retryFit, 100); + } else { + me.render(); + triggerOnChange(); + } + } + if (tableDiv.clientWidth <= 0) { + retryFit(); + } + }; + + var registerWidths = function() { + columns.subset = columns.subset.map(function(column) { + column.width = columns.widths[column.name].inner; + return column; + }); + }; + + var parsePadding = function(value) { + return parseInt(value) >= 0 ? parseInt(value) : 0; + }; + + me.fixedHeight = function() { + return options.rows.max != null; + } + + me.fitRows = function() { + if (me.fixedHeight()) + return; + + measurer.calculate(measuresCell); + + var rows = options.rows.min !== null ? options.rows.min : 0; + var headerHeight = header !== null && header.offsetHeight > 0 ? header.offsetHeight : 0; + var footerHeight = footer !== null && footer.offsetHeight > 0 ? footer.offsetHeight : 0; + + if (pagedTable.offsetHeight > 0) { + var availableHeight = pagedTable.offsetHeight - headerHeight - footerHeight; + rows = Math.floor((availableHeight) / measurer.measures.height); + } + + rows = options.rows.min !== null ? Math.max(options.rows.min, rows) : rows; + + page.setRows(rows); + } + + // The goal of this function is to add as many columns as possible + // starting from left-to-right, when the right most limit is reached + // it tries to add columns from the left as well. + // + // When startBackwards is true columns are added from right-to-left + me.fitColumns = function(startBackwards) { + measurer.calculate(measuresCell); + columns.calculateWidths(measurer.measures); + + if (tableDiv.clientWidth > 0) { + tableDiv.style.opacity = 1; + } + + var visibleColumns = tableDiv.clientWidth <= 0 ? Math.max(columns.min, 1) : 1; + var columnNumber = columns.number; + var paddingCount = 0; + + // track a list of added columns as we build the visible ones to allow us + // to remove columns when they don't fit anymore. + var columnHistory = []; + + var lastTableHeight = 0; + var backwards = startBackwards; + + var tableDivStyle = window.getComputedStyle(tableDiv, null); + var tableDivPadding = parsePadding(tableDivStyle.paddingLeft) + + parsePadding(tableDivStyle.paddingRight); + + var addPaddingCol = false; + var currentWidth = 0; + + while (true) { + columns.setVisibleColumns(columnNumber, visibleColumns, paddingCount); + currentWidth = columns.getWidth(); + + if (tableDiv.clientWidth - tableDivPadding < currentWidth) { + break; + } + + columnHistory.push({ + columnNumber: columnNumber, + visibleColumns: visibleColumns, + paddingCount: paddingCount + }); + + if (columnHistory.length > 100) { + console.error("More than 100 tries to fit columns, aborting"); + break; + } + + if (columns.max !== null && + columns.visible + columns.getPaddingCount() >= columns.max) { + break; + } + + // if we run out of right-columns + if (!backwards && columnNumber + columns.visible >= columns.total) { + // if we started adding right-columns, try adding left-columns + if (!startBackwards && columnNumber > 0) { + backwards = true; + } + else if (columns.min === null || visibleColumns + columns.getPaddingCount() >= columns.min) { + break; + } + else { + paddingCount = paddingCount + 1; + } + } + + // if we run out of left-columns + if (backwards && columnNumber == 0) { + // if we started adding left-columns, try adding right-columns + if (startBackwards && columnNumber + columns.visible < columns.total) { + backwards = false; + } + else if (columns.min === null || visibleColumns + columns.getPaddingCount() >= columns.min) { + break; + } + else { + paddingCount = paddingCount + 1; + } + } + + // when moving backwards try fitting left columns first + if (backwards && columnNumber > 0) { + columnNumber = columnNumber - 1; + } + + if (columnNumber + visibleColumns < columns.total) { + visibleColumns = visibleColumns + 1; + } + } + + var lastRenderableColumn = { + columnNumber: columnNumber, + visibleColumns: visibleColumns, + paddingCount: paddingCount + }; + + if (columnHistory.length > 0) { + lastRenderableColumn = columnHistory[columnHistory.length - 1]; + } + + columns.setVisibleColumns( + lastRenderableColumn.columnNumber, + lastRenderableColumn.visibleColumns, + lastRenderableColumn.paddingCount); + + if (pagedTable.offsetWidth > 0) { + page.setVisiblePages(Math.max(Math.ceil(1.0 * (pagedTable.offsetWidth - 250) / 40), 2)); + } + + registerWidths(); + }; + + me.fit = function(startBackwards) { + me.fitRows(); + me.fitColumns(startBackwards); + } + + me.render = function() { + me.fitColumns(false); + + // render header/footer to measure height accurately + renderHeader(); + renderFooter(); + + me.fitRows(); + renderBody(); + + // re-render footer to match new rows + renderFooter(); + } + + var resizeLastWidth = -1; + var resizeLastHeight = -1; + var resizeNewWidth = -1; + var resizeNewHeight = -1; + var resizePending = false; + + me.resize = function(newWidth, newHeight) { + + function resizeDelayed() { + resizePending = false; + + if ( + (resizeNewWidth !== resizeLastWidth) || + (!me.fixedHeight() && resizeNewHeight !== resizeLastHeight) + ) { + resizeLastWidth = resizeNewWidth; + resizeLastHeight = resizeNewHeight; + + setTimeout(resizeDelayed, 200); + resizePending = true; + } else { + me.render(); + triggerOnChange(); + + resizeLastWidth = -1; + resizeLastHeight = -1; + } + } + + resizeNewWidth = newWidth; + resizeNewHeight = newHeight; + + if (!resizePending) resizeDelayed(); + }; +}; + +var PagedTableDoc; +(function (PagedTableDoc) { + var allPagedTables = []; + + PagedTableDoc.initAll = function() { + allPagedTables = []; + + var pagedTables = [].slice.call(document.querySelectorAll('[data-pagedtable="false"],[data-pagedtable=""]')); + pagedTables.forEach(function(pagedTable, idx) { + pagedTable.setAttribute("data-pagedtable", "true"); + pagedTable.setAttribute("pagedtable-page", 0); + pagedTable.setAttribute("class", "pagedtable-wrapper"); + + var pagedTableInstance = new PagedTable(pagedTable); + pagedTableInstance.init(); + + allPagedTables.push(pagedTableInstance); + }); + }; + + PagedTableDoc.resizeAll = function() { + allPagedTables.forEach(function(pagedTable) { + pagedTable.render(); + }); + }; + + window.addEventListener("resize", PagedTableDoc.resizeAll); + + return PagedTableDoc; +})(PagedTableDoc || (PagedTableDoc = {})); + +window.onload = function() { + PagedTableDoc.initAll(); +}; diff --git a/articles/img/batch_correction.svg b/articles/img/batch_correction.svg new file mode 100644 index 0000000..40112cf --- /dev/null +++ b/articles/img/batch_correction.svg @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/articles/img/bio_conservation.svg b/articles/img/bio_conservation.svg new file mode 100644 index 0000000..bdf7044 --- /dev/null +++ b/articles/img/bio_conservation.svg @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/articles/img/cell_cluster.svg b/articles/img/cell_cluster.svg new file mode 100644 index 0000000..ea52377 --- /dev/null +++ b/articles/img/cell_cluster.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + diff --git a/articles/img/cell_type.svg b/articles/img/cell_type.svg new file mode 100644 index 0000000..638c988 --- /dev/null +++ b/articles/img/cell_type.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + diff --git a/articles/img/conda_envs_bbknn.png b/articles/img/conda_envs_bbknn.png new file mode 100644 index 0000000..ec89c51 Binary files /dev/null and b/articles/img/conda_envs_bbknn.png differ diff --git a/articles/img/conda_envs_set.png b/articles/img/conda_envs_set.png new file mode 100644 index 0000000..ff012c3 Binary files /dev/null and b/articles/img/conda_envs_set.png differ diff --git a/articles/img/conda_envs_unset.png b/articles/img/conda_envs_unset.png new file mode 100644 index 0000000..2605856 Binary files /dev/null and b/articles/img/conda_envs_unset.png differ diff --git a/articles/img/embedding.svg b/articles/img/embedding.svg new file mode 100644 index 0000000..514311b --- /dev/null +++ b/articles/img/embedding.svg @@ -0,0 +1,1039 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/articles/img/logo_Python.svg b/articles/img/logo_Python.svg new file mode 100644 index 0000000..269bbea --- /dev/null +++ b/articles/img/logo_Python.svg @@ -0,0 +1,265 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/articles/img/logo_R.svg b/articles/img/logo_R.svg new file mode 100644 index 0000000..1fa3ba6 --- /dev/null +++ b/articles/img/logo_R.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/articles/img/network.svg b/articles/img/network.svg new file mode 100644 index 0000000..8692093 --- /dev/null +++ b/articles/img/network.svg @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/articles/index.html b/articles/index.html new file mode 100644 index 0000000..a7b91f3 --- /dev/null +++ b/articles/index.html @@ -0,0 +1,76 @@ + +Articles • SeuratIntegrate + Skip to contents + + +
+
+
+ + +
+ + +
+ + + + + + + diff --git a/articles/introduction.html b/articles/introduction.html new file mode 100644 index 0000000..9dd7d12 --- /dev/null +++ b/articles/introduction.html @@ -0,0 +1,951 @@ + + + + + + + +Integration example with of the pbmcsca data • SeuratIntegrate + + + + + + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + + + +
+

Install and load the data +

+

We will use the pbmcsca dataset available from the +package SeuratData.

+
+# install `SeuratData` package (if not yet)
+if (! requireNamespace("SeuratData", quietly = TRUE)) {
+  devtools::install_github('satijalab/seurat-data')
+}
+
+# increase download timeout and install the dataset
+options(timeout = 300)
+SeuratData::InstallData('pbmcsca')
+
+# load the dataset (take 1,000 first cells to speed-up execution)
+seu <- SeuratData::LoadData('pbmcsca')[,1:1e3]
+
## Warning: Assay RNA changing from Assay to Assay
+
## Warning: Assay RNA changing from Assay to Assay5
+
+
+

Inspect the dataset +

+

Have a look at the metadata:

+
+# rmarkdown::paged_table -> prints data frames in a less ugly way than default
+rmarkdown::paged_table(head(seu[[]], n = 10))
+
+ +
+

The column Method provides information about the +single-cell technology used to acquire each cell’s trancriptome. We +consider it as the batch of origin.

+
+table(seu$Method)
+
## 
+## 10x Chromium (v2) A            CEL-Seq2          Smart-seq2 
+##                 494                 253                 253
+

The column CellType contains cell-types annotation that +we will use later on.

+
+rmarkdown::paged_table(as.data.frame(table(seu$CellType)))
+
+ +
+

Let’s now define the batch variable and the cell-type +variable(s):

+
+batch.var <- 'Method'   # available in the metadata of the object
+cell.var <- 'CellType'  # available in the metadata of the object
+
+
+

Seurat data processing - Standard workflow +

+

The current Seurat object is not split, meaning that each layer +contains cells from all batches.

+
+cat('Layers before split:', paste(Layers(seu), collapse = ", "), '\n')
+
## Layers before split: counts, data
+

We select the column Method to separate the cells into +batch-specific layers. This step is indispensable to run integration +methods and enables to normalise each batch (i.e. layer) +independently.

+
+seu[['RNA']] <- split(seu[['RNA']], f = seu$Method)
+
+cat('Layers after split:', paste(Layers(seu), collapse = ", "), '\n')
+
## Layers after split: counts.Smart-seq2, counts.CEL-Seq2, counts.10x_Chromium_v2_A, data.Smart-seq2, data.CEL-Seq2, data.10x_Chromium_v2_A
+

Then, we proceed to the standard Seurat workflow until +we obtain the PCA reduction.

+

+
+seu <- SCTransform(seu)
+seu <- RunPCA(seu, verbose = F)
+seu <- FindNeighbors(seu, reduction = "pca", dims = 1:30, k.param = 20L)
+

We now further process the object until we can visualise the +dispersion of cells on a UMAP dimension reduction.

+
+seu <- FindClusters(seu, graph.name = 'SCT_snn', resolution = .5)
+seu <- RunUMAP(seu, dims = 1:30, reduction = 'pca')
+
## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
+## 
+## Number of nodes: 1000
+## Number of edges: 43767
+## 
+## Running Louvain algorithm...
+## Maximum modularity in 10 random starts: 0.8715
+## Number of communities: 8
+## Elapsed time: 0 seconds
+
+DimPlot(seu, label = T) + NoLegend() + ggplot2::coord_fixed(ratio = .7)
+

UMAP of unintegrated pbmcsca data with cells colored by cluster

+

Let’s colour cells according to batch and cell-type label.

+
+DimPlot(seu, group.by = batch.var) +
+  DimPlot(seu, group.by = cell.var) & ggplot2::coord_fixed(ratio = .7)
+

UMAP of unintegrated pbmcsca data with cells colored by sequencing method (i.e. batch) and cell type label

+

Albeit moderately, the dispersion of cells on the UMAP seems to be +influenced by a batch effect. According to the “CellType” variable, B +cells from 10x and CEL-Seq2 are not gathered together and monocyte cells +do not fully overlap.

+

Now, we want to correct these technical differences.

+
+
+

Integrate batches - SeuratIntegrate workflow +

+

The integration commands are to some extent similar to the Seurat +V5 vignette. The purpose of this package is to extend the set of +available integration methods. See the bottom of +?IntegrateLayers to have a comprehensive list of relevant +methods.

+

Many methods supported by SeuratIntegrate are implemented in Python, +and the wrappers provided rely on the reticulate package +and conda environments. If you are not familiar with the +CondaEnvManager, have a look at the +vignette("setup_and_tips").

+

Here are some important considerations before performing an +integration:

+
    +
  • use the interface DoIntegrate() from SeuratIntegrate to +integrate the cell batches (see the next section)
  • +
  • check the method-specific arguments +(e.g. ?bbknnIntegration)
  • +
  • set up conda environments to use Python-based methods: +
      +
    • with the CondaEnvManager via +UpdateEnvCache() (check the +vignette("setup_and_tips"))
    • +
    • with a custom conda environment by passing its path - or its name - +to the conda_env parameter. This overrides the default +behaviour by loading the specified environment instead of fetching the +CondaEnvManager’s cache.
    • +
    +
  • +
+

Some methods expect a raw count matrix, others expect the scaled +counts of the variable features, etc. To help you with the choice, look +at the table below

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodLayerFeatures
ComBatdataany but better with restricted number of features +(e.g. variable)
HarmonyN/A (PCA reduction)N/A (PCA reduction)
MNNdataany but better with restricted number of features +(e.g. variable)
bbknnN/A (PCA reduction)N/A (PCA reduction)
scVI / scANVIcountsall
Scanoramacounts or dataany
trVAE +

data (recon loss “mse”)

+

counts (otherwise)

+
all
+

Layers:

+
    +
  • counts: raw counts
  • +
  • data: normalised counts
  • +
  • scale.data: scaled normalised counts of variable features
  • +
+


/!\ IMPORTANT /!\ To use +all features when calling an integration method with +IntegrateLayers(): +IntegrateLayers(object, features = Features(object), scale.layer = NULL). +Does not work for a SCTAssay.

+
+

DoIntegrate philosophy (#do_integrate) +

+

The function DoIntegrate() is a very handy way to run +multiple integrations in a single command. Note that:

+
    +
  • +... is the place to specify the integration commands to +run.
  • +
  • integration commands are expected to be function +calls, i.e. of the form FooIntegration(), +BarIntegration(), etc.
  • +
  • Calls accept method-specific argument (e.g. +FooIntegration(layers = "data"))
  • +
  • +use.hvg = TRUE results in using variable features
  • +
  • +use.future = TRUE is useful to run Python-based methods +(a normal R session cannot load more than one conda instance, while +future enables to launch background sessions, preventing +the main on to load any conda environment.). It is highly +recommended to set it to FALSE for R-based +methods.
  • +
+

Most integration methods can be used without modifying default +parameters. In this vignette, we will change some arguments to meet our +needs. Notably, we will change the number of cores allocated to each +method (where possible).

+
+ncores <- parallel::detectCores() - 2
+

In this vignette, we are going to use 3 Python-based methods, namely +BBKNN, Scanorama and scANVI from the +scvi-tools suite. Let’s make sure they are available straight away:

+
+# BBKNN
+if (! isValid(getCache()$bbknn)) {
+  UpdateEnvCache("bbknn")
+}
+# Scanorama
+if (! isValid(getCache()$scanorama)) {
+  UpdateEnvCache("scanorama")
+}
+# scvi-tools
+if (! isValid(getCache()$scanvi)) {
+  UpdateEnvCache("scanvi")
+}
+


Let’s proceed to a few batch-effect corrections:

+
+
+

Integration part 1) Using R-based methods +

+
+seu <- DoIntegrate(
+  object = seu,
+  SeuratIntegrate::HarmonyIntegration(orig = "pca", dims = 1:30,
+                                      ncores = ncores),
+  CCAIntegration(orig = "pca", dims = 1:30 , new.reduction = "cca.integrated",
+                 normalization.method = "SCT"),
+  RPCAIntegration(orig = "pca", dims = 1:30, new.reduction = "rpca.integrated",
+                  normalization.method = "SCT"),
+  use.future = FALSE  # R-based
+)
+
## Integration 1 in 3: integrating using 'SeuratIntegrate::HarmonyIntegration'
+## Integration 2 in 3: integrating using 'CCAIntegration'
+## Integration 3 in 3: integrating using 'RPCAIntegration'
+

Note: We use SeuratIntegrate:: before +HarmonyIntegration to avoid any confusion with +Seurat::HarmonyIntegration().

+
+
+

Integration part 2) Using python-based methods +

+
+seu <- DoIntegrate(
+  object = seu,
+  bbknnIntegration(orig = "pca", layers = "data", ndims = 30),
+  ScanoramaIntegration(orig = "pca", ncores = ncores),
+  scANVIIntegration(groups = seu[[]], groups.name = "Method",
+                    labels.name = "CellType", layers = "counts",
+                    torch.intraop.threads = ncores,
+                    torch.interop.threads = ncores,
+                    max_epochs = 20L),
+  use.future = TRUE,  # Python-based
+  use.hvg = c(TRUE, TRUE, FALSE)
+)
+
## Integration 1 in 3: integrating using 'bbknnIntegration'
+## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
+## 
+## Number of nodes: 1000
+## Number of edges: 6866
+## 
+## Running Louvain algorithm...
+## Maximum modularity in 10 random starts: 0.6812
+## Number of communities: 10
+## Elapsed time: 0 seconds
+## Integration 2 in 3: integrating using 'ScanoramaIntegration'
+## Integration 3 in 3: integrating using 'scANVIIntegration'
+
+

Note: set max_epochs = 20L for +scANVIIntegration is only to save time ! The default number +of epochs (400) results in a superior integration.

+
+

If we take a look at our Seurat object, we can note that it has been +enriched with many objects:

+
+print(seu)
+
## An object of class Seurat 
+## 69594 features across 1000 samples within 4 assays 
+## Active assay: SCT (16450 features, 3000 variable features)
+##  3 layers present: counts, data, scale.data
+##  3 other assays present: RNA, bbknn.ridge, scanorama.reconstructed
+##  8 dimensional reductions calculated: pca, umap, harmony, cca.integrated, rpca.integrated, pca.bbknn, integrated.scanorama, integrated.scANVI
+
+cat("Graph objects:", paste(Graphs(seu), collapse = ", "), "\n")
+cat("Neighbor objects:", paste(Neighbors(seu), collapse = ", "), "\n")
+cat("Reduction dimensions:", paste(Reductions(seu), collapse = ", "), "\n")
+cat("Assays:", paste(Assays(seu), collapse = ", "), "\n")
+
## Graph objects: SCT_nn, SCT_snn, bbknn_scale.data_connectivities, bbknn_scale.data_distances, bbknn_ridge.residuals_connectivities, bbknn_ridge.residuals_distances 
+## Neighbor objects:  
+## Reduction dimensions: pca, umap, harmony, cca.integrated, rpca.integrated, pca.bbknn, integrated.scanorama, integrated.scANVI 
+## Assays: RNA, SCT, bbknn.ridge, scanorama.reconstructed
+

Great! We have successfully performed several integrations! However, +stopping here would be unsatisfactory because we still need to process +each integration’s output(s) to obtain at least one UMAP projection for +each. Here, we will also aim at generating assessable representations to +score.

+
+
+
+

Score integrations +

+
+

Process outputs +

+

Several objects can be produced by each integration algorithm, namely +a layer in a new assay (i.e. corrected counts), a dimension reduction +(corrected embedding), or a knn network. Some even produce more than one +output (for instance Scanorama produces corrected counts and a dimension +reduction).

+

The type of output is important to consider, because scoring metrics +are not compatible with all output types. The simplest strategy is to +process each output separately in order to obtain at least a PCA out of +it, or even a knn graph (essential to compute clusters). Note that most +scores cannot be computed on knn graphs, hence knn graph outputs +(e.g. BBKNN) can only be evaluated by a reduced set of metrics.

+

Below is a summary of post-processing steps for each output type +(bracketed steps are not always necessary):

+ +

RunPCA() is sometimes run even on dimension reduction +objects (within scoring functions) because some scores require a +variance associated with each dimension.

+

Let’s process all the outputs. Here, we will go through all the steps +for a more exhaustive demonstration. However, it is to be noted that +skipping the final step FindOptimalClusters() makes the +neighbour graph computation step (FindNeighbors()) +unnecessary. In such a case however, one will forgo two scoring metrics, +namely ARI and NMI.

+

Here, we will use SymmetrizeKnn() between +FindNeighbors() and FindOptimalClusters() +because we set return.neighbor = TRUE in +FindNeighbors(). This is useful to keep the distances +between cells in the KNN graph rather than what +FindNeighbors() does by default, which is converting the +KNN graph to an adjacency matrix with 0/1s and to a +SNN network with values bounded between 0 and 1. This not +compulsory, but this is used to stay in line with BBKNN’s output. To +prevent the community detection algorithm to output a high fraction of +singletons, we “symmetrize” the matrix which makes the graph +“undirected”.

+
+# corrected counts outputs
+DefaultAssay(seu) <- "scanorama.reconstructed"
+seu <- ScaleData(seu)
+seu <- RunPCA(seu, npcs = 50L, reduction.name = "pca.scanorama_counts")
+seu <- FindNeighbors(seu, reduction = "pca.scanorama_counts", dims = 1:30, return.neighbor = TRUE,
+                     graph.name = "knn.scanorama_counts")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.scanorama_counts")
+seu <- FindOptimalClusters(seu, graph.name = "knn.scanorama_counts_symmetric",
+                           cluster.name = "scanorama_counts_{cell.var}_{metric}",
+                           cell.var = cell.var,
+                           optimisation.metric = c("nmi", "ari")) # default, compute both
+
+
+# dimension reduction outputs
+DefaultAssay(seu) <- "SCT"
+seu <- FindNeighbors(seu, reduction = "pca", dims = 1:30, k.param = 20L,
+                     return.neighbor = TRUE, graph.name = "knn.unintegrated")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.unintegrated")
+seu <- FindOptimalClusters(seu, graph.name = "knn.unintegrated_symmetric",
+                           cluster.name = "unintegrated_{cell.var}_{metric}",
+                           cell.var = cell.var)
+
+seu <- FindNeighbors(seu, reduction = "integrated.scanorama", dims = 1:30,
+                     return.neighbor = TRUE, graph.name = "knn.scanorama_reduction")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.scanorama_reduction")
+seu <- FindOptimalClusters(seu, graph.name = "knn.scanorama_reduction_symmetric",
+                           cluster.name = "scanorama_reduction_{cell.var}_{metric}",
+                           cell.var = cell.var)
+
+seu <- FindNeighbors(seu, reduction = "harmony", dims = 1:30,
+                     return.neighbor = TRUE, graph.name = "knn.harmony")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.harmony")
+seu <- FindOptimalClusters(seu, graph.name = "knn.harmony_symmetric", cell.var = cell.var,
+                           cluster.name = "harmony_{cell.var}_{metric}")
+
+seu <- FindNeighbors(seu, reduction = "cca.integrated", dims = 1:30,
+                     return.neighbor = TRUE, graph.name = "knn.cca")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.cca")
+seu <- FindOptimalClusters(seu, graph.name = "knn.cca_symmetric", cell.var = cell.var,
+                           cluster.name = "cca_{cell.var}_{metric}")
+
+seu <- FindNeighbors(seu, reduction = "rpca.integrated", dims = 1:30,
+                     return.neighbor = TRUE, graph.name = "knn.rpca")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.rpca")
+seu <- FindOptimalClusters(seu, graph.name = "knn.rpca_symmetric", cell.var = cell.var,
+                           cluster.name = "rpca_{cell.var}_{metric}")
+
+seu <- FindNeighbors(seu, reduction = "integrated.scANVI",
+                     return.neighbor = TRUE, graph.name = "knn.scanvi")
+seu <- SymmetrizeKnn(seu, graph.name = "knn.scanvi")
+seu <- FindOptimalClusters(seu, graph.name = "knn.scanvi_symmetric", cell.var = cell.var,
+                           cluster.name = "scanvi_{cell.var}_{metric}")
+
+
+# graph outputs
+seu <- SymmetrizeKnn(seu, graph.name = "bbknn_ridge.residuals_distances")
+seu <- FindOptimalClusters(seu, graph.name = "bbknn_ridge.residuals_distances_symmetric",
+                           cell.var = cell.var, cluster.name = "bbknn_{cell.var}_{metric}")
+
+

Note: Instead of sticking with the default +FindNeighbors(return.neighbors = FALSE) at the beginning, we could have switched it to +TRUE right away, process the KNN graph with +SymmetrizeKnn() and use it for subsequent steps (umap, +clustering, etc.)

+
+

FindOptimalClusters() adds metadata columns with the +clustering results that maximized a metric (NMI or ARI) to the Seurat +object:

+
+rmarkdown::paged_table(seu[[]][1:10, grep("CellType_[arinm]{3}$", colnames(seu[[]]))])
+
+ +
+
+
+

Add scores to the Seurat object +

+

Now that we have computed objects ready to be scored, we will proceed +with assessing each integration output. For this step, one can either +use Score[score_name]() and save scores in separate +variables or use AddScore[score_name]() to directly store +scores within the Seurat object. The latter is far more convenient and +allows to compare scores graphically. This is the strategy we are going +to adopt here.

+

Last but not least, a cell-type variable is used in most scores, +hence it is highly recommended to have an estimate of each cell’s type +(or produce such an estimate) stored in the Seurat object as a column in +the metadata.

+
+

Note that if one doesn’t have a variable with cell-labels (used as +ground truth in multiple scores) he will have to produce it or do +without several scores. Alternatively, one can use automatic cell +annotation algorithms (e.g. the Azimuth package). One +can also have multiple cell label variables (e.g. Azimuth typically +returns as many cell label variables as levels of annotations contained +in the reference). Scores requiring cell type annotations always accept +multiple column names.

+
+
+

There is a risk of confusion between cell annotations when using +automatic cell annotation tools. Furthermore, in the case of using +Azimuth to annotate cells, there is a specific risk of biasing results +by favouring RPCA integration because Azimuth uses RPCA to integrate the +query dataset onto the reference.

+
+

First of all, let’s organise outputs in lists:

+
+reductions <- list(
+  unintegrated = "pca",
+  scanorama_counts = "pca.scanorama_counts",
+  scanorama_reduction = "integrated.scanorama",
+  harmony = "harmony",
+  cca = "cca.integrated",
+  rpca = "rpca.integrated",
+  scanvi = "integrated.scANVI",
+  bbknn = NULL
+)
+
+graphs <- list(
+  unintegrated = "knn.unintegrated_symmetric",
+  scanorama_counts = "knn.scanorama_counts_symmetric",
+  scanorama_reduction = "knn.scanorama_reduction_symmetric",
+  harmony = "knn.harmony_symmetric",
+  cca = "knn.cca_symmetric",
+  rpca = "knn.rpca_symmetric",
+  scanvi = "knn.scanvi_symmetric",
+  bbknn = "bbknn_ridge.residuals_distances_symmetric"
+)
+
+integrations <- names(reductions)
+

Let’s finalise our preparations: :

+ +
+seu <- CellCycleScoringPerBatch(seu, batch.var = batch.var,
+                                s.features = cc.genes$s.genes,
+                                g2m.features = cc.genes$g2m.genes)
+

Let’s now loop through the integration outputs:

+
+for (integ in integrations) {
+  reduc <- reductions[[integ]]
+  graph <- graphs[[integ]]
+  clust.var.ari <- paste(integ, cell.var, "ari", sep = "_") # produced by `FindOptimalClusters()`
+  clust.var.nmi <- paste(integ, cell.var, "nmi", sep = "_") # produced by `FindOptimalClusters()`
+  if (! is.null(reduc)) {   # all TRUE except bbknn
+    seu <- AddScoreASW(seu, integration = integ, cell.var = cell.var,
+                       what = reduc, dist.package = "distances")
+    seu <- AddScoreASWBatch(seu, integration = integ, batch.var = batch.var,
+                            cell.var = cell.var, what = reduc,
+                            dist.package = "distances")
+    seu <- AddScoreDensityPC(seu, integration = integ, batch.var = batch.var,
+                             reduction = reduc)
+    seu <- AddScoreRegressPC(seu, integration = integ, batch.var = batch.var,
+                             reduction = reduc)
+    seu <- AddScoreRegressPC.CellCycle(seu, integration = integ,
+                                       batch.var = batch.var, what = reduc,
+                                       compute.cc = FALSE) # because CellCycleScoringPerBatch was ran before
+  }
+  seu <- AddScoreARI(seu, integration = integ, cell.var = cell.var,
+                     clust.var = clust.var.ari)
+  seu <- AddScoreNMI(seu, integration = integ, cell.var = cell.var,
+                     clust.var = clust.var.nmi)
+  seu <- AddScoreConnectivity(seu, integration = integ, graph.name = graph,
+                              cell.var = cell.var)
+  seu <- AddScoreKBET(seu, integration = integ, batch.var = batch.var,
+                      cell.var = cell.var, what = reduc %||% sub("_symmetric$", "", graph),
+                      graph.type = "distances", verbose = FALSE)
+  seu <- AddScoreLISI(seu, integration = integ, batch.var = batch.var,
+                      cell.var = cell.var, reduction = reduc,
+                      graph.name = if (is.null(reduc)) sub("_symmetric$", "", graph) else NULL,
+                      graph.type = "distances", ncores = ncores)
+  
+}
+

Now that we have computed multiple scores, we can look at them using +IntegrationScores():

+
+rmarkdown::paged_table(IntegrationScores(seu))
+
+ +
+
+
+

Compare the integrations +

+

Note that those scores are raw. Let’s scale them (and make them +comparable):

+
+seu <- ScaleScores(seu)
+

Once again, we can print them:

+
+rmarkdown::paged_table(IntegrationScores(seu, scaled = TRUE))
+
+ +
+

To readily compare the integrations, let’s plot the scores:

+ +

Dot plot to compare performance of integrations based on scores

+

One might notice a difference in scale for some of the scores, if +comparing the plot with the table just before. This is the case for the +PCA density score for instance.

+
+print(sort(IntegrationScores(seu, scaled = TRUE)$PCA.density))
+
## [1] 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.05713768 0.12268377
+

Indeed, PlotScores() rescales the scores using min-max +normalisation by default (rescale = TRUE). One might chose +to disable it:

+
+PlotScores(seu, rescale = FALSE)
+

Dot plot of scores without min-max rescaling

+

We notice that PCA based methods output very low scores in this case. +Since they cannot be computed on knn graphs, scores are biased in favour +of BBKNN. You can exclude some scores (and recompute overall scores on +the fly)

+
+PlotScores(seu, rescale = FALSE, exclude.score = c("pca.density", "pca.regression"))
+

Dot plot of scores without min-max rescaling, excluding non-informative scores

+

You can chose a different type of plot (radar or +lollipop):

+
+library(ggplot2)
+PlotScores(seu, plot.type = "radar") +
+  # reduce overlap between axis names and figures 
+  theme(legend.position = "top", panel.spacing = unit(3, "cm"),
+        plot.margin = margin(r = 3, l = 3, unit = "cm"),
+        axis.text.x = element_text(size = 10))
+
## Warning: Removed 5 rows containing missing values or values outside the scale range
+## (`geom_point()`).
+

Radar plot of scores

+

In this last plot, we also exclude the non-integrated dataset. Since +the rescale argument is true by default, the scores are +rescaled without the excluded integration’s scores.

+
+  PlotScores(seu, plot.type = "lollipop",
+             exclude.integration = "unintegrated")
+
## Warning: Removed 5 rows containing missing values or values outside the scale range
+## (`geom_point()`).
+
## Warning: Removed 5 rows containing missing values or values outside the scale range
+## (`geom_errorbarh()`).
+

Lollipop plot of scores without the unintegrated case

+

We want to compare the UMAP embeddings. For this, we first compute +the dimension reductions:

+
+for (integ in integrations) {
+  reduc <- reductions[[integ]]
+  if (! is.null(reduc)) { # all except BBKNN
+    seu <- RunUMAP(seu, dims = 1:min(30, ncol(seu[[reduc]])), reduction = reduc,
+                   reduction.name = paste0(integ, ".umap"))
+  }
+}
+

As BBKNN’s output is a graph, we need to use the umap Python +package:

+
+if (! reticulate::condaenv_exists('umap_0.5.4')) {
+  reticulate::conda_create('umap_0.5.4', packages = 'umap=0.5.4')
+}
+
+library(future)
+plan(multisession)
+seu %<-% {
+  reticulate::use_condaenv('umap_0.5.4')
+  RunUMAP(seu, graph = "bbknn_ridge.residuals_connectivities", umap.method = "umap-learn",
+          n.epochs = 200L, reduction.name = "bbknn.umap") }
+seu
+plan(sequential)
+
+library(ggplot2)
+plot_list <- sapply(integrations, function(integ) {
+  DimPlot(seu, reduction = paste0(integ, ".umap"), group.by = batch.var) +
+    ggtitle(integ) +
+    theme(axis.title = element_blank())
+}, simplify = FALSE)
+
+patchwork::wrap_plots(plot_list, guides = "collect")
+

UMAPs of unintegrated and integrated pbmcsca data with cells colored by sequencing method (i.e. batch)

+
+library(ggplot2)
+plot_list <- sapply(integrations, function(integ) {
+  DimPlot(seu, reduction = paste0(integ, ".umap"), group.by = cell.var) +
+    ggtitle(integ) +
+    theme(axis.title = element_blank())
+}, simplify = FALSE)
+
+patchwork::wrap_plots(plot_list, guides = "collect")
+

UMAPs of unintegrated and integrated pbmcsca data with cells colored by cell type label

+

There are several observations to be made here, that require further +explanations:

+
    +
  • some cells seem to be assigned a wrong label in +CellType, highlighting the importance of having cell +annotations of sufficient quality to be considered suitable as ground +truth (which is actually not the case here)
  • +
  • All scaled PCA regression scores are set to zero. This is because +the unintegrated dataset has the lowest raw PCA regression score. It is +very likely the consequence of the SCT normalisation, which +is much more efficient at masking batch-specific differences than the +classical LogNorm. Thus, the inter-batch differences are +not driving the principal components.
  • +
  • +ScaleScores() produce scores that can have different +scales (as long as rescale = FALSE) . Thus, min-max +rescaling is used by default in PlotScores(), to balance +each score’s contribution to the overall scores. This is especially +suited for comparing a large number of integrations. However, it has +some drawbacks: it can heavily distort the scale of scores when their +maximum or minimum are far from 1 or 0 respectively (e.g. all cLISI +scores are above 0.9). Hence, the final decision on +whether to use min-max rescaling is left to the user’s +discretion.
  • +
+
Session info +
  ## R version 4.4.2 (2024-10-31)
+  ## Platform: x86_64-pc-linux-gnu
+  ## Running under: Linux Mint 21
+  ## 
+  ## Matrix products: default
+  ## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
+  ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
+  ## 
+  ## locale:
+  ##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
+  ##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
+  ##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=en_US.UTF-8   
+  ##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
+  ##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
+  ## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
+  ## 
+  ## time zone: Europe/Paris
+  ## tzcode source: system (glibc)
+  ## 
+  ## attached base packages:
+  ## [1] stats     graphics  grDevices utils     datasets  methods   base     
+  ## 
+  ## other attached packages:
+  ## [1] future_1.34.0         ggplot2_3.5.1         SeuratIntegrate_0.4.0
+  ## [4] Seurat_5.1.0          SeuratObject_5.0.2    sp_2.1-4             
+  ## 
+  ## loaded via a namespace (and not attached):
+  ##   [1] fs_1.6.5                       matrixStats_1.4.1             
+  ##   [3] spatstat.sparse_3.1-0          httr_1.4.7                    
+  ##   [5] RColorBrewer_1.1-3             tools_4.4.2                   
+  ##   [7] sctransform_0.4.1              backports_1.5.0               
+  ##   [9] R6_2.5.1                       ResidualMatrix_1.14.1         
+  ##  [11] lazyeval_0.2.2                 uwot_0.2.2                    
+  ##  [13] mgcv_1.9-1                     withr_3.0.2                   
+  ##  [15] gridExtra_2.3                  progressr_0.15.1              
+  ##  [17] cli_3.6.3                      Biobase_2.64.0                
+  ##  [19] textshaping_0.4.1              spatstat.explore_3.3-3        
+  ##  [21] fastDummies_1.7.4              labeling_0.4.3                
+  ##  [23] sass_0.4.9                     spatstat.data_3.1-4           
+  ##  [25] genefilter_1.86.0              ggridges_0.5.6                
+  ##  [27] pbapply_1.7-2                  pkgdown_2.1.1                 
+  ##  [29] systemfonts_1.1.0              hcabm40k.SeuratData_3.0.0     
+  ##  [31] harmony_1.2.3                  parallelly_1.41.0             
+  ##  [33] limma_3.60.6                   rstudioapi_0.17.1             
+  ##  [35] RSQLite_2.3.9                  FNN_1.1.4.1                   
+  ##  [37] generics_0.1.3                 ica_1.0-3                     
+  ##  [39] spatstat.random_3.3-2          dplyr_1.1.4                   
+  ##  [41] Matrix_1.7-1                   S4Vectors_0.42.1              
+  ##  [43] abind_1.4-8                    lifecycle_1.0.4               
+  ##  [45] yaml_2.3.10                    edgeR_4.2.2                   
+  ##  [47] SummarizedExperiment_1.34.0    SparseArray_1.4.8             
+  ##  [49] Rtsne_0.17                     glmGamPoi_1.16.0              
+  ##  [51] grid_4.4.2                     blob_1.2.4                    
+  ##  [53] ifnb.SeuratData_3.1.0          promises_1.3.2                
+  ##  [55] crayon_1.5.3                   miniUI_0.1.1.1                
+  ##  [57] lattice_0.22-6                 beachmat_2.20.0               
+  ##  [59] cowplot_1.1.3                  annotate_1.82.0               
+  ##  [61] KEGGREST_1.44.1                pillar_1.10.0                 
+  ##  [63] knitr_1.49                     GenomicRanges_1.56.2          
+  ##  [65] kBET_0.99.6                    future.apply_1.11.3           
+  ##  [67] codetools_0.2-20               leiden_0.4.3.1                
+  ##  [69] glue_1.8.0                     spatstat.univar_3.1-1         
+  ##  [71] data.table_1.16.4              vctrs_0.6.5                   
+  ##  [73] png_0.1-8                      spam_2.11-0                   
+  ##  [75] gtable_0.3.6                   cachem_1.1.0                  
+  ##  [77] xfun_0.49                      S4Arrays_1.4.1                
+  ##  [79] mime_0.12                      survival_3.8-3                
+  ##  [81] pbmcref.SeuratData_1.0.0       SingleCellExperiment_1.26.0   
+  ##  [83] statmod_1.5.0                  fitdistrplus_1.2-1            
+  ##  [85] ROCR_1.0-11                    nlme_3.1-166                  
+  ##  [87] bit64_4.5.2                    RcppAnnoy_0.0.22              
+  ##  [89] GenomeInfoDb_1.40.1            bslib_0.8.0                   
+  ##  [91] irlba_2.3.5.1                  KernSmooth_2.23-24            
+  ##  [93] colorspace_2.1-1               BiocGenerics_0.50.0           
+  ##  [95] DBI_1.2.3                      tidyselect_1.2.1              
+  ##  [97] bit_4.5.0.1                    compiler_4.4.2                
+  ##  [99] BiocNeighbors_1.22.0           desc_1.4.3                    
+  ## [101] DelayedArray_0.30.1            plotly_4.10.4                 
+  ## [103] scales_1.3.0                   lmtest_0.9-40                 
+  ## [105] distances_0.1.11               rappdirs_0.3.3                
+  ## [107] stringr_1.5.1                  digest_0.6.37                 
+  ## [109] goftest_1.2-3                  spatstat.utils_3.1-1          
+  ## [111] rmarkdown_2.29                 XVector_0.44.0                
+  ## [113] RhpcBLASctl_0.23-42            htmltools_0.5.8.1             
+  ## [115] pkgconfig_2.0.3                sparseMatrixStats_1.16.0      
+  ## [117] MatrixGenerics_1.16.0          fastmap_1.2.0                 
+  ## [119] rlang_1.1.4                    htmlwidgets_1.6.4             
+  ## [121] UCSC.utils_1.0.0               shiny_1.10.0                  
+  ## [123] DelayedMatrixStats_1.26.0      farver_2.1.2                  
+  ## [125] jquerylib_0.1.4                zoo_1.8-12                    
+  ## [127] jsonlite_1.8.9                 BiocParallel_1.38.0           
+  ## [129] BiocSingular_1.20.0            magrittr_2.0.3                
+  ## [131] scuttle_1.14.0                 GenomeInfoDbData_1.2.12       
+  ## [133] dotCall64_1.2                  patchwork_1.3.0               
+  ## [135] pbmcsca.SeuratData_3.0.0       munsell_0.5.1                 
+  ## [137] Rcpp_1.0.13-1                  reticulate_1.40.0             
+  ## [139] stringi_1.8.4                  zlibbioc_1.50.0               
+  ## [141] MASS_7.3-61                    plyr_1.8.9                    
+  ## [143] parallel_4.4.2                 listenv_0.9.1                 
+  ## [145] ggrepel_0.9.6                  forcats_1.0.0                 
+  ## [147] deldir_2.0-4                   Biostrings_2.72.1             
+  ## [149] splines_4.4.2                  tensor_1.5                    
+  ## [151] locfit_1.5-9.10                lisi_1.0                      
+  ## [153] bonemarrowref.SeuratData_1.0.0 igraph_2.1.2                  
+  ## [155] spatstat.geom_3.3-4            heartref.SeuratData_1.0.0     
+  ## [157] RcppHNSW_0.6.0                 reshape2_1.4.4                
+  ## [159] stats4_4.4.2                   ScaledMatrix_1.12.0           
+  ## [161] XML_3.99-0.17                  evaluate_1.0.1                
+  ## [163] tweenr_2.0.3                   httpuv_1.6.15                 
+  ## [165] batchelor_1.20.0               bmcite.SeuratData_0.3.0       
+  ## [167] RANN_2.6.2                     tidyr_1.3.1                   
+  ## [169] purrr_1.0.2                    polyclip_1.10-7               
+  ## [171] SeuratData_0.2.2.9001          scattermore_1.2               
+  ## [173] ggforce_0.4.2                  rsvd_1.0.5                    
+  ## [175] broom_1.0.7                    xtable_1.8-4                  
+  ## [177] RSpectra_0.16-2                later_1.4.1                   
+  ## [179] viridisLite_0.4.2              ragg_1.3.3                    
+  ## [181] tibble_3.2.1                   memoise_2.0.1                 
+  ## [183] AnnotationDbi_1.66.0           IRanges_2.38.1                
+  ## [185] cluster_2.1.8                  sva_3.52.0                    
+  ## [187] globals_0.16.3
+
+
+
+
+
+ + + + +
+ + + + + + + diff --git a/articles/introduction_files/figure-html/unnamed-chunk-21-1.png b/articles/introduction_files/figure-html/unnamed-chunk-21-1.png new file mode 100644 index 0000000..8c5d902 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-21-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-23-1.png b/articles/introduction_files/figure-html/unnamed-chunk-23-1.png new file mode 100644 index 0000000..e78d206 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-23-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-24-1.png b/articles/introduction_files/figure-html/unnamed-chunk-24-1.png new file mode 100644 index 0000000..d5f0f72 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-24-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-25-1.png b/articles/introduction_files/figure-html/unnamed-chunk-25-1.png new file mode 100644 index 0000000..f3b6223 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-25-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-26-1.png b/articles/introduction_files/figure-html/unnamed-chunk-26-1.png new file mode 100644 index 0000000..75c5226 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-26-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-29-1.png b/articles/introduction_files/figure-html/unnamed-chunk-29-1.png new file mode 100644 index 0000000..b0b541a Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-29-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-30-1.png b/articles/introduction_files/figure-html/unnamed-chunk-30-1.png new file mode 100644 index 0000000..2c41916 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-30-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-8-1.png b/articles/introduction_files/figure-html/unnamed-chunk-8-1.png new file mode 100644 index 0000000..3fc2889 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-8-1.png differ diff --git a/articles/introduction_files/figure-html/unnamed-chunk-9-1.png b/articles/introduction_files/figure-html/unnamed-chunk-9-1.png new file mode 100644 index 0000000..73df9f3 Binary files /dev/null and b/articles/introduction_files/figure-html/unnamed-chunk-9-1.png differ diff --git a/articles/introduction_files/pagedtable-1.1/css/pagedtable.css b/articles/introduction_files/pagedtable-1.1/css/pagedtable.css new file mode 100644 index 0000000..8764d88 --- /dev/null +++ b/articles/introduction_files/pagedtable-1.1/css/pagedtable.css @@ -0,0 +1,142 @@ +.pagedtable { + overflow: auto; + padding-left: 8px; + padding-right: 8px; +} + +.pagedtable-wrapper { + border: 1px solid #ccc; + border-radius: 4px; + margin-bottom: 10px; +} + +.pagedtable table { + width: 100%; + max-width: 100%; + margin: 0; +} + +.pagedtable th { + padding: 0 5px 0 5px; + border: none; + border-bottom: 2px solid #dddddd; + + min-width: 45px; +} + +.pagedtable-empty th { + display: none; +} + +.pagedtable td { + padding: 0 4px 0 4px; +} + +.pagedtable .even { + background-color: rgba(140, 140, 140, 0.1); +} + +.pagedtable-padding-col { + display: none; +} + +.pagedtable a { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.pagedtable-index-nav { + cursor: pointer; + padding: 0 5px 0 5px; + float: right; + border: 0; +} + +.pagedtable-index-nav-disabled { + cursor: default; + text-decoration: none; + color: #999; +} + +a.pagedtable-index-nav-disabled:hover { + text-decoration: none; + color: #999; +} + +.pagedtable-indexes { + cursor: pointer; + float: right; + border: 0; +} + +.pagedtable-index-current { + cursor: default; + text-decoration: none; + font-weight: bold; + color: #333; + border: 0; +} + +a.pagedtable-index-current:hover { + text-decoration: none; + font-weight: bold; + color: #333; +} + +.pagedtable-index { + width: 30px; + display: inline-block; + text-align: center; + border: 0; +} + +.pagedtable-index-separator-left { + display: inline-block; + color: #333; + font-size: 9px; + padding: 0 0 0 0; + cursor: default; +} + +.pagedtable-index-separator-right { + display: inline-block; + color: #333; + font-size: 9px; + padding: 0 4px 0 0; + cursor: default; +} + +.pagedtable-footer { + padding-top: 4px; + padding-bottom: 5px; +} + +.pagedtable-not-empty .pagedtable-footer { + border-top: 2px solid #dddddd; +} + +.pagedtable-info { + overflow: hidden; + color: #999; + white-space: nowrap; + text-overflow: ellipsis; +} + +.pagedtable-header-name { + overflow: hidden; + text-overflow: ellipsis; +} + +.pagedtable-header-type { + color: #999; + font-weight: 400; +} + +.pagedtable-na-cell { + font-style: italic; + opacity: 0.3; +} diff --git a/articles/introduction_files/pagedtable-1.1/js/pagedtable.js b/articles/introduction_files/pagedtable-1.1/js/pagedtable.js new file mode 100644 index 0000000..52ada2b --- /dev/null +++ b/articles/introduction_files/pagedtable-1.1/js/pagedtable.js @@ -0,0 +1,1151 @@ +// Production steps of ECMA-262, Edition 5, 15.4.4.18 +// Reference: http://es5.github.io/#x15.4.4.18 +if (!Array.prototype.forEach) { + + Array.prototype.forEach = function(callback, thisArg) { + + var T, k; + + if (this === null) { + throw new TypeError(' this is null or not defined'); + } + + // 1. Let O be the result of calling toObject() passing the + // |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get() internal + // method of O with the argument "length". + // 3. Let len be toUint32(lenValue). + var len = O.length >>> 0; + + // 4. If isCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + ' is not a function'); + } + + // 5. If thisArg was supplied, let T be thisArg; else let + // T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let k be 0 + k = 0; + + // 7. Repeat, while k < len + while (k < len) { + + var kValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty + // internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal + // method of O with argument Pk. + kValue = O[k]; + + // ii. Call the Call internal method of callback with T as + // the this value and argument list containing kValue, k, and O. + callback.call(T, kValue, k, O); + } + // d. Increase k by 1. + k++; + } + // 8. return undefined + }; +} + +// Production steps of ECMA-262, Edition 5, 15.4.4.19 +// Reference: http://es5.github.io/#x15.4.4.19 +if (!Array.prototype.map) { + + Array.prototype.map = function(callback, thisArg) { + + var T, A, k; + + if (this == null) { + throw new TypeError(' this is null or not defined'); + } + + // 1. Let O be the result of calling ToObject passing the |this| + // value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal + // method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== 'function') { + throw new TypeError(callback + ' is not a function'); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let A be a new array created as if by the expression new Array(len) + // where Array is the standard built-in constructor with that name and + // len is the value of len. + A = new Array(len); + + // 7. Let k be 0 + k = 0; + + // 8. Repeat, while k < len + while (k < len) { + + var kValue, mappedValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal + // method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal + // method of O with argument Pk. + kValue = O[k]; + + // ii. Let mappedValue be the result of calling the Call internal + // method of callback with T as the this value and argument + // list containing kValue, k, and O. + mappedValue = callback.call(T, kValue, k, O); + + // iii. Call the DefineOwnProperty internal method of A with arguments + // Pk, Property Descriptor + // { Value: mappedValue, + // Writable: true, + // Enumerable: true, + // Configurable: true }, + // and false. + + // In browsers that support Object.defineProperty, use the following: + // Object.defineProperty(A, k, { + // value: mappedValue, + // writable: true, + // enumerable: true, + // configurable: true + // }); + + // For best browser support, use the following: + A[k] = mappedValue; + } + // d. Increase k by 1. + k++; + } + + // 9. return A + return A; + }; +} + +var PagedTable = function (pagedTable) { + var me = this; + + var source = function(pagedTable) { + var sourceElems = [].slice.call(pagedTable.children).filter(function(e) { + return e.hasAttribute("data-pagedtable-source"); + }); + + if (sourceElems === null || sourceElems.length !== 1) { + throw("A single data-pagedtable-source was not found"); + } + + return JSON.parse(sourceElems[0].innerHTML); + }(pagedTable); + + var options = function(source) { + var options = typeof(source.options) !== "undefined" && + source.options !== null ? source.options : {}; + + var columns = typeof(options.columns) !== "undefined" ? options.columns : {}; + var rows = typeof(options.rows) !== "undefined" ? options.rows : {}; + + var positiveIntOrNull = function(value) { + return parseInt(value) >= 0 ? parseInt(value) : null; + }; + + return { + pages: positiveIntOrNull(options.pages), + rows: { + min: positiveIntOrNull(rows.min), + max: positiveIntOrNull(rows.max), + total: positiveIntOrNull(rows.total) + }, + columns: { + min: positiveIntOrNull(columns.min), + max: positiveIntOrNull(columns.max), + total: positiveIntOrNull(columns.total) + } + }; + }(source); + + var Measurer = function() { + + // set some default initial values that will get adjusted in runtime + me.measures = { + padding: 12, + character: 8, + height: 15, + defaults: true + }; + + me.calculate = function(measuresCell) { + if (!me.measures.defaults) + return; + + var measuresCellStyle = window.getComputedStyle(measuresCell, null); + + var newPadding = parsePadding(measuresCellStyle.paddingLeft) + + parsePadding(measuresCellStyle.paddingRight); + + var sampleString = "ABCDEFGHIJ0123456789"; + var newCharacter = Math.ceil(measuresCell.clientWidth / sampleString.length); + + if (newPadding <= 0 || newCharacter <= 0) + return; + + me.measures.padding = newPadding; + me.measures.character = newCharacter; + me.measures.height = measuresCell.clientHeight; + me.measures.defaults = false; + }; + + return me; + }; + + var Page = function(data, options) { + var me = this; + + var defaults = { + max: 7, + rows: 10 + }; + + var totalPages = function() { + return Math.ceil(data.length / me.rows); + }; + + me.number = 0; + me.max = options.pages !== null ? options.pages : defaults.max; + me.visible = me.max; + me.rows = options.rows.min !== null ? options.rows.min : defaults.rows; + me.total = totalPages(); + + me.setRows = function(newRows) { + me.rows = newRows; + me.total = totalPages(); + }; + + me.setPageNumber = function(newPageNumber) { + if (newPageNumber < 0) newPageNumber = 0; + if (newPageNumber >= me.total) newPageNumber = me.total - 1; + + me.number = newPageNumber; + }; + + me.setVisiblePages = function(visiblePages) { + me.visible = Math.min(me.max, visiblePages); + me.setPageNumber(me.number); + }; + + me.getVisiblePageRange = function() { + var start = me.number - Math.max(Math.floor((me.visible - 1) / 2), 0); + var end = me.number + Math.floor(me.visible / 2) + 1; + var pageCount = me.total; + + if (start < 0) { + var diffToStart = 0 - start; + start += diffToStart; + end += diffToStart; + } + + if (end > pageCount) { + var diffToEnd = end - pageCount; + start -= diffToEnd; + end -= diffToEnd; + } + + start = start < 0 ? 0 : start; + end = end >= pageCount ? pageCount : end; + + var first = false; + var last = false; + + if (start > 0 && me.visible > 1) { + start = start + 1; + first = true; + } + + if (end < pageCount && me.visible > 2) { + end = end - 1; + last = true; + } + + return { + first: first, + start: start, + end: end, + last: last + }; + }; + + me.getRowStart = function() { + var rowStart = page.number * page.rows; + if (rowStart < 0) + rowStart = 0; + + return rowStart; + }; + + me.getRowEnd = function() { + var rowStart = me.getRowStart(); + return Math.min(rowStart + me.rows, data.length); + }; + + me.getPaddingRows = function() { + var rowStart = me.getRowStart(); + var rowEnd = me.getRowEnd(); + return data.length > me.rows ? me.rows - (rowEnd - rowStart) : 0; + }; + }; + + var Columns = function(data, columns, options) { + var me = this; + + me.defaults = { + min: 5 + }; + + me.number = 0; + me.visible = 0; + me.total = columns.length; + me.subset = []; + me.padding = 0; + me.min = options.columns.min !== null ? options.columns.min : me.defaults.min; + me.max = options.columns.max !== null ? options.columns.max : null; + me.widths = {}; + + var widthsLookAhead = Math.max(100, options.rows.min); + var paddingColChars = 10; + + me.emptyNames = function() { + columns.forEach(function(column) { + if (columns.label !== null && columns.label !== "") + return false; + }); + + return true; + }; + + var parsePadding = function(value) { + return parseInt(value) >= 0 ? parseInt(value) : 0; + }; + + me.calculateWidths = function(measures) { + columns.forEach(function(column) { + var maxChars = Math.max( + column.label.toString().length, + column.type.toString().length + ); + + for (var idxRow = 0; idxRow < Math.min(widthsLookAhead, data.length); idxRow++) { + maxChars = Math.max(maxChars, data[idxRow][column.name.toString()].length); + } + + me.widths[column.name] = { + // width in characters + chars: maxChars, + // width for the inner html columns + inner: maxChars * measures.character, + // width adding outer styles like padding + outer: maxChars * measures.character + measures.padding + }; + }); + }; + + me.getWidth = function() { + var widthOuter = 0; + for (var idxCol = 0; idxCol < me.subset.length; idxCol++) { + var columnName = me.subset[idxCol].name; + widthOuter = widthOuter + me.widths[columnName].outer; + } + + widthOuter = widthOuter + me.padding * paddingColChars * measurer.measures.character; + + if (me.hasMoreLeftColumns()) { + widthOuter = widthOuter + columnNavigationWidthPX + measurer.measures.padding; + } + + if (me.hasMoreRightColumns()) { + widthOuter = widthOuter + columnNavigationWidthPX + measurer.measures.padding; + } + + return widthOuter; + }; + + me.updateSlice = function() { + if (me.number + me.visible >= me.total) + me.number = me.total - me.visible; + + if (me.number < 0) me.number = 0; + + me.subset = columns.slice(me.number, Math.min(me.number + me.visible, me.total)); + + me.subset = me.subset.map(function(column) { + Object.keys(column).forEach(function(colKey) { + column[colKey] = column[colKey] === null ? "" : column[colKey].toString(); + }); + + column.width = null; + return column; + }); + }; + + me.setVisibleColumns = function(columnNumber, newVisibleColumns, paddingCount) { + me.number = columnNumber; + me.visible = newVisibleColumns; + me.padding = paddingCount; + + me.updateSlice(); + }; + + me.incColumnNumber = function(increment) { + me.number = me.number + increment; + }; + + me.setColumnNumber = function(newNumber) { + me.number = newNumber; + }; + + me.setPaddingCount = function(newPadding) { + me.padding = newPadding; + }; + + me.getPaddingCount = function() { + return me.padding; + }; + + me.hasMoreLeftColumns = function() { + return me.number > 0; + }; + + me.hasMoreRightColumns = function() { + return me.number + me.visible < me.total; + }; + + me.updateSlice(0); + return me; + }; + + var data = source.data; + var page = new Page(data, options); + var measurer = new Measurer(data, options); + var columns = new Columns(data, source.columns, options); + + var table = null; + var tableDiv = null; + var header = null; + var footer = null; + var tbody = null; + + // Caches pagedTable.clientWidth, specially for webkit + var cachedPagedTableClientWidth = null; + + var onChangeCallbacks = []; + + var clearSelection = function() { + if(document.selection && document.selection.empty) { + document.selection.empty(); + } else if(window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + } + }; + + var columnNavigationWidthPX = 5; + + var renderColumnNavigation = function(increment, backwards) { + var arrow = document.createElement("div"); + arrow.setAttribute("style", + "border-top: " + columnNavigationWidthPX + "px solid transparent;" + + "border-bottom: " + columnNavigationWidthPX + "px solid transparent;" + + "border-" + (backwards ? "right" : "left") + ": " + columnNavigationWidthPX + "px solid;"); + + var header = document.createElement("th"); + header.appendChild(arrow); + header.setAttribute("style", + "cursor: pointer;" + + "vertical-align: middle;" + + "min-width: " + columnNavigationWidthPX + "px;" + + "width: " + columnNavigationWidthPX + "px;"); + + header.onclick = function() { + columns.incColumnNumber(backwards ? -1 : increment); + + me.animateColumns(backwards); + renderFooter(); + + clearSelection(); + triggerOnChange(); + }; + + return header; + }; + + var maxColumnWidth = function(width) { + var padding = 80; + var columnMax = Math.max(cachedPagedTableClientWidth - padding, 0); + + return parseInt(width) > 0 ? + Math.min(columnMax, parseInt(width)) + "px" : + columnMax + "px"; + }; + + var clearHeader = function() { + var thead = pagedTable.querySelectorAll("thead")[0]; + thead.innerHTML = ""; + }; + + var renderHeader = function(clear) { + cachedPagedTableClientWidth = pagedTable.clientWidth; + + var fragment = document.createDocumentFragment(); + + header = document.createElement("tr"); + fragment.appendChild(header); + + if (columns.number > 0) + header.appendChild(renderColumnNavigation(-columns.visible, true)); + + columns.subset = columns.subset.map(function(columnData) { + var column = document.createElement("th"); + column.setAttribute("align", columnData.align); + column.style.textAlign = columnData.align; + + column.style.maxWidth = maxColumnWidth(null); + if (columnData.width) { + column.style.minWidth = + column.style.maxWidth = maxColumnWidth(columnData.width); + } + + var columnName = document.createElement("div"); + columnName.setAttribute("class", "pagedtable-header-name"); + if (columnData.label === "") { + columnName.innerHTML = " "; + } + else { + columnName.appendChild(document.createTextNode(columnData.label)); + } + column.appendChild(columnName); + + var columnType = document.createElement("div"); + columnType.setAttribute("class", "pagedtable-header-type"); + if (columnData.type === "") { + columnType.innerHTML = " "; + } + else { + columnType.appendChild(document.createTextNode("<" + columnData.type + ">")); + } + column.appendChild(columnType); + + header.appendChild(column); + + columnData.element = column; + + return columnData; + }); + + for (var idx = 0; idx < columns.getPaddingCount(); idx++) { + var paddingCol = document.createElement("th"); + paddingCol.setAttribute("class", "pagedtable-padding-col"); + header.appendChild(paddingCol); + } + + if (columns.number + columns.visible < columns.total) + header.appendChild(renderColumnNavigation(columns.visible, false)); + + if (typeof(clear) == "undefined" || clear) clearHeader(); + var thead = pagedTable.querySelectorAll("thead")[0]; + thead.appendChild(fragment); + }; + + me.animateColumns = function(backwards) { + var thead = pagedTable.querySelectorAll("thead")[0]; + + var headerOld = thead.querySelectorAll("tr")[0]; + var tbodyOld = table.querySelectorAll("tbody")[0]; + + me.fitColumns(backwards); + + renderHeader(false); + + header.style.opacity = "0"; + header.style.transform = backwards ? "translateX(-30px)" : "translateX(30px)"; + header.style.transition = "transform 200ms linear, opacity 200ms"; + header.style.transitionDelay = "0"; + + renderBody(false); + + if (headerOld) { + headerOld.style.position = "absolute"; + headerOld.style.transform = "translateX(0px)"; + headerOld.style.opacity = "1"; + headerOld.style.transition = "transform 100ms linear, opacity 100ms"; + headerOld.setAttribute("class", "pagedtable-remove-head"); + if (headerOld.style.transitionEnd) { + headerOld.addEventListener("transitionend", function() { + var headerOldByClass = thead.querySelector(".pagedtable-remove-head"); + if (headerOldByClass) thead.removeChild(headerOldByClass); + }); + } + else { + thead.removeChild(headerOld); + } + } + + if (tbodyOld) table.removeChild(tbodyOld); + + tbody.style.opacity = "0"; + tbody.style.transition = "transform 200ms linear, opacity 200ms"; + tbody.style.transitionDelay = "0ms"; + + // force relayout + window.getComputedStyle(header).opacity; + window.getComputedStyle(tbody).opacity; + + if (headerOld) { + headerOld.style.transform = backwards ? "translateX(20px)" : "translateX(-30px)"; + headerOld.style.opacity = "0"; + } + + header.style.transform = "translateX(0px)"; + header.style.opacity = "1"; + + tbody.style.opacity = "1"; + } + + me.onChange = function(callback) { + onChangeCallbacks.push(callback); + }; + + var triggerOnChange = function() { + onChangeCallbacks.forEach(function(onChange) { + onChange(); + }); + }; + + var clearBody = function() { + if (tbody) { + table.removeChild(tbody); + tbody = null; + } + }; + + var renderBody = function(clear) { + cachedPagedTableClientWidth = pagedTable.clientWidth + + var fragment = document.createDocumentFragment(); + + var pageData = data.slice(page.getRowStart(), page.getRowEnd()); + + pageData.forEach(function(dataRow, idxRow) { + var htmlRow = document.createElement("tr"); + htmlRow.setAttribute("class", (idxRow % 2 !==0) ? "even" : "odd"); + + if (columns.hasMoreLeftColumns()) + htmlRow.appendChild(document.createElement("td")); + + columns.subset.forEach(function(columnData) { + var cellName = columnData.name; + var dataCell = dataRow[cellName]; + var htmlCell = document.createElement("td"); + + if (dataCell === "NA") htmlCell.setAttribute("class", "pagedtable-na-cell"); + if (dataCell === "__NA__") dataCell = "NA"; + + var cellText = document.createTextNode(dataCell); + htmlCell.appendChild(cellText); + if (dataCell.length > 50) { + htmlCell.setAttribute("title", dataCell); + } + htmlCell.setAttribute("align", columnData.align); + htmlCell.style.textAlign = columnData.align; + htmlCell.style.maxWidth = maxColumnWidth(null); + if (columnData.width) { + htmlCell.style.minWidth = htmlCell.style.maxWidth = maxColumnWidth(columnData.width); + } + htmlRow.appendChild(htmlCell); + }); + + for (var idx = 0; idx < columns.getPaddingCount(); idx++) { + var paddingCol = document.createElement("td"); + paddingCol.setAttribute("class", "pagedtable-padding-col"); + htmlRow.appendChild(paddingCol); + } + + if (columns.hasMoreRightColumns()) + htmlRow.appendChild(document.createElement("td")); + + fragment.appendChild(htmlRow); + }); + + for (var idxPadding = 0; idxPadding < page.getPaddingRows(); idxPadding++) { + var paddingRow = document.createElement("tr"); + + var paddingCellRow = document.createElement("td"); + paddingCellRow.innerHTML = " "; + paddingCellRow.setAttribute("colspan", "100%"); + paddingRow.appendChild(paddingCellRow); + + fragment.appendChild(paddingRow); + } + + if (typeof(clear) == "undefined" || clear) clearBody(); + tbody = document.createElement("tbody"); + tbody.appendChild(fragment); + + table.appendChild(tbody); + }; + + var getLabelInfo = function() { + var pageStart = page.getRowStart(); + var pageEnd = page.getRowEnd(); + var totalRows = data.length; + + var totalRowsLabel = options.rows.total ? options.rows.total : totalRows; + var totalRowsLabelFormat = totalRowsLabel.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,'); + + var infoText = (pageStart + 1) + "-" + pageEnd + " of " + totalRowsLabelFormat + " rows"; + if (totalRows < page.rows) { + infoText = totalRowsLabel + " row" + (totalRows != 1 ? "s" : ""); + } + if (columns.total > columns.visible) { + var totalColumnsLabel = options.columns.total ? options.columns.total : columns.total; + + infoText = infoText + " | " + (columns.number + 1) + "-" + + (Math.min(columns.number + columns.visible, columns.total)) + + " of " + totalColumnsLabel + " columns"; + } + + return infoText; + }; + + var clearFooter = function() { + footer = pagedTable.querySelectorAll("div.pagedtable-footer")[0]; + footer.innerHTML = ""; + + return footer; + }; + + var createPageLink = function(idxPage) { + var pageLink = document.createElement("a"); + pageLinkClass = idxPage === page.number ? "pagedtable-index pagedtable-index-current" : "pagedtable-index"; + pageLink.setAttribute("class", pageLinkClass); + pageLink.setAttribute("data-page-index", idxPage); + pageLink.onclick = function() { + page.setPageNumber(parseInt(this.getAttribute("data-page-index"))); + renderBody(); + renderFooter(); + + triggerOnChange(); + }; + + pageLink.appendChild(document.createTextNode(idxPage + 1)); + + return pageLink; + } + + var renderFooter = function() { + footer = clearFooter(); + + var next = document.createElement("a"); + next.appendChild(document.createTextNode("Next")); + next.onclick = function() { + page.setPageNumber(page.number + 1); + renderBody(); + renderFooter(); + + triggerOnChange(); + }; + if (data.length > page.rows) footer.appendChild(next); + + var pageNumbers = document.createElement("div"); + pageNumbers.setAttribute("class", "pagedtable-indexes"); + + var pageRange = page.getVisiblePageRange(); + + if (pageRange.first) { + var pageLink = createPageLink(0); + pageNumbers.appendChild(pageLink); + + var pageSeparator = document.createElement("div"); + pageSeparator.setAttribute("class", "pagedtable-index-separator-left"); + pageSeparator.appendChild(document.createTextNode("...")) + pageNumbers.appendChild(pageSeparator); + } + + for (var idxPage = pageRange.start; idxPage < pageRange.end; idxPage++) { + var pageLink = createPageLink(idxPage); + + pageNumbers.appendChild(pageLink); + } + + if (pageRange.last) { + var pageSeparator = document.createElement("div"); + pageSeparator.setAttribute("class", "pagedtable-index-separator-right"); + pageSeparator.appendChild(document.createTextNode("...")) + pageNumbers.appendChild(pageSeparator); + + var pageLink = createPageLink(page.total - 1); + pageNumbers.appendChild(pageLink); + } + + if (data.length > page.rows) footer.appendChild(pageNumbers); + + var previous = document.createElement("a"); + previous.appendChild(document.createTextNode("Previous")); + previous.onclick = function() { + page.setPageNumber(page.number - 1); + renderBody(); + renderFooter(); + + triggerOnChange(); + }; + if (data.length > page.rows) footer.appendChild(previous); + + var infoLabel = document.createElement("div"); + infoLabel.setAttribute("class", "pagedtable-info"); + infoLabel.setAttribute("title", getLabelInfo()); + infoLabel.appendChild(document.createTextNode(getLabelInfo())); + footer.appendChild(infoLabel); + + var enabledClass = "pagedtable-index-nav"; + var disabledClass = "pagedtable-index-nav pagedtable-index-nav-disabled"; + previous.setAttribute("class", page.number <= 0 ? disabledClass : enabledClass); + next.setAttribute("class", (page.number + 1) * page.rows >= data.length ? disabledClass : enabledClass); + }; + + var measuresCell = null; + + var renderMeasures = function() { + var measuresTable = document.createElement("table"); + measuresTable.style.visibility = "hidden"; + measuresTable.style.position = "absolute"; + measuresTable.style.whiteSpace = "nowrap"; + measuresTable.style.height = "auto"; + measuresTable.style.width = "auto"; + + var measuresRow = document.createElement("tr"); + measuresTable.appendChild(measuresRow); + + measuresCell = document.createElement("td"); + var sampleString = "ABCDEFGHIJ0123456789"; + measuresCell.appendChild(document.createTextNode(sampleString)); + + measuresRow.appendChild(measuresCell); + + tableDiv.appendChild(measuresTable); + } + + me.init = function() { + tableDiv = document.createElement("div"); + pagedTable.appendChild(tableDiv); + var pagedTableClass = data.length > 0 ? + "pagedtable pagedtable-not-empty" : + "pagedtable pagedtable-empty"; + + if (columns.total == 0 || (columns.emptyNames() && data.length == 0)) { + pagedTableClass = pagedTableClass + " pagedtable-empty-columns"; + } + + tableDiv.setAttribute("class", pagedTableClass); + + renderMeasures(); + measurer.calculate(measuresCell); + columns.calculateWidths(measurer.measures); + + table = document.createElement("table"); + table.setAttribute("cellspacing", "0"); + table.setAttribute("class", "table table-condensed"); + tableDiv.appendChild(table); + + table.appendChild(document.createElement("thead")); + + var footerDiv = document.createElement("div"); + footerDiv.setAttribute("class", "pagedtable-footer"); + tableDiv.appendChild(footerDiv); + + // if the host has not yet provided horizontal space, render hidden + if (tableDiv.clientWidth <= 0) { + tableDiv.style.opacity = "0"; + } + + me.render(); + + // retry seizing columns later if the host has not provided space + function retryFit() { + if (tableDiv.clientWidth <= 0) { + setTimeout(retryFit, 100); + } else { + me.render(); + triggerOnChange(); + } + } + if (tableDiv.clientWidth <= 0) { + retryFit(); + } + }; + + var registerWidths = function() { + columns.subset = columns.subset.map(function(column) { + column.width = columns.widths[column.name].inner; + return column; + }); + }; + + var parsePadding = function(value) { + return parseInt(value) >= 0 ? parseInt(value) : 0; + }; + + me.fixedHeight = function() { + return options.rows.max != null; + } + + me.fitRows = function() { + if (me.fixedHeight()) + return; + + measurer.calculate(measuresCell); + + var rows = options.rows.min !== null ? options.rows.min : 0; + var headerHeight = header !== null && header.offsetHeight > 0 ? header.offsetHeight : 0; + var footerHeight = footer !== null && footer.offsetHeight > 0 ? footer.offsetHeight : 0; + + if (pagedTable.offsetHeight > 0) { + var availableHeight = pagedTable.offsetHeight - headerHeight - footerHeight; + rows = Math.floor((availableHeight) / measurer.measures.height); + } + + rows = options.rows.min !== null ? Math.max(options.rows.min, rows) : rows; + + page.setRows(rows); + } + + // The goal of this function is to add as many columns as possible + // starting from left-to-right, when the right most limit is reached + // it tries to add columns from the left as well. + // + // When startBackwards is true columns are added from right-to-left + me.fitColumns = function(startBackwards) { + measurer.calculate(measuresCell); + columns.calculateWidths(measurer.measures); + + if (tableDiv.clientWidth > 0) { + tableDiv.style.opacity = 1; + } + + var visibleColumns = tableDiv.clientWidth <= 0 ? Math.max(columns.min, 1) : 1; + var columnNumber = columns.number; + var paddingCount = 0; + + // track a list of added columns as we build the visible ones to allow us + // to remove columns when they don't fit anymore. + var columnHistory = []; + + var lastTableHeight = 0; + var backwards = startBackwards; + + var tableDivStyle = window.getComputedStyle(tableDiv, null); + var tableDivPadding = parsePadding(tableDivStyle.paddingLeft) + + parsePadding(tableDivStyle.paddingRight); + + var addPaddingCol = false; + var currentWidth = 0; + + while (true) { + columns.setVisibleColumns(columnNumber, visibleColumns, paddingCount); + currentWidth = columns.getWidth(); + + if (tableDiv.clientWidth - tableDivPadding < currentWidth) { + break; + } + + columnHistory.push({ + columnNumber: columnNumber, + visibleColumns: visibleColumns, + paddingCount: paddingCount + }); + + if (columnHistory.length > 100) { + console.error("More than 100 tries to fit columns, aborting"); + break; + } + + if (columns.max !== null && + columns.visible + columns.getPaddingCount() >= columns.max) { + break; + } + + // if we run out of right-columns + if (!backwards && columnNumber + columns.visible >= columns.total) { + // if we started adding right-columns, try adding left-columns + if (!startBackwards && columnNumber > 0) { + backwards = true; + } + else if (columns.min === null || visibleColumns + columns.getPaddingCount() >= columns.min) { + break; + } + else { + paddingCount = paddingCount + 1; + } + } + + // if we run out of left-columns + if (backwards && columnNumber == 0) { + // if we started adding left-columns, try adding right-columns + if (startBackwards && columnNumber + columns.visible < columns.total) { + backwards = false; + } + else if (columns.min === null || visibleColumns + columns.getPaddingCount() >= columns.min) { + break; + } + else { + paddingCount = paddingCount + 1; + } + } + + // when moving backwards try fitting left columns first + if (backwards && columnNumber > 0) { + columnNumber = columnNumber - 1; + } + + if (columnNumber + visibleColumns < columns.total) { + visibleColumns = visibleColumns + 1; + } + } + + var lastRenderableColumn = { + columnNumber: columnNumber, + visibleColumns: visibleColumns, + paddingCount: paddingCount + }; + + if (columnHistory.length > 0) { + lastRenderableColumn = columnHistory[columnHistory.length - 1]; + } + + columns.setVisibleColumns( + lastRenderableColumn.columnNumber, + lastRenderableColumn.visibleColumns, + lastRenderableColumn.paddingCount); + + if (pagedTable.offsetWidth > 0) { + page.setVisiblePages(Math.max(Math.ceil(1.0 * (pagedTable.offsetWidth - 250) / 40), 2)); + } + + registerWidths(); + }; + + me.fit = function(startBackwards) { + me.fitRows(); + me.fitColumns(startBackwards); + } + + me.render = function() { + me.fitColumns(false); + + // render header/footer to measure height accurately + renderHeader(); + renderFooter(); + + me.fitRows(); + renderBody(); + + // re-render footer to match new rows + renderFooter(); + } + + var resizeLastWidth = -1; + var resizeLastHeight = -1; + var resizeNewWidth = -1; + var resizeNewHeight = -1; + var resizePending = false; + + me.resize = function(newWidth, newHeight) { + + function resizeDelayed() { + resizePending = false; + + if ( + (resizeNewWidth !== resizeLastWidth) || + (!me.fixedHeight() && resizeNewHeight !== resizeLastHeight) + ) { + resizeLastWidth = resizeNewWidth; + resizeLastHeight = resizeNewHeight; + + setTimeout(resizeDelayed, 200); + resizePending = true; + } else { + me.render(); + triggerOnChange(); + + resizeLastWidth = -1; + resizeLastHeight = -1; + } + } + + resizeNewWidth = newWidth; + resizeNewHeight = newHeight; + + if (!resizePending) resizeDelayed(); + }; +}; + +var PagedTableDoc; +(function (PagedTableDoc) { + var allPagedTables = []; + + PagedTableDoc.initAll = function() { + allPagedTables = []; + + var pagedTables = [].slice.call(document.querySelectorAll('[data-pagedtable="false"],[data-pagedtable=""]')); + pagedTables.forEach(function(pagedTable, idx) { + pagedTable.setAttribute("data-pagedtable", "true"); + pagedTable.setAttribute("pagedtable-page", 0); + pagedTable.setAttribute("class", "pagedtable-wrapper"); + + var pagedTableInstance = new PagedTable(pagedTable); + pagedTableInstance.init(); + + allPagedTables.push(pagedTableInstance); + }); + }; + + PagedTableDoc.resizeAll = function() { + allPagedTables.forEach(function(pagedTable) { + pagedTable.render(); + }); + }; + + window.addEventListener("resize", PagedTableDoc.resizeAll); + + return PagedTableDoc; +})(PagedTableDoc || (PagedTableDoc = {})); + +window.onload = function() { + PagedTableDoc.initAll(); +}; diff --git a/articles/memo_integration.html b/articles/memo_integration.html new file mode 100644 index 0000000..dbcc283 --- /dev/null +++ b/articles/memo_integration.html @@ -0,0 +1,323 @@ + + + + + + + +Memo: Integration methods • SeuratIntegrate + + + + + + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + + +

SeuratIntegrate provides access to R and Python methods to correct +batch effect:

+ + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Comprehensive overview of the integration methods provided by +SeuratIntegrate
MethodTypeImplementationUnderlying algorithmReference
ComBatR logo +sva +(Bioconductor)Empirical Bayes adjustmentJohnson et al., +2007
HarmonyR logo +harmony +(CRAN)Iterative embedding correctionKorsunsky et al., +2019
MNNR logo +batchelor +(Bioconductor)Mutual Nearest NeighborsHaghverdi +et al., 2018
BBKNNPython logo +bbknn +(GitHub)Batch-balanced nearest neighborsPolański et al., +2020
scVIPython logo +scvi-tools +(GitHub)Variational autoencoderLopez et al., +2018
scANVIPython logo +scvi-tools +(GitHub)Semi-supervised variational autoencoderXu et +al., 2021
ScanoramaPython logo +scanorama (GitHub)Manifold alignmentHie et al., +2019
trVAEPython logo +scArches (GitHub)Conditional variational autoencoderLotfollahi et al., +2020
+

SeuratIntegrate provides a new interface to integrate the layers of +an object: DoIntegrate(). Moreover, SeuratIntegrate is +compatible with CCA and RPCA (included in Seurat) and +FastMNN (from SeuratWrappers)

+

The table below summarizes the integrations methods you can run with +DoIntegrate() along with the expected inputs and produced +outputs of each method.

+ + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Comprehensive overview of inputs and outputs of the integration +methods
MethodPackageFunctionInputOutput(s)
ComBatSeuratIntegrateCombatIntegration()LayerLayer with corrected counts
HarmonySeuratIntegrateHarmonyIntegration()PCADimReduc (corrected PCA)
MNNSeuratIntegrateMNNIntegration()LayerLayer with corrected counts
BBKNNSeuratIntegratebbknnIntegration()PCAGraphs (edge weights can be distances or +connectivities)
scVISeuratIntegratescVIIntegration()LayerDimReduc (latent space)
scANVISeuratIntegratescANVIIntegration()LayerDimReduc (latent space)
ScanoramaSeuratIntegrateScanoramaIntegration()Layer +

Layer with corrected counts

+

DimReduc (corrected embedding)

+
trVAESeuratIntegratetrVAEIntegration() +

Data layer
+(recon.loss = "mse")

+

Counts layer
+(otherwise)

+
DimReduc (latent space)
CCASeuratCCAIntegration()PCADimReduc (corrected PCA)
RPCASeuratRPCAIntegration()PCADimReduc (corrected PCA)
FastMNNSeuratWrappersFastMNNIntegration()Layer +

Layer with corrected counts

+

DimReduc (corrected PCA)

+
+
+ + + + +
+ + + + + + + diff --git a/articles/memo_score.html b/articles/memo_score.html new file mode 100644 index 0000000..d306cb8 --- /dev/null +++ b/articles/memo_score.html @@ -0,0 +1,233 @@ + + + + + + + +Memo: Scoring metrics • SeuratIntegrate + + + + + + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + + +

SeuratIntegrate incorporates 11 scoring metrics: 6 quantify the +degree of batch mixing batch correction (batch +correction), while 5 assess the preservation of biological +differences bio-conservation (bio-conservation) based +on ground truth cell type labels.

+

Below is a table summarising each score’s input and type:

+ + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table summarising the inputs required for each score, and the +type of scores it belongs to.
Score nameRequire a cell type variableRequire a clustering variableInputScore type
Cell cycle regressionDimension reductionbio-conservation
PCA regressionDimension reductionbatch correction
PCA densityDimension reductionbatch correction
ASW batchcell-type variableDimension reductionbatch correction
ASWcell-type variableDimension reductionbio-conservation
ARIcell-type variableclustering variablebio-conservation
NMIcell-type variableclustering variablebio-conservation
cLISIcell-type variable +Dimension reduction or +KNN graph +bio-conservation
iLISIcell-type variable +Dimension reduction or +KNN graph +batch correction
kBETcell-type variable +Dimension reduction or +KNN graph +batch correction
Graph connectivity +cell-type variable +(per.component = TRUE)KNN graphbatch correction
+

Most scores are computed on an embedding DimReduc object +(Seurat::DimReduc object) or a graph Graph or Neighbor object (Seurat::Neighbor or +Seurat::Graph object). The exceptions are ARI and NMI, +which compare two categorical variables thus don’t need anything else +than a cell-type and a cluster assignment variables.d anything else than +a cell-type and a cluster assignment variables.

+

Most scores are based on a cell type label variable. This consists in +an estimate of each cell’s type obtained by analysing each batch +separately or by using an automatic cell annotation algorithm. This +estimate of cell types must be of sufficient quality to be considered +suitable as ground truth.

+
+
+ + + + +
+ + + + + + + diff --git a/articles/setup_and_tips.html b/articles/setup_and_tips.html new file mode 100644 index 0000000..5af9b44 --- /dev/null +++ b/articles/setup_and_tips.html @@ -0,0 +1,566 @@ + + + + + + + +Generic advice about setting up and using conda environments • SeuratIntegrate + + + + + + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + + +
+

Introduction +

+

SeuratIntegrate’s main purpose is to extend the range of +scRNA-seq integration tools available in R and compatible with +Seurat. Many of them being solely available in Python, we +developed wrappers leveraging reticulate package’s +capabilities. reticulate enables to directly call Python +from R, give that conda environments have been set up beforehand.

+

The purpose of this vignette is to illustrate and ease the +installation and the use of those environments.

+

Prior to starting, make sure you have:

+
    +
  • conda installed on your machine
  • +
  • conda binary in your PATH (or that you +know its location)
  • +
+
+
+

Set-up +

+

We need multiple conda environments. One for bbknn, one +for Scanorama, one for +scVI/scANVI and one for trVAE. If +you don’t plan on using any or some of these methods, whether you decide +to set up their respective conda environments is up to you.

+

One the contrary, if you already have some conda environments with +appropriate libraries on your machine, you can tell +SeuratIntegrate to use them. Let’s see how.

+ +

Have look at your CondaEnvManager:

+ +

Unset conda environments

+

It’s a handy way to have a glance at all the implemented methods and +the status of their conda environments. ComBat, +Harmony and MNN are R-based methods and don’t +need any conda environment. The rest of them however are Python-based +and will function through reticulate, hence require conda +environments.

+

If you don’t have any conda environments for them, look at the next sub-section. Conversely, if you want to add +an existing conda environment, directly go to the following one.

+
+

Option 1: Create new conda environments with +SeuratIntegrate +

+

Note that the commands below have only been tested on Linux +distributions

+

Try the following commands (be aware that execution might take +time):

+
+UpdateEnvCache('bbknn')
+UpdateEnvCache('scvi')
+UpdateEnvCache('scanorama')
+UpdateEnvCache('trvae')
+

Note that:

+
    +
  • if conda is not in you PATH set +conda.bin = /path/to/conda +
  • +
  • +scVI and scANVI share the same +environment. Hence, it is not necessary to run both +UpdateEnvCache('scvi') and +UpdateEnvCache('scanvi') +
  • +
+

Have look at your CondaEnvManager:

+ +

Fully set conda environments

+
+
+

Option 2: Use existing conda environments +

+

If you already have one (several) existing conda environment(s) for +one (some) of the methods, you can tell SeuratIntegrate to +use it (them). Similarly, if you run into problems with +UpdateEnvCache() commands above, the alternative is to set +up conda environments yourself and provide them to +SeuratIntegrate. Whatever the case, let’s proceed.

+

You’ll use UpdateEnvCache(). You can specify the name of +the conda environment or the path to it. By default, +UpdateEnvCache() will try to decide whether the provided +value for conda.env is a path or a name based on simple +tests. To avoid any misinterpretation, you can use +conda.env.is.path = TRUE or FALSE when your +input is the path or the name of the environment, respectively. +But beware not to make mistakes !!!

+

See examples below. You should adapt the arguments to your +situation:

+
+# environment for bbknn
+UpdateEnvCache('bbknn', conda.env = 'bbknn_env',
+               conda.env.is.path = FALSE)   # default 'auto' would work
+
+# environment for bbknn in ./bbknn_env/
+UpdateEnvCache('bbknn', conda.env = 'bbknn_env',
+               conda.env.is.path = TRUE)
+
+# environment for bbknn, conda binary not in PATH
+UpdateEnvCache('bbknn', conda.env = 'bbknn_env', conda.bin = 'cutom/location/conda')
+
+# path for scvi-tools
+UpdateEnvCache('scvi', conda.env = '~/miniconda3/envs/scvi-tools_env',
+               conda.env.is.path = TRUE)   # default 'auto' would work
+

Note that:

+
    +
  • if conda is not in you PATH set +conda.bin = /path/to/conda +
  • +
  • the conda.bin must correspond to the conda managing the +conda.env +
  • +
  • +scVI and scANVI share the same +environment. Hence, it is not necessary to run both +UpdateEnvCache('scvi') and +UpdateEnvCache('scanvi') +
  • +
+

Now you can use the Python-based methods !

+
+
+

Update or reset conda environments +

+

If you want to update a conda environment, use

+
+# change 'method' by the name of the method
+UpdateEnvCache(method = 'method', overwrite.env = TRUE, ...)
+

To unset an environment, use

+
+# change 'method' by the name of the method
+resetCache(method = 'method')
+
+
+
+

Troubleshouting with conda +

+
+

Common issues with setting up environments +

+

It can happen that a conda environment cannot be installed on a +specific machine or os. In this case, there is hardly anything better to +do than browse the internet in hope that someone else has experienced a +similar problem and that the solution is public. Otherwise, try to +modify the set of packages to install, be more or less stringent with +package versions to install, etc. You can also create a conda +environment with Python and pip, and then to try to install packages +with pip rather than conda.

+

Once the problem is solved (if it can be), you can save the new +environment to the CondaEnvManager with

+
+# change 'method' by the name of the method
+# change'difficult_conda_env' by the name of the working conda environment
+UpdateEnvCache(method = 'method', conda.env = 'difficult_conda_env')
+
+
+

Possible issues with activating environments +

+

It can happen that a conda environment does not work (or stops +working) on a specific machine. Below are some potential causes of +conflicts between Python libraries, conda itself or other components +that could lead to malfunctions (non exhaustive list):

+
    +
  1. with rmarkdown/knitr
  2. +
+
    How to check +

    Check if the same command works outside of an rmarkdown (e.g. in a R +script), once you have closed any Rmardown file and closed the R session +(and restrated RStudio). This is something to consider notably when you +encounter an error like:

    +
    ImportError: /opt/conda/envs/[env_name]/lib/python3.10/site-packages/PIL/../../../libtiff.so.6: undefined symbol: jpeg12_write_raw_data, version LIBJPEG_8.0
    +
+
    How to fix + +Close any Rmardown file in the source panel, quit the R session (close +RStudio) and work from a R script. +
+
    +
  1. with RStudio
  2. +
+
    How to check +

    Check if the same command works outside of RStudio. For instance, if +there is an error during an integration because scanpy cannot be +imported, try:

    +
    # from a terminal
    +R
    +
    > library(reticulate)
    +> use_condaenv('[conda_env_name]')
    +> scanpy <- import("scanpy", convert = FALSE)
    +# error here ?
    +> 
    +
+
    How to fix + +Lunch the integration outside of RStudio (from a terminal for example). +
+
    +
  1. with reticulate
  2. +
+
    How to check +

    Check if the conda environment loads properly in a pure Python +session. For instance, if there is an error during an integration +because scanpy cannot be imported, try to:

    +
    conda activate [conda_env_name]
    +python
    +
    >>> import scanpy
    +# error here ?
    +>>>
    +
+
    How to fix +

    First, try to update reticulate. If it doesn’t work any better, check +if someone has encountered the same issue (browse the web or the issues +on the reticulate github repository. If nothing works, either post an +issue on the reticulate github repos or retry to import after you have +installed different Python package versions.

    +If this is a problem with mkl, install the conda +environment again with the arguments nomkl (and +-c conda-forge if not already). +
+
    +
  1. between Python packages
  2. +
+
    How to check +

    This is more tricky. But some packages are know to be incompatible. +For instance, jax and jaxlib work better when their versions are +identical. In my experience, the scvi-tools environment can +be set up with two discrepant versions of jax and jaxlib. To check, +try:

    +
    conda list -n [conda_env_name] jax
    +
+
    How to fix + +If this is a problem with jax and jaxlib, try to force install them with +identical versions. Otherwise, search your error on the web. +
+
    +
  1. between your local os and the list of packages to be +installed by SeuratIntegrate
  2. +
+
    How to check + +This is more an installation problem usually. Check the previous section. +
+
    How to fix + +This is more an installation problem usually. Check the previous section. +
+
+
+
+

Subtleties of using Future +

+

If the following bullet points seem obscure, further explanations are +given in the sections below. In brief,

+
+
    +
  • +disable future for R-based methods +(DoIntegrate([...], use.future = FALSE))
  • +
  • +never use CCA and RPCA +integration methods with multisession (previous advice prevents this, +especially for Windows users)
  • +
  • multicore futures are faster and less memory-intensive than +multisession, but unstable on RStudio and unavailable on +Windows +
  • +
  • to force DoIntegrate() to use a multicore framework (at +your own risk), set +options(parallelly.fork.enable = FALSE). +Unavailable on Windows +
  • +
+
+
+

Why SeuratIntegrate uses Future ? +

+

A R session can only initialise one Python environment at a time via +reticulate. This known +limitation +of reticualte is overcome by launching a “background +session” using Future. The environment is initialised +there instead of the main user’s R session. This feature is embedded in +DoIntegrate().

+

Futures are therefore useless for R-based methods and should be +disabled with DoIntegrate([...], use.future = FALSE). +Worse, it is discouraged with +CCAIntegration and RPCAIntegration +(explanations are in the final part of the vignette)

+
+
+

Inconveniences +

+

In the vast majority of cases, the impact of the “futures” +is insignificant. The most obvious are the few needed seconds to launch +the future session and export globals, in addition to the reordering +of stdout and message output, resulting in messy and less +informative print statements intended for the user.

+
+
+

Tweaks +

+

The package implements sequential, multicore, multisession, and +cluster futures. SeuratIntegrate only uses the multicore +and multisession ones. DoIntegrate() automatically picks +the preferred one based on the output of

+
+parallelly::supportsMulticore()
+
## [1] FALSE
+

Here multicore is not supported, thus DoIntegrate() +would start a multisession. Further explanations regarding settings +giving priority to multicore are available in the function’s help (the +important part is in the disclosure widget +?supportsMulticore)

+
+help('supportsMulticore', package = 'parallelly')
+
?supportsMulticore +
+

Support for process forking + +

+

While R supports forked processing on Unix-like operating system such as +Linux and macOS, it does not on the Microsoft Windows operating system. +

+

For some R environments it is considered unstable to perform parallel +processing based on forking. +This is for example the case when using RStudio, cf. +RStudio Inc. recommends against using forked processing when running R from within the RStudio software. +This function detects when running in such an environment and returns +FALSE, despite the underlying operating system supports forked processing. +A warning will also be produced informing the user about this the first +time time this function is called in an R session. +This warning can be disabled by setting R option +parallelly.supportsMulticore.unstable, or environment variable +R_PARALLELLY_SUPPORTSMULTICORE_UNSTABLE to "quiet". +

+ + +

Enable or disable forked processing + +

+

It is possible to disable forked processing for futures by setting R +option parallelly.fork.enable to FALSE. Alternatively, one can +set environment variable R_PARALLELLY_FORK_ENABLE to false. +Analogously, it is possible to override disabled forking by setting one +of these to TRUE. +

+ +
+


In a nutshell, multicore is

+
    +
  • unavailable on Windows
  • +
  • discouraged (considered unstable) in some R environments, notably +RStudio
  • +
  • always used on Unix-like operating systems when +options(parallelly.fork.enable = TRUE) +
  • +
+

The main reason for using multicore is that FORKing is considered to +be faster and result in a lower memory overhead than PSOCK +(i.e. multisession) (see there +for technical details)

+

Furthermore, DoIntegrate() uses not only future, but +also NSE (non-standard evaluation), enabling to specify arguments within +each integration function call. Briefly, each call inside +DoIntegrate() (such as +DoIntegrate(bbknnIntegration())) is not directly executed +but captured to be executed later on (so that the proper value +for the object parameter can be passed on to +bbknnIntegration for instance). Further details are +available in the book Advanced +R by Hadley Wickham.

+

The important part is that, unlike for multicore, on a multisession +future, DoIntegrate() evaluates each argument before +launching the integration on the background R session. Thus, a Seurat +Assay object is passed as a structure (output of +str(object)). This takes time and makes the call extremely +long.

+

It has a unexpected side-effect. It slows down +CCAIntegration and RPCAIntegration a lot when +they are input with Seurat objects normalised with +SCTransform(). Indeed, they both call +FindIntegrationAnchors() -> merge() -> +merge.SCTAssay(). The latter performs a grep +on the previous calls (output of sys.calls()). In a +multisession future, big objects such as the Seurat Assay object are +passed as a structure and the grep can be +unnecessarily time-consuming. To avoid this, one can either specify +use.future = FALSE for the R-based method (this is always +preferable) or at least ban the use of CCA and +RPCA integrations with a multisession future (note that +Windows users can only pick the first option).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + +
+ + + + + + + diff --git a/authors.html b/authors.html new file mode 100644 index 0000000..de345a5 --- /dev/null +++ b/authors.html @@ -0,0 +1,104 @@ + +Authors and Citation • SeuratIntegrate + Skip to contents + + +
+
+
+ +
+

Authors

+ +
  • +

    Florian Specque. Author, maintainer. +

    +
  • +
  • +

    Domitille Chalopin. Author. +

    +
  • +
  • +

    Macha Nikolski. Reviewer. +

    +
  • +
  • +

    Aurélien Barré. Contributor. +

    +
  • +
  • +

    Centre de Bioinformatique de Bordeaux (CBiB). Copyright holder. +

    +
  • +
+ +
+

Citation

+

Source: DESCRIPTION

+ +

Specque F, Chalopin D (2025). +SeuratIntegrate: Expands the set of integration methods available to Seurat. +R package version 0.4.0, https://cbib.github.io/Seurat-Integrate/, https://github.com/cbib/Seurat-Integrate. +

+
@Manual{,
+  title = {SeuratIntegrate: Expands the set of integration methods available to Seurat},
+  author = {Florian Specque and Domitille Chalopin},
+  year = {2025},
+  note = {R package version 0.4.0, https://cbib.github.io/Seurat-Integrate/},
+  url = {https://github.com/cbib/Seurat-Integrate},
+}
+
+ +
+ + +
+ + + + + + + diff --git a/deps/bootstrap-5.3.1/bootstrap.bundle.min.js b/deps/bootstrap-5.3.1/bootstrap.bundle.min.js new file mode 100644 index 0000000..e8f21f7 --- /dev/null +++ b/deps/bootstrap-5.3.1/bootstrap.bundle.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),s=t=>{t.dispatchEvent(new Event(i))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},g=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,_=(t,e,n=!0)=>{if(!n)return void g(t);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),g(t))};e.addEventListener(i,a),setTimeout((()=>{r||s(e)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=I(t);return C.has(o)||(o=t),[n,s,o]}function S(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return P(s,{delegateTarget:r}),n.oneOff&&N.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return P(n,{delegateTarget:t}),i.oneOff&&N.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function D(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function $(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&D(t,e,i,r.callable,r.delegationSelector)}function I(t){return t=t.replace(y,""),T[t]||t}const N={on(t,e,i,n){S(t,e,i,n,!1)},one(t,e,i,n){S(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))$(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(w,"");a&&!e.includes(s)||D(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==I(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=P(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function P(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function j(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const F={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${j(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${j(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${j(e)}`))};class H{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?F.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?F.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`)}var i}}class W extends H{constructor(t,i){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),N.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.1"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const B=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return n(e)},z={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=B(t);return e&&z.findOne(e)?e:null},getElementFromSelector(t){const e=B(t);return e?z.findOne(e):null},getMultipleElementsFromSelector(t){const e=B(t);return e?z.find(e):[]}},R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;N.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const s=z.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},q=".bs.alert",V=`close${q}`,K=`closed${q}`;class Q extends W{static get NAME(){return"alert"}close(){if(N.trigger(this._element,V).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),N.trigger(this._element,K),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Q.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(Q,"close"),m(Q);const X='[data-bs-toggle="button"]';class Y extends W{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=Y.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}N.on(document,"click.bs.button.data-api",X,(t=>{t.preventDefault();const e=t.target.closest(X);Y.getOrCreateInstance(e).toggle()})),m(Y);const U=".bs.swipe",G=`touchstart${U}`,J=`touchmove${U}`,Z=`touchend${U}`,tt=`pointerdown${U}`,et=`pointerup${U}`,it={endCallback:null,leftCallback:null,rightCallback:null},nt={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class st extends H{constructor(t,e){super(),this._element=t,t&&st.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return it}static get DefaultType(){return nt}static get NAME(){return"swipe"}dispose(){N.off(this._element,U)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),g(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&g(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(N.on(this._element,tt,(t=>this._start(t))),N.on(this._element,et,(t=>this._end(t))),this._element.classList.add("pointer-event")):(N.on(this._element,G,(t=>this._start(t))),N.on(this._element,J,(t=>this._move(t))),N.on(this._element,Z,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const ot=".bs.carousel",rt=".data-api",at="next",lt="prev",ct="left",ht="right",dt=`slide${ot}`,ut=`slid${ot}`,ft=`keydown${ot}`,pt=`mouseenter${ot}`,mt=`mouseleave${ot}`,gt=`dragstart${ot}`,_t=`load${ot}${rt}`,bt=`click${ot}${rt}`,vt="carousel",yt="active",wt=".active",At=".carousel-item",Et=wt+At,Tt={ArrowLeft:ht,ArrowRight:ct},Ct={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Ot={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class xt extends W{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=z.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===vt&&this.cycle()}static get Default(){return Ct}static get DefaultType(){return Ot}static get NAME(){return"carousel"}next(){this._slide(at)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(lt)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?N.one(this._element,ut,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void N.one(this._element,ut,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?at:lt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&N.on(this._element,ft,(t=>this._keydown(t))),"hover"===this._config.pause&&(N.on(this._element,pt,(()=>this.pause())),N.on(this._element,mt,(()=>this._maybeEnableCycle()))),this._config.touch&&st.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of z.find(".carousel-item img",this._element))N.on(t,gt,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(ct)),rightCallback:()=>this._slide(this._directionToOrder(ht)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new st(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=Tt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=z.findOne(wt,this._indicatorsElement);e.classList.remove(yt),e.removeAttribute("aria-current");const i=z.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(yt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===at,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>N.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(dt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(yt),i.classList.remove(yt,c,l),this._isSliding=!1,r(ut)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return z.findOne(Et,this._element)}_getItems(){return z.find(At,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===ct?lt:at:t===ct?at:lt}_orderToDirection(t){return p()?t===lt?ct:ht:t===lt?ht:ct}static jQueryInterface(t){return this.each((function(){const e=xt.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}N.on(document,bt,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=z.getElementFromSelector(this);if(!e||!e.classList.contains(vt))return;t.preventDefault();const i=xt.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===F.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),N.on(window,_t,(()=>{const t=z.find('[data-bs-ride="carousel"]');for(const e of t)xt.getOrCreateInstance(e)})),m(xt);const kt=".bs.collapse",Lt=`show${kt}`,St=`shown${kt}`,Dt=`hide${kt}`,$t=`hidden${kt}`,It=`click${kt}.data-api`,Nt="show",Pt="collapse",Mt="collapsing",jt=`:scope .${Pt} .${Pt}`,Ft='[data-bs-toggle="collapse"]',Ht={parent:null,toggle:!0},Wt={parent:"(null|element)",toggle:"boolean"};class Bt extends W{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=z.find(Ft);for(const t of i){const e=z.getSelectorFromElement(t),i=z.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Ht}static get DefaultType(){return Wt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>Bt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(N.trigger(this._element,Lt).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Pt),this._element.classList.add(Mt),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt,Nt),this._element.style[e]="",N.trigger(this._element,St)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(N.trigger(this._element,Dt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(Mt),this._element.classList.remove(Pt,Nt);for(const t of this._triggerArray){const e=z.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt),N.trigger(this._element,$t)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(Nt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Ft);for(const e of t){const t=z.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=z.find(jt,this._config.parent);return z.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=Bt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}N.on(document,It,Ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of z.getMultipleElementsFromSelector(this))Bt.getOrCreateInstance(t,{toggle:!1}).toggle()})),m(Bt);var zt="top",Rt="bottom",qt="right",Vt="left",Kt="auto",Qt=[zt,Rt,qt,Vt],Xt="start",Yt="end",Ut="clippingParents",Gt="viewport",Jt="popper",Zt="reference",te=Qt.reduce((function(t,e){return t.concat([e+"-"+Xt,e+"-"+Yt])}),[]),ee=[].concat(Qt,[Kt]).reduce((function(t,e){return t.concat([e,e+"-"+Xt,e+"-"+Yt])}),[]),ie="beforeRead",ne="read",se="afterRead",oe="beforeMain",re="main",ae="afterMain",le="beforeWrite",ce="write",he="afterWrite",de=[ie,ne,se,oe,re,ae,le,ce,he];function ue(t){return t?(t.nodeName||"").toLowerCase():null}function fe(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function pe(t){return t instanceof fe(t).Element||t instanceof Element}function me(t){return t instanceof fe(t).HTMLElement||t instanceof HTMLElement}function ge(t){return"undefined"!=typeof ShadowRoot&&(t instanceof fe(t).ShadowRoot||t instanceof ShadowRoot)}const _e={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];me(s)&&ue(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});me(n)&&ue(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function be(t){return t.split("-")[0]}var ve=Math.max,ye=Math.min,we=Math.round;function Ae(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ee(){return!/^((?!chrome|android).)*safari/i.test(Ae())}function Te(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&me(t)&&(s=t.offsetWidth>0&&we(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&we(n.height)/t.offsetHeight||1);var r=(pe(t)?fe(t):window).visualViewport,a=!Ee()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Ce(t){var e=Te(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Oe(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ge(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function xe(t){return fe(t).getComputedStyle(t)}function ke(t){return["table","td","th"].indexOf(ue(t))>=0}function Le(t){return((pe(t)?t.ownerDocument:t.document)||window.document).documentElement}function Se(t){return"html"===ue(t)?t:t.assignedSlot||t.parentNode||(ge(t)?t.host:null)||Le(t)}function De(t){return me(t)&&"fixed"!==xe(t).position?t.offsetParent:null}function $e(t){for(var e=fe(t),i=De(t);i&&ke(i)&&"static"===xe(i).position;)i=De(i);return i&&("html"===ue(i)||"body"===ue(i)&&"static"===xe(i).position)?e:i||function(t){var e=/firefox/i.test(Ae());if(/Trident/i.test(Ae())&&me(t)&&"fixed"===xe(t).position)return null;var i=Se(t);for(ge(i)&&(i=i.host);me(i)&&["html","body"].indexOf(ue(i))<0;){var n=xe(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function Ie(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Ne(t,e,i){return ve(t,ye(e,i))}function Pe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function Me(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const je={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=be(i.placement),l=Ie(a),c=[Vt,qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Pe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:Me(t,Qt))}(s.padding,i),d=Ce(o),u="y"===l?zt:Vt,f="y"===l?Rt:qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=$e(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Ne(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Oe(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Fe(t){return t.split("-")[1]}var He={top:"auto",right:"auto",bottom:"auto",left:"auto"};function We(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Vt,y=zt,w=window;if(c){var A=$e(i),E="clientHeight",T="clientWidth";A===fe(i)&&"static"!==xe(A=Le(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===zt||(s===Vt||s===qt)&&o===Yt)&&(y=Rt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Vt&&(s!==zt&&s!==Rt||o!==Yt)||(v=qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&He),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:we(i*s)/s||0,y:we(n*s)/s||0}}({x:f,y:m},fe(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const Be={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:be(e.placement),variation:Fe(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,We(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,We(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ze={passive:!0};const Re={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=fe(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ze)})),a&&l.addEventListener("resize",i.update,ze),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ze)})),a&&l.removeEventListener("resize",i.update,ze)}},data:{}};var qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Ve(t){return t.replace(/left|right|bottom|top/g,(function(t){return qe[t]}))}var Ke={start:"end",end:"start"};function Qe(t){return t.replace(/start|end/g,(function(t){return Ke[t]}))}function Xe(t){var e=fe(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ye(t){return Te(Le(t)).left+Xe(t).scrollLeft}function Ue(t){var e=xe(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ge(t){return["html","body","#document"].indexOf(ue(t))>=0?t.ownerDocument.body:me(t)&&Ue(t)?t:Ge(Se(t))}function Je(t,e){var i;void 0===e&&(e=[]);var n=Ge(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=fe(n),r=s?[o].concat(o.visualViewport||[],Ue(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Je(Se(r)))}function Ze(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ti(t,e,i){return e===Gt?Ze(function(t,e){var i=fe(t),n=Le(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ee();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ye(t),y:l}}(t,i)):pe(e)?function(t,e){var i=Te(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Ze(function(t){var e,i=Le(t),n=Xe(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ve(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ve(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ye(t),l=-n.scrollTop;return"rtl"===xe(s||i).direction&&(a+=ve(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Le(t)))}function ei(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?be(s):null,r=s?Fe(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case zt:e={x:a,y:i.y-n.height};break;case Rt:e={x:a,y:i.y+i.height};break;case qt:e={x:i.x+i.width,y:l};break;case Vt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?Ie(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Xt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Yt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ii(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Ut:a,c=i.rootBoundary,h=void 0===c?Gt:c,d=i.elementContext,u=void 0===d?Jt:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Pe("number"!=typeof g?g:Me(g,Qt)),b=u===Jt?Zt:Jt,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Je(Se(t)),i=["absolute","fixed"].indexOf(xe(t).position)>=0&&me(t)?$e(t):t;return pe(i)?e.filter((function(t){return pe(t)&&Oe(t,i)&&"body"!==ue(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=ti(t,i,n);return e.top=ve(s.top,e.top),e.right=ye(s.right,e.right),e.bottom=ye(s.bottom,e.bottom),e.left=ve(s.left,e.left),e}),ti(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(pe(y)?y:y.contextElement||Le(t.elements.popper),l,h,r),A=Te(t.elements.reference),E=ei({reference:A,element:v,strategy:"absolute",placement:s}),T=Ze(Object.assign({},v,E)),C=u===Jt?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Jt&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[qt,Rt].indexOf(t)>=0?1:-1,i=[zt,Rt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function ni(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?ee:l,h=Fe(n),d=h?a?te:te.filter((function(t){return Fe(t)===h})):Qt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ii(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[be(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const si={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=be(g),b=l||(_!==g&&p?function(t){if(be(t)===Kt)return[];var e=Ve(t);return[Qe(t),e,Qe(e)]}(g):[Ve(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(be(i)===Kt?ni(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=ii(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?qt:Vt:k?Rt:zt;y[S]>w[S]&&($=Ve($));var I=Ve($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every((function(t){return t}))){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==P(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function oi(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ri(t){return[zt,qt,Rt,Vt].some((function(e){return t[e]>=0}))}const ai={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ii(e,{elementContext:"reference"}),a=ii(e,{altBoundary:!0}),l=oi(r,n),c=oi(a,s,o),h=ri(l),d=ri(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},li={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=ee.reduce((function(t,i){return t[i]=function(t,e,i){var n=be(t),s=[Vt,zt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Vt,qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ci={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ei({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},hi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ii(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=be(e.placement),b=Fe(e.placement),v=!b,y=Ie(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?zt:Vt,D="y"===y?Rt:qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],M=f?-T[$]/2:0,j=b===Xt?E[$]:T[$],F=b===Xt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?Ce(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Ne(0,E[$],W[$]),V=v?E[$]/2-M-q-z-O.mainAxis:j-q-z-O.mainAxis,K=v?-E[$]/2+M+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&$e(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Ne(f?ye(N,I+V-Y-X):N,I,f?ve(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?zt:Vt,tt="x"===y?Rt:qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[zt,Vt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Ne(t,e,i);return n>i?i:n}(at,et,lt):Ne(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function di(t,e,i){void 0===i&&(i=!1);var n,s,o=me(e),r=me(e)&&function(t){var e=t.getBoundingClientRect(),i=we(e.width)/t.offsetWidth||1,n=we(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=Le(e),l=Te(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==ue(e)||Ue(a))&&(c=(n=e)!==fe(n)&&me(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Xe(n)),me(e)?((h=Te(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ye(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function ui(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var fi={placement:"bottom",modifiers:[],strategy:"absolute"};function pi(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(F.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...g(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ti,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=z.find(Ni);for(const i of e){const e=qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ei,Ti].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ii)?this:z.prev(this,Ii)[0]||z.next(this,Ii)[0]||z.findOne(Ii,t.delegateTarget.parentNode),o=qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}N.on(document,Si,Ii,qi.dataApiKeydownHandler),N.on(document,Si,Pi,qi.dataApiKeydownHandler),N.on(document,Li,qi.clearMenus),N.on(document,Di,qi.clearMenus),N.on(document,Li,Ii,(function(t){t.preventDefault(),qi.getOrCreateInstance(this).toggle()})),m(qi);const Vi="backdrop",Ki="show",Qi=`mousedown.bs.${Vi}`,Xi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Yi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Ui extends H{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return Vi}show(t){if(!this._config.isVisible)return void g(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(Ki),this._emulateAnimation((()=>{g(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Ki),this._emulateAnimation((()=>{this.dispose(),g(t)}))):g(t)}dispose(){this._isAppended&&(N.off(this._element,Qi),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),N.on(t,Qi,(()=>{g(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const Gi=".bs.focustrap",Ji=`focusin${Gi}`,Zi=`keydown.tab${Gi}`,tn="backward",en={autofocus:!0,trapElement:null},nn={autofocus:"boolean",trapElement:"element"};class sn extends H{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return en}static get DefaultType(){return nn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),N.off(document,Gi),N.on(document,Ji,(t=>this._handleFocusin(t))),N.on(document,Zi,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,N.off(document,Gi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=z.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===tn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?tn:"forward")}}const on=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",rn=".sticky-top",an="padding-right",ln="margin-right";class cn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,an,(e=>e+t)),this._setElementAttributes(on,an,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,an),this._resetElementAttributes(on,an),this._resetElementAttributes(rn,ln)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&F.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=F.getDataAttribute(t,e);null!==i?(F.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of z.find(t,this._element))e(i)}}const hn=".bs.modal",dn=`hide${hn}`,un=`hidePrevented${hn}`,fn=`hidden${hn}`,pn=`show${hn}`,mn=`shown${hn}`,gn=`resize${hn}`,_n=`click.dismiss${hn}`,bn=`mousedown.dismiss${hn}`,vn=`keydown.dismiss${hn}`,yn=`click${hn}.data-api`,wn="modal-open",An="show",En="modal-static",Tn={backdrop:!0,focus:!0,keyboard:!0},Cn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class On extends W{constructor(t,e){super(t,e),this._dialog=z.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cn,this._addEventListeners()}static get Default(){return Tn}static get DefaultType(){return Cn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||N.trigger(this._element,pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(wn),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(N.trigger(this._element,dn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(An),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){N.off(window,hn),N.off(this._dialog,hn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Ui({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=z.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(An),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,N.trigger(this._element,mn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){N.on(this._element,vn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),N.on(window,gn,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),N.on(this._element,bn,(t=>{N.one(this._element,_n,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(wn),this._resetAdjustments(),this._scrollBar.reset(),N.trigger(this._element,fn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(N.trigger(this._element,un).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(En)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(En),this._queueCallback((()=>{this._element.classList.remove(En),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=On.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}N.on(document,yn,'[data-bs-toggle="modal"]',(function(t){const e=z.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),N.one(e,pn,(t=>{t.defaultPrevented||N.one(e,fn,(()=>{a(this)&&this.focus()}))}));const i=z.findOne(".modal.show");i&&On.getInstance(i).hide(),On.getOrCreateInstance(e).toggle(this)})),R(On),m(On);const xn=".bs.offcanvas",kn=".data-api",Ln=`load${xn}${kn}`,Sn="show",Dn="showing",$n="hiding",In=".offcanvas.show",Nn=`show${xn}`,Pn=`shown${xn}`,Mn=`hide${xn}`,jn=`hidePrevented${xn}`,Fn=`hidden${xn}`,Hn=`resize${xn}`,Wn=`click${xn}${kn}`,Bn=`keydown.dismiss${xn}`,zn={backdrop:!0,keyboard:!0,scroll:!1},Rn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class qn extends W{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zn}static get DefaultType(){return Rn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||N.trigger(this._element,Nn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Dn),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Sn),this._element.classList.remove(Dn),N.trigger(this._element,Pn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(N.trigger(this._element,Mn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add($n),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Sn,$n),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cn).reset(),N.trigger(this._element,Fn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Ui({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():N.trigger(this._element,jn)}:null})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_addEventListeners(){N.on(this._element,Bn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():N.trigger(this._element,jn))}))}static jQueryInterface(t){return this.each((function(){const e=qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}N.on(document,Wn,'[data-bs-toggle="offcanvas"]',(function(t){const e=z.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;N.one(e,Fn,(()=>{a(this)&&this.focus()}));const i=z.findOne(In);i&&i!==e&&qn.getInstance(i).hide(),qn.getOrCreateInstance(e).toggle(this)})),N.on(window,Ln,(()=>{for(const t of z.find(In))qn.getOrCreateInstance(t).show()})),N.on(window,Hn,(()=>{for(const t of z.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&qn.getOrCreateInstance(t).hide()})),R(qn),m(qn);const Vn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Qn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Kn.has(i)||Boolean(Qn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Yn={allowList:Vn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Un={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Gn={entry:"(string|element|function|null)",selector:"(string|element)"};class Jn extends H{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Yn}static get DefaultType(){return Un}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Gn)}_setContent(t,e,i){const n=z.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Xn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return g(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Zn=new Set(["sanitize","allowList","sanitizeFn"]),ts="fade",es="show",is=".modal",ns="hide.bs.modal",ss="hover",os="focus",rs={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},as={allowList:Vn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ls={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cs extends W{constructor(t,e){if(void 0===vi)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return as}static get DefaultType(){return ls}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),N.off(this._element.closest(is),ns,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=N.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),N.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.on(t,"mouseover",h);this._queueCallback((()=>{N.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!N.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger[os]=!1,this._activeTrigger[ss]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),N.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ts,es),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ts),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Jn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ts)}_isShown(){return this.tip&&this.tip.classList.contains(es)}_createPopper(t){const e=g(this._config.placement,[this,t,this._element]),i=rs[e.toUpperCase()];return bi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return g(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...g(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)N.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===ss?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ss?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");N.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?os:ss]=!0,e._enter()})),N.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?os:ss]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},N.on(this._element.closest(is),ns,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=F.getDataAttributes(this._element);for(const t of Object.keys(e))Zn.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(cs);const hs={...cs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},ds={...cs.DefaultType,content:"(null|string|element|function)"};class us extends cs{static get Default(){return hs}static get DefaultType(){return ds}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=us.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(us);const fs=".bs.scrollspy",ps=`activate${fs}`,ms=`click${fs}`,gs=`load${fs}.data-api`,_s="active",bs="[href]",vs=".nav-link",ys=`${vs}, .nav-item > ${vs}, .list-group-item`,ws={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},As={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Es extends W{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ws}static get DefaultType(){return As}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(N.off(this._config.target,ms),N.on(this._config.target,ms,bs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=z.find(bs,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=z.findOne(decodeURI(e.hash),this._element);a(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(_s),this._activateParents(t),N.trigger(this._element,ps,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))z.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(_s);else for(const e of z.parents(t,".nav, .list-group"))for(const t of z.prev(e,ys))t.classList.add(_s)}_clearActiveClass(t){t.classList.remove(_s);const e=z.find(`${bs}.${_s}`,t);for(const t of e)t.classList.remove(_s)}static jQueryInterface(t){return this.each((function(){const e=Es.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(window,gs,(()=>{for(const t of z.find('[data-bs-spy="scroll"]'))Es.getOrCreateInstance(t)})),m(Es);const Ts=".bs.tab",Cs=`hide${Ts}`,Os=`hidden${Ts}`,xs=`show${Ts}`,ks=`shown${Ts}`,Ls=`click${Ts}`,Ss=`keydown${Ts}`,Ds=`load${Ts}`,$s="ArrowLeft",Is="ArrowRight",Ns="ArrowUp",Ps="ArrowDown",Ms="Home",js="End",Fs="active",Hs="fade",Ws="show",Bs=":not(.dropdown-toggle)",zs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Rs=`.nav-link${Bs}, .list-group-item${Bs}, [role="tab"]${Bs}, ${zs}`,qs=`.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`;class Vs extends W{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),N.on(this._element,Ss,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?N.trigger(e,Cs,{relatedTarget:t}):null;N.trigger(t,xs,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Fs),this._activate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),N.trigger(t,ks,{relatedTarget:e})):t.classList.add(Ws)}),t,t.classList.contains(Hs)))}_deactivate(t,e){t&&(t.classList.remove(Fs),t.blur(),this._deactivate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),N.trigger(t,Os,{relatedTarget:e})):t.classList.remove(Ws)}),t,t.classList.contains(Hs)))}_keydown(t){if(![$s,Is,Ns,Ps,Ms,js].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!l(t)));let i;if([Ms,js].includes(t.key))i=e[t.key===Ms?0:e.length-1];else{const n=[Is,Ps].includes(t.key);i=b(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Vs.getOrCreateInstance(i).show())}_getChildren(){return z.find(Rs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=z.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=z.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",Fs),n(".dropdown-menu",Ws),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Fs)}_getInnerElement(t){return t.matches(Rs)?t:z.findOne(Rs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Vs.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(document,Ls,zs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||Vs.getOrCreateInstance(this).show()})),N.on(window,Ds,(()=>{for(const t of z.find(qs))Vs.getOrCreateInstance(t)})),m(Vs);const Ks=".bs.toast",Qs=`mouseover${Ks}`,Xs=`mouseout${Ks}`,Ys=`focusin${Ks}`,Us=`focusout${Ks}`,Gs=`hide${Ks}`,Js=`hidden${Ks}`,Zs=`show${Ks}`,to=`shown${Ks}`,eo="hide",io="show",no="showing",so={animation:"boolean",autohide:"boolean",delay:"number"},oo={animation:!0,autohide:!0,delay:5e3};class ro extends W{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return oo}static get DefaultType(){return so}static get NAME(){return"toast"}show(){N.trigger(this._element,Zs).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(eo),d(this._element),this._element.classList.add(io,no),this._queueCallback((()=>{this._element.classList.remove(no),N.trigger(this._element,to),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(N.trigger(this._element,Gs).defaultPrevented||(this._element.classList.add(no),this._queueCallback((()=>{this._element.classList.add(eo),this._element.classList.remove(no,io),N.trigger(this._element,Js)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(io),super.dispose()}isShown(){return this._element.classList.contains(io)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){N.on(this._element,Qs,(t=>this._onInteraction(t,!0))),N.on(this._element,Xs,(t=>this._onInteraction(t,!1))),N.on(this._element,Ys,(t=>this._onInteraction(t,!0))),N.on(this._element,Us,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=ro.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(ro),m(ro),{Alert:Q,Button:Y,Carousel:xt,Collapse:Bt,Dropdown:qi,Modal:On,Offcanvas:qn,Popover:us,ScrollSpy:Es,Tab:Vs,Toast:ro,Tooltip:cs}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/deps/bootstrap-5.3.1/bootstrap.bundle.min.js.map b/deps/bootstrap-5.3.1/bootstrap.bundle.min.js.map new file mode 100644 index 0000000..3863da8 --- /dev/null +++ b/deps/bootstrap-5.3.1/bootstrap.bundle.min.js.map @@ -0,0 +1 @@ +{"version":3,"names":["elementMap","Map","Data","set","element","key","instance","has","instanceMap","get","size","console","error","Array","from","keys","remove","delete","TRANSITION_END","parseSelector","selector","window","CSS","escape","replace","match","id","triggerTransitionEnd","dispatchEvent","Event","isElement","object","jquery","nodeType","getElement","length","document","querySelector","isVisible","getClientRects","elementIsVisible","getComputedStyle","getPropertyValue","closedDetails","closest","summary","parentNode","isDisabled","Node","ELEMENT_NODE","classList","contains","disabled","hasAttribute","getAttribute","findShadowRoot","documentElement","attachShadow","getRootNode","root","ShadowRoot","noop","reflow","offsetHeight","getjQuery","jQuery","body","DOMContentLoadedCallbacks","isRTL","dir","defineJQueryPlugin","plugin","callback","$","name","NAME","JQUERY_NO_CONFLICT","fn","jQueryInterface","Constructor","noConflict","readyState","addEventListener","push","execute","possibleCallback","args","defaultValue","executeAfterTransition","transitionElement","waitForTransition","emulatedDuration","transitionDuration","transitionDelay","floatTransitionDuration","Number","parseFloat","floatTransitionDelay","split","getTransitionDurationFromElement","called","handler","target","removeEventListener","setTimeout","getNextActiveElement","list","activeElement","shouldGetNext","isCycleAllowed","listLength","index","indexOf","Math","max","min","namespaceRegex","stripNameRegex","stripUidRegex","eventRegistry","uidEvent","customEvents","mouseenter","mouseleave","nativeEvents","Set","makeEventUid","uid","getElementEvents","findHandler","events","callable","delegationSelector","Object","values","find","event","normalizeParameters","originalTypeEvent","delegationFunction","isDelegated","typeEvent","getTypeEvent","addHandler","oneOff","wrapFunction","relatedTarget","delegateTarget","call","this","handlers","previousFunction","domElements","querySelectorAll","domElement","hydrateObj","EventHandler","off","type","apply","bootstrapDelegationHandler","bootstrapHandler","removeHandler","Boolean","removeNamespacedHandlers","namespace","storeElementEvent","handlerKey","entries","includes","on","one","inNamespace","isNamespace","startsWith","elementEvent","slice","keyHandlers","trigger","jQueryEvent","bubbles","nativeDispatch","defaultPrevented","isPropagationStopped","isImmediatePropagationStopped","isDefaultPrevented","evt","cancelable","preventDefault","obj","meta","value","_unused","defineProperty","configurable","normalizeData","toString","JSON","parse","decodeURIComponent","normalizeDataKey","chr","toLowerCase","Manipulator","setDataAttribute","setAttribute","removeDataAttribute","removeAttribute","getDataAttributes","attributes","bsKeys","dataset","filter","pureKey","charAt","getDataAttribute","Config","Default","DefaultType","Error","_getConfig","config","_mergeConfigObj","_configAfterMerge","_typeCheckConfig","jsonConfig","constructor","configTypes","property","expectedTypes","valueType","prototype","RegExp","test","TypeError","toUpperCase","BaseComponent","super","_element","_config","DATA_KEY","dispose","EVENT_KEY","propertyName","getOwnPropertyNames","_queueCallback","isAnimated","getInstance","getOrCreateInstance","VERSION","eventName","getSelector","hrefAttribute","trim","SelectorEngine","concat","Element","findOne","children","child","matches","parents","ancestor","prev","previous","previousElementSibling","next","nextElementSibling","focusableChildren","focusables","map","join","el","getSelectorFromElement","getElementFromSelector","getMultipleElementsFromSelector","enableDismissTrigger","component","method","clickEvent","tagName","EVENT_CLOSE","EVENT_CLOSED","Alert","close","_destroyElement","each","data","undefined","SELECTOR_DATA_TOGGLE","Button","toggle","button","EVENT_TOUCHSTART","EVENT_TOUCHMOVE","EVENT_TOUCHEND","EVENT_POINTERDOWN","EVENT_POINTERUP","endCallback","leftCallback","rightCallback","Swipe","isSupported","_deltaX","_supportPointerEvents","PointerEvent","_initEvents","_start","_eventIsPointerPenTouch","clientX","touches","_end","_handleSwipe","_move","absDeltaX","abs","direction","add","pointerType","navigator","maxTouchPoints","DATA_API_KEY","ORDER_NEXT","ORDER_PREV","DIRECTION_LEFT","DIRECTION_RIGHT","EVENT_SLIDE","EVENT_SLID","EVENT_KEYDOWN","EVENT_MOUSEENTER","EVENT_MOUSELEAVE","EVENT_DRAG_START","EVENT_LOAD_DATA_API","EVENT_CLICK_DATA_API","CLASS_NAME_CAROUSEL","CLASS_NAME_ACTIVE","SELECTOR_ACTIVE","SELECTOR_ITEM","SELECTOR_ACTIVE_ITEM","KEY_TO_DIRECTION","ArrowLeft","ArrowRight","interval","keyboard","pause","ride","touch","wrap","Carousel","_interval","_activeElement","_isSliding","touchTimeout","_swipeHelper","_indicatorsElement","_addEventListeners","cycle","_slide","nextWhenVisible","hidden","_clearInterval","_updateInterval","setInterval","_maybeEnableCycle","to","items","_getItems","activeIndex","_getItemIndex","_getActive","order","defaultInterval","_keydown","_addTouchEventListeners","img","swipeConfig","_directionToOrder","endCallBack","clearTimeout","_setActiveIndicatorElement","activeIndicator","newActiveIndicator","elementInterval","parseInt","isNext","nextElement","nextElementIndex","triggerEvent","_orderToDirection","isCycling","directionalClassName","orderClassName","completeCallBack","_isAnimated","clearInterval","carousel","slideIndex","carousels","EVENT_SHOW","EVENT_SHOWN","EVENT_HIDE","EVENT_HIDDEN","CLASS_NAME_SHOW","CLASS_NAME_COLLAPSE","CLASS_NAME_COLLAPSING","CLASS_NAME_DEEPER_CHILDREN","parent","Collapse","_isTransitioning","_triggerArray","toggleList","elem","filterElement","foundElement","_initializeChildren","_addAriaAndCollapsedClass","_isShown","hide","show","activeChildren","_getFirstLevelChildren","activeInstance","dimension","_getDimension","style","scrollSize","complete","getBoundingClientRect","selected","triggerArray","isOpen","top","bottom","right","left","auto","basePlacements","start","end","clippingParents","viewport","popper","reference","variationPlacements","reduce","acc","placement","placements","beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite","modifierPhases","getNodeName","nodeName","getWindow","node","ownerDocument","defaultView","isHTMLElement","HTMLElement","isShadowRoot","applyStyles$1","enabled","phase","_ref","state","elements","forEach","styles","assign","effect","_ref2","initialStyles","position","options","strategy","margin","arrow","hasOwnProperty","attribute","requires","getBasePlacement","round","getUAString","uaData","userAgentData","brands","isArray","item","brand","version","userAgent","isLayoutViewport","includeScale","isFixedStrategy","clientRect","scaleX","scaleY","offsetWidth","width","height","visualViewport","addVisualOffsets","x","offsetLeft","y","offsetTop","getLayoutRect","rootNode","isSameNode","host","isTableElement","getDocumentElement","getParentNode","assignedSlot","getTrueOffsetParent","offsetParent","getOffsetParent","isFirefox","currentNode","css","transform","perspective","contain","willChange","getContainingBlock","getMainAxisFromPlacement","within","mathMax","mathMin","mergePaddingObject","paddingObject","expandToHashMap","hashMap","arrow$1","_state$modifiersData$","arrowElement","popperOffsets","modifiersData","basePlacement","axis","len","padding","rects","toPaddingObject","arrowRect","minProp","maxProp","endDiff","startDiff","arrowOffsetParent","clientSize","clientHeight","clientWidth","centerToReference","center","offset","axisProp","centerOffset","_options$element","requiresIfExists","getVariation","unsetSides","mapToStyles","_Object$assign2","popperRect","variation","offsets","gpuAcceleration","adaptive","roundOffsets","isFixed","_offsets$x","_offsets$y","_ref3","hasX","hasY","sideX","sideY","win","heightProp","widthProp","_Object$assign","commonStyles","_ref4","dpr","devicePixelRatio","roundOffsetsByDPR","computeStyles$1","_ref5","_options$gpuAccelerat","_options$adaptive","_options$roundOffsets","passive","eventListeners","_options$scroll","scroll","_options$resize","resize","scrollParents","scrollParent","update","hash","getOppositePlacement","matched","getOppositeVariationPlacement","getWindowScroll","scrollLeft","pageXOffset","scrollTop","pageYOffset","getWindowScrollBarX","isScrollParent","_getComputedStyle","overflow","overflowX","overflowY","getScrollParent","listScrollParents","_element$ownerDocumen","isBody","updatedList","rectToClientRect","rect","getClientRectFromMixedType","clippingParent","html","layoutViewport","getViewportRect","clientTop","clientLeft","getInnerBoundingClientRect","winScroll","scrollWidth","scrollHeight","getDocumentRect","computeOffsets","commonX","commonY","mainAxis","detectOverflow","_options","_options$placement","_options$strategy","_options$boundary","boundary","_options$rootBoundary","rootBoundary","_options$elementConte","elementContext","_options$altBoundary","altBoundary","_options$padding","altContext","clippingClientRect","mainClippingParents","clipperElement","getClippingParents","firstClippingParent","clippingRect","accRect","getClippingRect","contextElement","referenceClientRect","popperClientRect","elementClientRect","overflowOffsets","offsetData","multiply","computeAutoPlacement","flipVariations","_options$allowedAutoP","allowedAutoPlacements","allPlacements","allowedPlacements","overflows","sort","a","b","flip$1","_skip","_options$mainAxis","checkMainAxis","_options$altAxis","altAxis","checkAltAxis","specifiedFallbackPlacements","fallbackPlacements","_options$flipVariatio","preferredPlacement","oppositePlacement","getExpandedFallbackPlacements","referenceRect","checksMap","makeFallbackChecks","firstFittingPlacement","i","_basePlacement","isStartVariation","isVertical","mainVariationSide","altVariationSide","checks","every","check","_loop","_i","fittingPlacement","reset","getSideOffsets","preventedOffsets","isAnySideFullyClipped","some","side","hide$1","preventOverflow","referenceOverflow","popperAltOverflow","referenceClippingOffsets","popperEscapeOffsets","isReferenceHidden","hasPopperEscaped","offset$1","_options$offset","invertDistance","skidding","distance","distanceAndSkiddingToXY","_data$state$placement","popperOffsets$1","preventOverflow$1","_options$tether","tether","_options$tetherOffset","tetherOffset","isBasePlacement","tetherOffsetValue","normalizedTetherOffsetValue","offsetModifierState","_offsetModifierState$","mainSide","altSide","additive","minLen","maxLen","arrowPaddingObject","arrowPaddingMin","arrowPaddingMax","arrowLen","minOffset","maxOffset","clientOffset","offsetModifierValue","tetherMax","preventedOffset","_offsetModifierState$2","_mainSide","_altSide","_offset","_len","_min","_max","isOriginSide","_offsetModifierValue","_tetherMin","_tetherMax","_preventedOffset","v","withinMaxClamp","getCompositeRect","elementOrVirtualElement","isOffsetParentAnElement","offsetParentIsScaled","isElementScaled","modifiers","visited","result","modifier","dep","depModifier","DEFAULT_OPTIONS","areValidElements","arguments","_key","popperGenerator","generatorOptions","_generatorOptions","_generatorOptions$def","defaultModifiers","_generatorOptions$def2","defaultOptions","pending","orderedModifiers","effectCleanupFns","isDestroyed","setOptions","setOptionsAction","cleanupModifierEffects","merged","orderModifiers","current","existing","m","_ref$options","cleanupFn","forceUpdate","_state$elements","_state$orderedModifie","_state$orderedModifie2","Promise","resolve","then","destroy","onFirstUpdate","createPopper","computeStyles","applyStyles","flip","ARROW_UP_KEY","ARROW_DOWN_KEY","EVENT_KEYDOWN_DATA_API","EVENT_KEYUP_DATA_API","SELECTOR_DATA_TOGGLE_SHOWN","SELECTOR_MENU","PLACEMENT_TOP","PLACEMENT_TOPEND","PLACEMENT_BOTTOM","PLACEMENT_BOTTOMEND","PLACEMENT_RIGHT","PLACEMENT_LEFT","autoClose","display","popperConfig","Dropdown","_popper","_parent","_menu","_inNavbar","_detectNavbar","_createPopper","focus","_completeHide","Popper","referenceElement","_getPopperConfig","_getPlacement","parentDropdown","isEnd","_getOffset","popperData","defaultBsPopperConfig","_selectMenuItem","clearMenus","openToggles","context","composedPath","isMenuTarget","dataApiKeydownHandler","isInput","isEscapeEvent","isUpOrDownEvent","getToggleButton","stopPropagation","EVENT_MOUSEDOWN","className","clickCallback","rootElement","Backdrop","_isAppended","_append","_getElement","_emulateAnimation","backdrop","createElement","append","EVENT_FOCUSIN","EVENT_KEYDOWN_TAB","TAB_NAV_BACKWARD","autofocus","trapElement","FocusTrap","_isActive","_lastTabNavDirection","activate","_handleFocusin","_handleKeydown","deactivate","shiftKey","SELECTOR_FIXED_CONTENT","SELECTOR_STICKY_CONTENT","PROPERTY_PADDING","PROPERTY_MARGIN","ScrollBarHelper","getWidth","documentWidth","innerWidth","_disableOverFlow","_setElementAttributes","calculatedValue","_resetElementAttributes","isOverflowing","_saveInitialAttribute","styleProperty","scrollbarWidth","_applyManipulationCallback","setProperty","actualValue","removeProperty","callBack","sel","EVENT_HIDE_PREVENTED","EVENT_RESIZE","EVENT_CLICK_DISMISS","EVENT_MOUSEDOWN_DISMISS","EVENT_KEYDOWN_DISMISS","CLASS_NAME_OPEN","CLASS_NAME_STATIC","Modal","_dialog","_backdrop","_initializeBackDrop","_focustrap","_initializeFocusTrap","_scrollBar","_adjustDialog","_showElement","_hideModal","handleUpdate","modalBody","transitionComplete","_triggerBackdropTransition","event2","_resetAdjustments","isModalOverflowing","initialOverflowY","isBodyOverflowing","paddingLeft","paddingRight","showEvent","alreadyOpen","CLASS_NAME_SHOWING","CLASS_NAME_HIDING","OPEN_SELECTOR","Offcanvas","blur","completeCallback","DefaultAllowlist","area","br","col","code","div","em","hr","h1","h2","h3","h4","h5","h6","li","ol","p","pre","s","small","span","sub","sup","strong","u","ul","uriAttributes","SAFE_URL_PATTERN","allowedAttribute","allowedAttributeList","attributeName","nodeValue","attributeRegex","regex","allowList","content","extraClass","sanitize","sanitizeFn","template","DefaultContentType","entry","TemplateFactory","getContent","_resolvePossibleFunction","hasContent","changeContent","_checkContent","toHtml","templateWrapper","innerHTML","_maybeSanitize","text","_setContent","arg","templateElement","_putElementInTemplate","textContent","unsafeHtml","sanitizeFunction","createdDocument","DOMParser","parseFromString","elementName","attributeList","allowedAttributes","sanitizeHtml","DISALLOWED_ATTRIBUTES","CLASS_NAME_FADE","SELECTOR_MODAL","EVENT_MODAL_HIDE","TRIGGER_HOVER","TRIGGER_FOCUS","AttachmentMap","AUTO","TOP","RIGHT","BOTTOM","LEFT","animation","container","customClass","delay","title","Tooltip","_isEnabled","_timeout","_isHovered","_activeTrigger","_templateFactory","_newContent","tip","_setListeners","_fixTitle","enable","disable","toggleEnabled","click","_leave","_enter","_hideModalHandler","_disposePopper","_isWithContent","isInTheDom","_getTipElement","_isWithActiveTrigger","_getTitle","_createTipElement","_getContentForTemplate","_getTemplateFactory","tipId","prefix","floor","random","getElementById","getUID","setContent","_initializeOnDelegatedTarget","_getDelegateConfig","attachment","triggers","eventIn","eventOut","_setTimeout","timeout","dataAttributes","dataAttribute","Popover","_getContent","EVENT_ACTIVATE","EVENT_CLICK","SELECTOR_TARGET_LINKS","SELECTOR_NAV_LINKS","SELECTOR_LINK_ITEMS","rootMargin","smoothScroll","threshold","ScrollSpy","_targetLinks","_observableSections","_rootElement","_activeTarget","_observer","_previousScrollData","visibleEntryTop","parentScrollTop","refresh","_initializeTargetsAndObservables","_maybeEnableSmoothScroll","disconnect","_getNewObserver","section","observe","observableSection","scrollTo","behavior","IntersectionObserver","_observerCallback","targetElement","_process","userScrollsDown","isIntersecting","_clearActiveClass","entryIsLowerThanPrevious","targetLinks","anchor","decodeURI","_activateParents","listGroup","activeNodes","spy","ARROW_LEFT_KEY","ARROW_RIGHT_KEY","HOME_KEY","END_KEY","NOT_SELECTOR_DROPDOWN_TOGGLE","SELECTOR_INNER_ELEM","SELECTOR_DATA_TOGGLE_ACTIVE","Tab","_setInitialAttributes","_getChildren","innerElem","_elemIsActive","active","_getActiveElem","hideEvent","_deactivate","_activate","relatedElem","_toggleDropDown","nextActiveElement","preventScroll","_setAttributeIfNotExists","_setInitialAttributesOnChild","_getInnerElement","isActive","outerElem","_getOuterElement","_setInitialAttributesOnTargetPanel","open","EVENT_MOUSEOVER","EVENT_MOUSEOUT","EVENT_FOCUSOUT","CLASS_NAME_HIDE","autohide","Toast","_hasMouseInteraction","_hasKeyboardInteraction","_clearTimeout","_maybeScheduleHide","isShown","_onInteraction","isInteracting"],"sources":["../../js/src/dom/data.js","../../js/src/util/index.js","../../js/src/dom/event-handler.js","../../js/src/dom/manipulator.js","../../js/src/util/config.js","../../js/src/base-component.js","../../js/src/dom/selector-engine.js","../../js/src/util/component-functions.js","../../js/src/alert.js","../../js/src/button.js","../../js/src/util/swipe.js","../../js/src/carousel.js","../../js/src/collapse.js","../../node_modules/@popperjs/core/lib/enums.js","../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js","../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js","../../node_modules/@popperjs/core/lib/utils/getBasePlacement.js","../../node_modules/@popperjs/core/lib/utils/math.js","../../node_modules/@popperjs/core/lib/utils/userAgent.js","../../node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js","../../node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js","../../node_modules/@popperjs/core/lib/dom-utils/contains.js","../../node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js","../../node_modules/@popperjs/core/lib/dom-utils/isTableElement.js","../../node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js","../../node_modules/@popperjs/core/lib/dom-utils/getParentNode.js","../../node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js","../../node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js","../../node_modules/@popperjs/core/lib/utils/within.js","../../node_modules/@popperjs/core/lib/utils/mergePaddingObject.js","../../node_modules/@popperjs/core/lib/utils/getFreshSideObject.js","../../node_modules/@popperjs/core/lib/utils/expandToHashMap.js","../../node_modules/@popperjs/core/lib/modifiers/arrow.js","../../node_modules/@popperjs/core/lib/utils/getVariation.js","../../node_modules/@popperjs/core/lib/modifiers/computeStyles.js","../../node_modules/@popperjs/core/lib/modifiers/eventListeners.js","../../node_modules/@popperjs/core/lib/utils/getOppositePlacement.js","../../node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js","../../node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js","../../node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js","../../node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js","../../node_modules/@popperjs/core/lib/utils/rectToClientRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js","../../node_modules/@popperjs/core/lib/utils/computeOffsets.js","../../node_modules/@popperjs/core/lib/utils/detectOverflow.js","../../node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js","../../node_modules/@popperjs/core/lib/modifiers/flip.js","../../node_modules/@popperjs/core/lib/modifiers/hide.js","../../node_modules/@popperjs/core/lib/modifiers/offset.js","../../node_modules/@popperjs/core/lib/modifiers/popperOffsets.js","../../node_modules/@popperjs/core/lib/modifiers/preventOverflow.js","../../node_modules/@popperjs/core/lib/utils/getAltAxis.js","../../node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js","../../node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js","../../node_modules/@popperjs/core/lib/utils/orderModifiers.js","../../node_modules/@popperjs/core/lib/createPopper.js","../../node_modules/@popperjs/core/lib/utils/debounce.js","../../node_modules/@popperjs/core/lib/utils/mergeByName.js","../../node_modules/@popperjs/core/lib/popper-lite.js","../../node_modules/@popperjs/core/lib/popper.js","../../js/src/dropdown.js","../../js/src/util/backdrop.js","../../js/src/util/focustrap.js","../../js/src/util/scrollbar.js","../../js/src/modal.js","../../js/src/offcanvas.js","../../js/src/util/sanitizer.js","../../js/src/util/template-factory.js","../../js/src/tooltip.js","../../js/src/popover.js","../../js/src/scrollspy.js","../../js/src/tab.js","../../js/src/toast.js","../../js/index.umd.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n/**\n * Constants\n */\n\nconst elementMap = new Map()\n\nexport default {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map())\n }\n\n const instanceMap = elementMap.get(element)\n\n // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)\n return\n }\n\n instanceMap.set(key, instance)\n },\n\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null\n }\n\n return null\n },\n\n remove(element, key) {\n if (!elementMap.has(element)) {\n return\n }\n\n const instanceMap = elementMap.get(element)\n\n instanceMap.delete(key)\n\n // free up element references if there are no instances left for an element\n if (instanceMap.size === 0) {\n elementMap.delete(element)\n }\n }\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst MAX_UID = 1_000_000\nconst MILLISECONDS_MULTIPLIER = 1000\nconst TRANSITION_END = 'transitionend'\n\n/**\n * Properly escape IDs selectors to handle weird IDs\n * @param {string} selector\n * @returns {string}\n */\nconst parseSelector = selector => {\n if (selector && window.CSS && window.CSS.escape) {\n // document.querySelector needs escaping to handle IDs (html5+) containing for instance /\n selector = selector.replace(/#([^\\s\"#']+)/g, (match, id) => `#${CSS.escape(id)}`)\n }\n\n return selector\n}\n\n// Shout-out Angus Croll (https://goo.gl/pxwQGp)\nconst toType = object => {\n if (object === null || object === undefined) {\n return `${object}`\n }\n\n return Object.prototype.toString.call(object).match(/\\s([a-z]+)/i)[1].toLowerCase()\n}\n\n/**\n * Public Util API\n */\n\nconst getUID = prefix => {\n do {\n prefix += Math.floor(Math.random() * MAX_UID)\n } while (document.getElementById(prefix))\n\n return prefix\n}\n\nconst getTransitionDurationFromElement = element => {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let { transitionDuration, transitionDelay } = window.getComputedStyle(element)\n\n const floatTransitionDuration = Number.parseFloat(transitionDuration)\n const floatTransitionDelay = Number.parseFloat(transitionDelay)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n transitionDelay = transitionDelay.split(',')[0]\n\n return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER\n}\n\nconst triggerTransitionEnd = element => {\n element.dispatchEvent(new Event(TRANSITION_END))\n}\n\nconst isElement = object => {\n if (!object || typeof object !== 'object') {\n return false\n }\n\n if (typeof object.jquery !== 'undefined') {\n object = object[0]\n }\n\n return typeof object.nodeType !== 'undefined'\n}\n\nconst getElement = object => {\n // it's a jQuery object or a node element\n if (isElement(object)) {\n return object.jquery ? object[0] : object\n }\n\n if (typeof object === 'string' && object.length > 0) {\n return document.querySelector(parseSelector(object))\n }\n\n return null\n}\n\nconst isVisible = element => {\n if (!isElement(element) || element.getClientRects().length === 0) {\n return false\n }\n\n const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'\n // Handle `details` element as its content may falsie appear visible when it is closed\n const closedDetails = element.closest('details:not([open])')\n\n if (!closedDetails) {\n return elementIsVisible\n }\n\n if (closedDetails !== element) {\n const summary = element.closest('summary')\n if (summary && summary.parentNode !== closedDetails) {\n return false\n }\n\n if (summary === null) {\n return false\n }\n }\n\n return elementIsVisible\n}\n\nconst isDisabled = element => {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return true\n }\n\n if (element.classList.contains('disabled')) {\n return true\n }\n\n if (typeof element.disabled !== 'undefined') {\n return element.disabled\n }\n\n return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'\n}\n\nconst findShadowRoot = element => {\n if (!document.documentElement.attachShadow) {\n return null\n }\n\n // Can find the shadow root otherwise it'll return the document\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode()\n return root instanceof ShadowRoot ? root : null\n }\n\n if (element instanceof ShadowRoot) {\n return element\n }\n\n // when we don't find a shadow root\n if (!element.parentNode) {\n return null\n }\n\n return findShadowRoot(element.parentNode)\n}\n\nconst noop = () => {}\n\n/**\n * Trick to restart an element's animation\n *\n * @param {HTMLElement} element\n * @return void\n *\n * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation\n */\nconst reflow = element => {\n element.offsetHeight // eslint-disable-line no-unused-expressions\n}\n\nconst getjQuery = () => {\n if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n return window.jQuery\n }\n\n return null\n}\n\nconst DOMContentLoadedCallbacks = []\n\nconst onDOMContentLoaded = callback => {\n if (document.readyState === 'loading') {\n // add listener on the first call when the document is in loading state\n if (!DOMContentLoadedCallbacks.length) {\n document.addEventListener('DOMContentLoaded', () => {\n for (const callback of DOMContentLoadedCallbacks) {\n callback()\n }\n })\n }\n\n DOMContentLoadedCallbacks.push(callback)\n } else {\n callback()\n }\n}\n\nconst isRTL = () => document.documentElement.dir === 'rtl'\n\nconst defineJQueryPlugin = plugin => {\n onDOMContentLoaded(() => {\n const $ = getjQuery()\n /* istanbul ignore if */\n if ($) {\n const name = plugin.NAME\n const JQUERY_NO_CONFLICT = $.fn[name]\n $.fn[name] = plugin.jQueryInterface\n $.fn[name].Constructor = plugin\n $.fn[name].noConflict = () => {\n $.fn[name] = JQUERY_NO_CONFLICT\n return plugin.jQueryInterface\n }\n }\n })\n}\n\nconst execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {\n return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue\n}\n\nconst executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n if (!waitForTransition) {\n execute(callback)\n return\n }\n\n const durationPadding = 5\n const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding\n\n let called = false\n\n const handler = ({ target }) => {\n if (target !== transitionElement) {\n return\n }\n\n called = true\n transitionElement.removeEventListener(TRANSITION_END, handler)\n execute(callback)\n }\n\n transitionElement.addEventListener(TRANSITION_END, handler)\n setTimeout(() => {\n if (!called) {\n triggerTransitionEnd(transitionElement)\n }\n }, emulatedDuration)\n}\n\n/**\n * Return the previous/next element of a list.\n *\n * @param {array} list The list of elements\n * @param activeElement The active element\n * @param shouldGetNext Choose to get next or previous element\n * @param isCycleAllowed\n * @return {Element|elem} The proper element\n */\nconst getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n const listLength = list.length\n let index = list.indexOf(activeElement)\n\n // if the element does not exist in the list return an element\n // depending on the direction and if cycle is allowed\n if (index === -1) {\n return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]\n }\n\n index += shouldGetNext ? 1 : -1\n\n if (isCycleAllowed) {\n index = (index + listLength) % listLength\n }\n\n return list[Math.max(0, Math.min(index, listLength - 1))]\n}\n\nexport {\n defineJQueryPlugin,\n execute,\n executeAfterTransition,\n findShadowRoot,\n getElement,\n getjQuery,\n getNextActiveElement,\n getTransitionDurationFromElement,\n getUID,\n isDisabled,\n isElement,\n isRTL,\n isVisible,\n noop,\n onDOMContentLoaded,\n parseSelector,\n reflow,\n triggerTransitionEnd,\n toType\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/event-handler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport { getjQuery } from '../util/index.js'\n\n/**\n * Constants\n */\n\nconst namespaceRegex = /[^.]*(?=\\..*)\\.|.*/\nconst stripNameRegex = /\\..*/\nconst stripUidRegex = /::\\d+$/\nconst eventRegistry = {} // Events storage\nlet uidEvent = 1\nconst customEvents = {\n mouseenter: 'mouseover',\n mouseleave: 'mouseout'\n}\n\nconst nativeEvents = new Set([\n 'click',\n 'dblclick',\n 'mouseup',\n 'mousedown',\n 'contextmenu',\n 'mousewheel',\n 'DOMMouseScroll',\n 'mouseover',\n 'mouseout',\n 'mousemove',\n 'selectstart',\n 'selectend',\n 'keydown',\n 'keypress',\n 'keyup',\n 'orientationchange',\n 'touchstart',\n 'touchmove',\n 'touchend',\n 'touchcancel',\n 'pointerdown',\n 'pointermove',\n 'pointerup',\n 'pointerleave',\n 'pointercancel',\n 'gesturestart',\n 'gesturechange',\n 'gestureend',\n 'focus',\n 'blur',\n 'change',\n 'reset',\n 'select',\n 'submit',\n 'focusin',\n 'focusout',\n 'load',\n 'unload',\n 'beforeunload',\n 'resize',\n 'move',\n 'DOMContentLoaded',\n 'readystatechange',\n 'error',\n 'abort',\n 'scroll'\n])\n\n/**\n * Private methods\n */\n\nfunction makeEventUid(element, uid) {\n return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++\n}\n\nfunction getElementEvents(element) {\n const uid = makeEventUid(element)\n\n element.uidEvent = uid\n eventRegistry[uid] = eventRegistry[uid] || {}\n\n return eventRegistry[uid]\n}\n\nfunction bootstrapHandler(element, fn) {\n return function handler(event) {\n hydrateObj(event, { delegateTarget: element })\n\n if (handler.oneOff) {\n EventHandler.off(element, event.type, fn)\n }\n\n return fn.apply(element, [event])\n }\n}\n\nfunction bootstrapDelegationHandler(element, selector, fn) {\n return function handler(event) {\n const domElements = element.querySelectorAll(selector)\n\n for (let { target } = event; target && target !== this; target = target.parentNode) {\n for (const domElement of domElements) {\n if (domElement !== target) {\n continue\n }\n\n hydrateObj(event, { delegateTarget: target })\n\n if (handler.oneOff) {\n EventHandler.off(element, event.type, selector, fn)\n }\n\n return fn.apply(target, [event])\n }\n }\n }\n}\n\nfunction findHandler(events, callable, delegationSelector = null) {\n return Object.values(events)\n .find(event => event.callable === callable && event.delegationSelector === delegationSelector)\n}\n\nfunction normalizeParameters(originalTypeEvent, handler, delegationFunction) {\n const isDelegated = typeof handler === 'string'\n // TODO: tooltip passes `false` instead of selector, so we need to check\n const callable = isDelegated ? delegationFunction : (handler || delegationFunction)\n let typeEvent = getTypeEvent(originalTypeEvent)\n\n if (!nativeEvents.has(typeEvent)) {\n typeEvent = originalTypeEvent\n }\n\n return [isDelegated, callable, typeEvent]\n}\n\nfunction addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return\n }\n\n let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction)\n\n // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n if (originalTypeEvent in customEvents) {\n const wrapFunction = fn => {\n return function (event) {\n if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) {\n return fn.call(this, event)\n }\n }\n }\n\n callable = wrapFunction(callable)\n }\n\n const events = getElementEvents(element)\n const handlers = events[typeEvent] || (events[typeEvent] = {})\n const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null)\n\n if (previousFunction) {\n previousFunction.oneOff = previousFunction.oneOff && oneOff\n\n return\n }\n\n const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''))\n const fn = isDelegated ?\n bootstrapDelegationHandler(element, handler, callable) :\n bootstrapHandler(element, callable)\n\n fn.delegationSelector = isDelegated ? handler : null\n fn.callable = callable\n fn.oneOff = oneOff\n fn.uidEvent = uid\n handlers[uid] = fn\n\n element.addEventListener(typeEvent, fn, isDelegated)\n}\n\nfunction removeHandler(element, events, typeEvent, handler, delegationSelector) {\n const fn = findHandler(events[typeEvent], handler, delegationSelector)\n\n if (!fn) {\n return\n }\n\n element.removeEventListener(typeEvent, fn, Boolean(delegationSelector))\n delete events[typeEvent][fn.uidEvent]\n}\n\nfunction removeNamespacedHandlers(element, events, typeEvent, namespace) {\n const storeElementEvent = events[typeEvent] || {}\n\n for (const [handlerKey, event] of Object.entries(storeElementEvent)) {\n if (handlerKey.includes(namespace)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)\n }\n }\n}\n\nfunction getTypeEvent(event) {\n // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n event = event.replace(stripNameRegex, '')\n return customEvents[event] || event\n}\n\nconst EventHandler = {\n on(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, false)\n },\n\n one(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, true)\n },\n\n off(element, originalTypeEvent, handler, delegationFunction) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return\n }\n\n const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction)\n const inNamespace = typeEvent !== originalTypeEvent\n const events = getElementEvents(element)\n const storeElementEvent = events[typeEvent] || {}\n const isNamespace = originalTypeEvent.startsWith('.')\n\n if (typeof callable !== 'undefined') {\n // Simplest case: handler is passed, remove that listener ONLY.\n if (!Object.keys(storeElementEvent).length) {\n return\n }\n\n removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null)\n return\n }\n\n if (isNamespace) {\n for (const elementEvent of Object.keys(events)) {\n removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1))\n }\n }\n\n for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {\n const handlerKey = keyHandlers.replace(stripUidRegex, '')\n\n if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)\n }\n }\n },\n\n trigger(element, event, args) {\n if (typeof event !== 'string' || !element) {\n return null\n }\n\n const $ = getjQuery()\n const typeEvent = getTypeEvent(event)\n const inNamespace = event !== typeEvent\n\n let jQueryEvent = null\n let bubbles = true\n let nativeDispatch = true\n let defaultPrevented = false\n\n if (inNamespace && $) {\n jQueryEvent = $.Event(event, args)\n\n $(element).trigger(jQueryEvent)\n bubbles = !jQueryEvent.isPropagationStopped()\n nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()\n defaultPrevented = jQueryEvent.isDefaultPrevented()\n }\n\n const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)\n\n if (defaultPrevented) {\n evt.preventDefault()\n }\n\n if (nativeDispatch) {\n element.dispatchEvent(evt)\n }\n\n if (evt.defaultPrevented && jQueryEvent) {\n jQueryEvent.preventDefault()\n }\n\n return evt\n }\n}\n\nfunction hydrateObj(obj, meta = {}) {\n for (const [key, value] of Object.entries(meta)) {\n try {\n obj[key] = value\n } catch {\n Object.defineProperty(obj, key, {\n configurable: true,\n get() {\n return value\n }\n })\n }\n }\n\n return obj\n}\n\nexport default EventHandler\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nfunction normalizeData(value) {\n if (value === 'true') {\n return true\n }\n\n if (value === 'false') {\n return false\n }\n\n if (value === Number(value).toString()) {\n return Number(value)\n }\n\n if (value === '' || value === 'null') {\n return null\n }\n\n if (typeof value !== 'string') {\n return value\n }\n\n try {\n return JSON.parse(decodeURIComponent(value))\n } catch {\n return value\n }\n}\n\nfunction normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)\n}\n\nconst Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)\n },\n\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)\n },\n\n getDataAttributes(element) {\n if (!element) {\n return {}\n }\n\n const attributes = {}\n const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'))\n\n for (const key of bsKeys) {\n let pureKey = key.replace(/^bs/, '')\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length)\n attributes[pureKey] = normalizeData(element.dataset[key])\n }\n\n return attributes\n },\n\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))\n }\n}\n\nexport default Manipulator\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/config.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Manipulator from '../dom/manipulator.js'\nimport { isElement, toType } from './index.js'\n\n/**\n * Class definition\n */\n\nclass Config {\n // Getters\n static get Default() {\n return {}\n }\n\n static get DefaultType() {\n return {}\n }\n\n static get NAME() {\n throw new Error('You have to implement the static method \"NAME\", for each component!')\n }\n\n _getConfig(config) {\n config = this._mergeConfigObj(config)\n config = this._configAfterMerge(config)\n this._typeCheckConfig(config)\n return config\n }\n\n _configAfterMerge(config) {\n return config\n }\n\n _mergeConfigObj(config, element) {\n const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {} // try to parse\n\n return {\n ...this.constructor.Default,\n ...(typeof jsonConfig === 'object' ? jsonConfig : {}),\n ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),\n ...(typeof config === 'object' ? config : {})\n }\n }\n\n _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {\n for (const [property, expectedTypes] of Object.entries(configTypes)) {\n const value = config[property]\n const valueType = isElement(value) ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new TypeError(\n `${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`\n )\n }\n }\n }\n}\n\nexport default Config\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Data from './dom/data.js'\nimport EventHandler from './dom/event-handler.js'\nimport Config from './util/config.js'\nimport { executeAfterTransition, getElement } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst VERSION = '5.3.1'\n\n/**\n * Class definition\n */\n\nclass BaseComponent extends Config {\n constructor(element, config) {\n super()\n\n element = getElement(element)\n if (!element) {\n return\n }\n\n this._element = element\n this._config = this._getConfig(config)\n\n Data.set(this._element, this.constructor.DATA_KEY, this)\n }\n\n // Public\n dispose() {\n Data.remove(this._element, this.constructor.DATA_KEY)\n EventHandler.off(this._element, this.constructor.EVENT_KEY)\n\n for (const propertyName of Object.getOwnPropertyNames(this)) {\n this[propertyName] = null\n }\n }\n\n _queueCallback(callback, element, isAnimated = true) {\n executeAfterTransition(callback, element, isAnimated)\n }\n\n _getConfig(config) {\n config = this._mergeConfigObj(config, this._element)\n config = this._configAfterMerge(config)\n this._typeCheckConfig(config)\n return config\n }\n\n // Static\n static getInstance(element) {\n return Data.get(getElement(element), this.DATA_KEY)\n }\n\n static getOrCreateInstance(element, config = {}) {\n return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)\n }\n\n static get VERSION() {\n return VERSION\n }\n\n static get DATA_KEY() {\n return `bs.${this.NAME}`\n }\n\n static get EVENT_KEY() {\n return `.${this.DATA_KEY}`\n }\n\n static eventName(name) {\n return `${name}${this.EVENT_KEY}`\n }\n}\n\nexport default BaseComponent\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/selector-engine.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport { isDisabled, isVisible, parseSelector } from '../util/index.js'\n\nconst getSelector = element => {\n let selector = element.getAttribute('data-bs-target')\n\n if (!selector || selector === '#') {\n let hrefAttribute = element.getAttribute('href')\n\n // The only valid content that could double as a selector are IDs or classes,\n // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n // `document.querySelector` will rightfully complain it is invalid.\n // See https://github.com/twbs/bootstrap/issues/32273\n if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {\n return null\n }\n\n // Just in case some CMS puts out a full URL with the anchor appended\n if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {\n hrefAttribute = `#${hrefAttribute.split('#')[1]}`\n }\n\n selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null\n }\n\n return parseSelector(selector)\n}\n\nconst SelectorEngine = {\n find(selector, element = document.documentElement) {\n return [].concat(...Element.prototype.querySelectorAll.call(element, selector))\n },\n\n findOne(selector, element = document.documentElement) {\n return Element.prototype.querySelector.call(element, selector)\n },\n\n children(element, selector) {\n return [].concat(...element.children).filter(child => child.matches(selector))\n },\n\n parents(element, selector) {\n const parents = []\n let ancestor = element.parentNode.closest(selector)\n\n while (ancestor) {\n parents.push(ancestor)\n ancestor = ancestor.parentNode.closest(selector)\n }\n\n return parents\n },\n\n prev(element, selector) {\n let previous = element.previousElementSibling\n\n while (previous) {\n if (previous.matches(selector)) {\n return [previous]\n }\n\n previous = previous.previousElementSibling\n }\n\n return []\n },\n // TODO: this is now unused; remove later along with prev()\n next(element, selector) {\n let next = element.nextElementSibling\n\n while (next) {\n if (next.matches(selector)) {\n return [next]\n }\n\n next = next.nextElementSibling\n }\n\n return []\n },\n\n focusableChildren(element) {\n const focusables = [\n 'a',\n 'button',\n 'input',\n 'textarea',\n 'select',\n 'details',\n '[tabindex]',\n '[contenteditable=\"true\"]'\n ].map(selector => `${selector}:not([tabindex^=\"-\"])`).join(',')\n\n return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))\n },\n\n getSelectorFromElement(element) {\n const selector = getSelector(element)\n\n if (selector) {\n return SelectorEngine.findOne(selector) ? selector : null\n }\n\n return null\n },\n\n getElementFromSelector(element) {\n const selector = getSelector(element)\n\n return selector ? SelectorEngine.findOne(selector) : null\n },\n\n getMultipleElementsFromSelector(element) {\n const selector = getSelector(element)\n\n return selector ? SelectorEngine.find(selector) : []\n }\n}\n\nexport default SelectorEngine\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/component-functions.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport { isDisabled } from './index.js'\n\nconst enableDismissTrigger = (component, method = 'hide') => {\n const clickEvent = `click.dismiss${component.EVENT_KEY}`\n const name = component.NAME\n\n EventHandler.on(document, clickEvent, `[data-bs-dismiss=\"${name}\"]`, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n if (isDisabled(this)) {\n return\n }\n\n const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`)\n const instance = component.getOrCreateInstance(target)\n\n // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method\n instance[method]()\n })\n}\n\nexport {\n enableDismissTrigger\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'alert'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)\n\n if (closeEvent.defaultPrevented) {\n return\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE)\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated)\n }\n\n // Private\n _destroyElement() {\n this._element.remove()\n EventHandler.trigger(this._element, EVENT_CLOSED)\n this.dispose()\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Alert.getOrCreateInstance(this)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](this)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close')\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Alert)\n\nexport default Alert\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'button'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"button\"]'\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Button.getOrCreateInstance(this)\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {\n event.preventDefault()\n\n const button = event.target.closest(SELECTOR_DATA_TOGGLE)\n const data = Button.getOrCreateInstance(button)\n\n data.toggle()\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Button)\n\nexport default Button\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/swipe.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport Config from './config.js'\nimport { execute } from './index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'swipe'\nconst EVENT_KEY = '.bs.swipe'\nconst EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`\nconst EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`\nconst EVENT_TOUCHEND = `touchend${EVENT_KEY}`\nconst EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`\nconst EVENT_POINTERUP = `pointerup${EVENT_KEY}`\nconst POINTER_TYPE_TOUCH = 'touch'\nconst POINTER_TYPE_PEN = 'pen'\nconst CLASS_NAME_POINTER_EVENT = 'pointer-event'\nconst SWIPE_THRESHOLD = 40\n\nconst Default = {\n endCallback: null,\n leftCallback: null,\n rightCallback: null\n}\n\nconst DefaultType = {\n endCallback: '(function|null)',\n leftCallback: '(function|null)',\n rightCallback: '(function|null)'\n}\n\n/**\n * Class definition\n */\n\nclass Swipe extends Config {\n constructor(element, config) {\n super()\n this._element = element\n\n if (!element || !Swipe.isSupported()) {\n return\n }\n\n this._config = this._getConfig(config)\n this._deltaX = 0\n this._supportPointerEvents = Boolean(window.PointerEvent)\n this._initEvents()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n dispose() {\n EventHandler.off(this._element, EVENT_KEY)\n }\n\n // Private\n _start(event) {\n if (!this._supportPointerEvents) {\n this._deltaX = event.touches[0].clientX\n\n return\n }\n\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX\n }\n }\n\n _end(event) {\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX - this._deltaX\n }\n\n this._handleSwipe()\n execute(this._config.endCallback)\n }\n\n _move(event) {\n this._deltaX = event.touches && event.touches.length > 1 ?\n 0 :\n event.touches[0].clientX - this._deltaX\n }\n\n _handleSwipe() {\n const absDeltaX = Math.abs(this._deltaX)\n\n if (absDeltaX <= SWIPE_THRESHOLD) {\n return\n }\n\n const direction = absDeltaX / this._deltaX\n\n this._deltaX = 0\n\n if (!direction) {\n return\n }\n\n execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback)\n }\n\n _initEvents() {\n if (this._supportPointerEvents) {\n EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event))\n EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event))\n\n this._element.classList.add(CLASS_NAME_POINTER_EVENT)\n } else {\n EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event))\n EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event))\n EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event))\n }\n }\n\n _eventIsPointerPenTouch(event) {\n return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)\n }\n\n // Static\n static isSupported() {\n return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0\n }\n}\n\nexport default Swipe\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport Manipulator from './dom/manipulator.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n getNextActiveElement,\n isRTL,\n isVisible,\n reflow,\n triggerTransitionEnd\n} from './util/index.js'\nimport Swipe from './util/swipe.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'carousel'\nconst DATA_KEY = 'bs.carousel'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst ARROW_LEFT_KEY = 'ArrowLeft'\nconst ARROW_RIGHT_KEY = 'ArrowRight'\nconst TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\n\nconst ORDER_NEXT = 'next'\nconst ORDER_PREV = 'prev'\nconst DIRECTION_LEFT = 'left'\nconst DIRECTION_RIGHT = 'right'\n\nconst EVENT_SLIDE = `slide${EVENT_KEY}`\nconst EVENT_SLID = `slid${EVENT_KEY}`\nconst EVENT_KEYDOWN = `keydown${EVENT_KEY}`\nconst EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`\nconst EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`\nconst EVENT_DRAG_START = `dragstart${EVENT_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_CAROUSEL = 'carousel'\nconst CLASS_NAME_ACTIVE = 'active'\nconst CLASS_NAME_SLIDE = 'slide'\nconst CLASS_NAME_END = 'carousel-item-end'\nconst CLASS_NAME_START = 'carousel-item-start'\nconst CLASS_NAME_NEXT = 'carousel-item-next'\nconst CLASS_NAME_PREV = 'carousel-item-prev'\n\nconst SELECTOR_ACTIVE = '.active'\nconst SELECTOR_ITEM = '.carousel-item'\nconst SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM\nconst SELECTOR_ITEM_IMG = '.carousel-item img'\nconst SELECTOR_INDICATORS = '.carousel-indicators'\nconst SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'\nconst SELECTOR_DATA_RIDE = '[data-bs-ride=\"carousel\"]'\n\nconst KEY_TO_DIRECTION = {\n [ARROW_LEFT_KEY]: DIRECTION_RIGHT,\n [ARROW_RIGHT_KEY]: DIRECTION_LEFT\n}\n\nconst Default = {\n interval: 5000,\n keyboard: true,\n pause: 'hover',\n ride: false,\n touch: true,\n wrap: true\n}\n\nconst DefaultType = {\n interval: '(number|boolean)', // TODO:v6 remove boolean support\n keyboard: 'boolean',\n pause: '(string|boolean)',\n ride: '(boolean|string)',\n touch: 'boolean',\n wrap: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Carousel extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._interval = null\n this._activeElement = null\n this._isSliding = false\n this.touchTimeout = null\n this._swipeHelper = null\n\n this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)\n this._addEventListeners()\n\n if (this._config.ride === CLASS_NAME_CAROUSEL) {\n this.cycle()\n }\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n next() {\n this._slide(ORDER_NEXT)\n }\n\n nextWhenVisible() {\n // FIXME TODO use `document.visibilityState`\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden && isVisible(this._element)) {\n this.next()\n }\n }\n\n prev() {\n this._slide(ORDER_PREV)\n }\n\n pause() {\n if (this._isSliding) {\n triggerTransitionEnd(this._element)\n }\n\n this._clearInterval()\n }\n\n cycle() {\n this._clearInterval()\n this._updateInterval()\n\n this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval)\n }\n\n _maybeEnableCycle() {\n if (!this._config.ride) {\n return\n }\n\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.cycle())\n return\n }\n\n this.cycle()\n }\n\n to(index) {\n const items = this._getItems()\n if (index > items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.to(index))\n return\n }\n\n const activeIndex = this._getItemIndex(this._getActive())\n if (activeIndex === index) {\n return\n }\n\n const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV\n\n this._slide(order, items[index])\n }\n\n dispose() {\n if (this._swipeHelper) {\n this._swipeHelper.dispose()\n }\n\n super.dispose()\n }\n\n // Private\n _configAfterMerge(config) {\n config.defaultInterval = config.interval\n return config\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n EventHandler.on(this._element, EVENT_MOUSEENTER, () => this.pause())\n EventHandler.on(this._element, EVENT_MOUSELEAVE, () => this._maybeEnableCycle())\n }\n\n if (this._config.touch && Swipe.isSupported()) {\n this._addTouchEventListeners()\n }\n }\n\n _addTouchEventListeners() {\n for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {\n EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault())\n }\n\n const endCallBack = () => {\n if (this._config.pause !== 'hover') {\n return\n }\n\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n\n this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n }\n\n const swipeConfig = {\n leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),\n rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),\n endCallback: endCallBack\n }\n\n this._swipeHelper = new Swipe(this._element, swipeConfig)\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n const direction = KEY_TO_DIRECTION[event.key]\n if (direction) {\n event.preventDefault()\n this._slide(this._directionToOrder(direction))\n }\n }\n\n _getItemIndex(element) {\n return this._getItems().indexOf(element)\n }\n\n _setActiveIndicatorElement(index) {\n if (!this._indicatorsElement) {\n return\n }\n\n const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement)\n\n activeIndicator.classList.remove(CLASS_NAME_ACTIVE)\n activeIndicator.removeAttribute('aria-current')\n\n const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to=\"${index}\"]`, this._indicatorsElement)\n\n if (newActiveIndicator) {\n newActiveIndicator.classList.add(CLASS_NAME_ACTIVE)\n newActiveIndicator.setAttribute('aria-current', 'true')\n }\n }\n\n _updateInterval() {\n const element = this._activeElement || this._getActive()\n\n if (!element) {\n return\n }\n\n const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10)\n\n this._config.interval = elementInterval || this._config.defaultInterval\n }\n\n _slide(order, element = null) {\n if (this._isSliding) {\n return\n }\n\n const activeElement = this._getActive()\n const isNext = order === ORDER_NEXT\n const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap)\n\n if (nextElement === activeElement) {\n return\n }\n\n const nextElementIndex = this._getItemIndex(nextElement)\n\n const triggerEvent = eventName => {\n return EventHandler.trigger(this._element, eventName, {\n relatedTarget: nextElement,\n direction: this._orderToDirection(order),\n from: this._getItemIndex(activeElement),\n to: nextElementIndex\n })\n }\n\n const slideEvent = triggerEvent(EVENT_SLIDE)\n\n if (slideEvent.defaultPrevented) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n // TODO: change tests that use empty divs to avoid this check\n return\n }\n\n const isCycling = Boolean(this._interval)\n this.pause()\n\n this._isSliding = true\n\n this._setActiveIndicatorElement(nextElementIndex)\n this._activeElement = nextElement\n\n const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END\n const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV\n\n nextElement.classList.add(orderClassName)\n\n reflow(nextElement)\n\n activeElement.classList.add(directionalClassName)\n nextElement.classList.add(directionalClassName)\n\n const completeCallBack = () => {\n nextElement.classList.remove(directionalClassName, orderClassName)\n nextElement.classList.add(CLASS_NAME_ACTIVE)\n\n activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName)\n\n this._isSliding = false\n\n triggerEvent(EVENT_SLID)\n }\n\n this._queueCallback(completeCallBack, activeElement, this._isAnimated())\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_SLIDE)\n }\n\n _getActive() {\n return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)\n }\n\n _getItems() {\n return SelectorEngine.find(SELECTOR_ITEM, this._element)\n }\n\n _clearInterval() {\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n }\n\n _directionToOrder(direction) {\n if (isRTL()) {\n return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT\n }\n\n return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV\n }\n\n _orderToDirection(order) {\n if (isRTL()) {\n return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT\n }\n\n return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Carousel.getOrCreateInstance(this, config)\n\n if (typeof config === 'number') {\n data.to(config)\n return\n }\n\n if (typeof config === 'string') {\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this)\n\n if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {\n return\n }\n\n event.preventDefault()\n\n const carousel = Carousel.getOrCreateInstance(target)\n const slideIndex = this.getAttribute('data-bs-slide-to')\n\n if (slideIndex) {\n carousel.to(slideIndex)\n carousel._maybeEnableCycle()\n return\n }\n\n if (Manipulator.getDataAttribute(this, 'slide') === 'next') {\n carousel.next()\n carousel._maybeEnableCycle()\n return\n }\n\n carousel.prev()\n carousel._maybeEnableCycle()\n})\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)\n\n for (const carousel of carousels) {\n Carousel.getOrCreateInstance(carousel)\n }\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Carousel)\n\nexport default Carousel\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n getElement,\n reflow\n} from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'collapse'\nconst DATA_KEY = 'bs.collapse'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_COLLAPSE = 'collapse'\nconst CLASS_NAME_COLLAPSING = 'collapsing'\nconst CLASS_NAME_COLLAPSED = 'collapsed'\nconst CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`\nconst CLASS_NAME_HORIZONTAL = 'collapse-horizontal'\n\nconst WIDTH = 'width'\nconst HEIGHT = 'height'\n\nconst SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"collapse\"]'\n\nconst Default = {\n parent: null,\n toggle: true\n}\n\nconst DefaultType = {\n parent: '(null|element)',\n toggle: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Collapse extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._isTransitioning = false\n this._triggerArray = []\n\n const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)\n\n for (const elem of toggleList) {\n const selector = SelectorEngine.getSelectorFromElement(elem)\n const filterElement = SelectorEngine.find(selector)\n .filter(foundElement => foundElement === this._element)\n\n if (selector !== null && filterElement.length) {\n this._triggerArray.push(elem)\n }\n }\n\n this._initializeChildren()\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._triggerArray, this._isShown())\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n if (this._isShown()) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning || this._isShown()) {\n return\n }\n\n let activeChildren = []\n\n // find active children\n if (this._config.parent) {\n activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES)\n .filter(element => element !== this._element)\n .map(element => Collapse.getOrCreateInstance(element, { toggle: false }))\n }\n\n if (activeChildren.length && activeChildren[0]._isTransitioning) {\n return\n }\n\n const startEvent = EventHandler.trigger(this._element, EVENT_SHOW)\n if (startEvent.defaultPrevented) {\n return\n }\n\n for (const activeInstance of activeChildren) {\n activeInstance.hide()\n }\n\n const dimension = this._getDimension()\n\n this._element.classList.remove(CLASS_NAME_COLLAPSE)\n this._element.classList.add(CLASS_NAME_COLLAPSING)\n\n this._element.style[dimension] = 0\n\n this._addAriaAndCollapsedClass(this._triggerArray, true)\n this._isTransitioning = true\n\n const complete = () => {\n this._isTransitioning = false\n\n this._element.classList.remove(CLASS_NAME_COLLAPSING)\n this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)\n\n this._element.style[dimension] = ''\n\n EventHandler.trigger(this._element, EVENT_SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n\n this._queueCallback(complete, this._element, true)\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning || !this._isShown()) {\n return\n }\n\n const startEvent = EventHandler.trigger(this._element, EVENT_HIDE)\n if (startEvent.defaultPrevented) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n reflow(this._element)\n\n this._element.classList.add(CLASS_NAME_COLLAPSING)\n this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)\n\n for (const trigger of this._triggerArray) {\n const element = SelectorEngine.getElementFromSelector(trigger)\n\n if (element && !this._isShown(element)) {\n this._addAriaAndCollapsedClass([trigger], false)\n }\n }\n\n this._isTransitioning = true\n\n const complete = () => {\n this._isTransitioning = false\n this._element.classList.remove(CLASS_NAME_COLLAPSING)\n this._element.classList.add(CLASS_NAME_COLLAPSE)\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n }\n\n this._element.style[dimension] = ''\n\n this._queueCallback(complete, this._element, true)\n }\n\n _isShown(element = this._element) {\n return element.classList.contains(CLASS_NAME_SHOW)\n }\n\n // Private\n _configAfterMerge(config) {\n config.toggle = Boolean(config.toggle) // Coerce string values\n config.parent = getElement(config.parent)\n return config\n }\n\n _getDimension() {\n return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT\n }\n\n _initializeChildren() {\n if (!this._config.parent) {\n return\n }\n\n const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE)\n\n for (const element of children) {\n const selected = SelectorEngine.getElementFromSelector(element)\n\n if (selected) {\n this._addAriaAndCollapsedClass([element], this._isShown(selected))\n }\n }\n }\n\n _getFirstLevelChildren(selector) {\n const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent)\n // remove children if greater depth\n return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element))\n }\n\n _addAriaAndCollapsedClass(triggerArray, isOpen) {\n if (!triggerArray.length) {\n return\n }\n\n for (const element of triggerArray) {\n element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen)\n element.setAttribute('aria-expanded', isOpen)\n }\n }\n\n // Static\n static jQueryInterface(config) {\n const _config = {}\n if (typeof config === 'string' && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n return this.each(function () {\n const data = Collapse.getOrCreateInstance(this, _config)\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {\n event.preventDefault()\n }\n\n for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {\n Collapse.getOrCreateInstance(element, { toggle: false }).toggle()\n }\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Collapse)\n\nexport default Collapse\n","export var top = 'top';\nexport var bottom = 'bottom';\nexport var right = 'right';\nexport var left = 'left';\nexport var auto = 'auto';\nexport var basePlacements = [top, bottom, right, left];\nexport var start = 'start';\nexport var end = 'end';\nexport var clippingParents = 'clippingParents';\nexport var viewport = 'viewport';\nexport var popper = 'popper';\nexport var reference = 'reference';\nexport var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {\n return acc.concat([placement + \"-\" + start, placement + \"-\" + end]);\n}, []);\nexport var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {\n return acc.concat([placement, placement + \"-\" + start, placement + \"-\" + end]);\n}, []); // modifiers that need to read the DOM\n\nexport var beforeRead = 'beforeRead';\nexport var read = 'read';\nexport var afterRead = 'afterRead'; // pure-logic modifiers\n\nexport var beforeMain = 'beforeMain';\nexport var main = 'main';\nexport var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)\n\nexport var beforeWrite = 'beforeWrite';\nexport var write = 'write';\nexport var afterWrite = 'afterWrite';\nexport var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];","export default function getNodeName(element) {\n return element ? (element.nodeName || '').toLowerCase() : null;\n}","export default function getWindow(node) {\n if (node == null) {\n return window;\n }\n\n if (node.toString() !== '[object Window]') {\n var ownerDocument = node.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView || window : window;\n }\n\n return node;\n}","import getWindow from \"./getWindow.js\";\n\nfunction isElement(node) {\n var OwnElement = getWindow(node).Element;\n return node instanceof OwnElement || node instanceof Element;\n}\n\nfunction isHTMLElement(node) {\n var OwnElement = getWindow(node).HTMLElement;\n return node instanceof OwnElement || node instanceof HTMLElement;\n}\n\nfunction isShadowRoot(node) {\n // IE 11 has no ShadowRoot\n if (typeof ShadowRoot === 'undefined') {\n return false;\n }\n\n var OwnElement = getWindow(node).ShadowRoot;\n return node instanceof OwnElement || node instanceof ShadowRoot;\n}\n\nexport { isElement, isHTMLElement, isShadowRoot };","import getNodeName from \"../dom-utils/getNodeName.js\";\nimport { isHTMLElement } from \"../dom-utils/instanceOf.js\"; // This modifier takes the styles prepared by the `computeStyles` modifier\n// and applies them to the HTMLElements such as popper and arrow\n\nfunction applyStyles(_ref) {\n var state = _ref.state;\n Object.keys(state.elements).forEach(function (name) {\n var style = state.styles[name] || {};\n var attributes = state.attributes[name] || {};\n var element = state.elements[name]; // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n } // Flow doesn't support to extend this property, but it's the most\n // effective way to apply styles to an HTMLElement\n // $FlowFixMe[cannot-write]\n\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (name) {\n var value = attributes[name];\n\n if (value === false) {\n element.removeAttribute(name);\n } else {\n element.setAttribute(name, value === true ? '' : value);\n }\n });\n });\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state;\n var initialStyles = {\n popper: {\n position: state.options.strategy,\n left: '0',\n top: '0',\n margin: '0'\n },\n arrow: {\n position: 'absolute'\n },\n reference: {}\n };\n Object.assign(state.elements.popper.style, initialStyles.popper);\n state.styles = initialStyles;\n\n if (state.elements.arrow) {\n Object.assign(state.elements.arrow.style, initialStyles.arrow);\n }\n\n return function () {\n Object.keys(state.elements).forEach(function (name) {\n var element = state.elements[name];\n var attributes = state.attributes[name] || {};\n var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them\n\n var style = styleProperties.reduce(function (style, property) {\n style[property] = '';\n return style;\n }, {}); // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n }\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (attribute) {\n element.removeAttribute(attribute);\n });\n });\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'applyStyles',\n enabled: true,\n phase: 'write',\n fn: applyStyles,\n effect: effect,\n requires: ['computeStyles']\n};","import { auto } from \"../enums.js\";\nexport default function getBasePlacement(placement) {\n return placement.split('-')[0];\n}","export var max = Math.max;\nexport var min = Math.min;\nexport var round = Math.round;","export default function getUAString() {\n var uaData = navigator.userAgentData;\n\n if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {\n return uaData.brands.map(function (item) {\n return item.brand + \"/\" + item.version;\n }).join(' ');\n }\n\n return navigator.userAgent;\n}","import getUAString from \"../utils/userAgent.js\";\nexport default function isLayoutViewport() {\n return !/^((?!chrome|android).)*safari/i.test(getUAString());\n}","import { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport { round } from \"../utils/math.js\";\nimport getWindow from \"./getWindow.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getBoundingClientRect(element, includeScale, isFixedStrategy) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n\n var clientRect = element.getBoundingClientRect();\n var scaleX = 1;\n var scaleY = 1;\n\n if (includeScale && isHTMLElement(element)) {\n scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;\n scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;\n }\n\n var _ref = isElement(element) ? getWindow(element) : window,\n visualViewport = _ref.visualViewport;\n\n var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;\n var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;\n var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;\n var width = clientRect.width / scaleX;\n var height = clientRect.height / scaleY;\n return {\n width: width,\n height: height,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x,\n x: x,\n y: y\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\"; // Returns the layout rect of an element relative to its offsetParent. Layout\n// means it doesn't take into account transforms.\n\nexport default function getLayoutRect(element) {\n var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.\n // Fixes https://github.com/popperjs/popper-core/issues/1223\n\n var width = element.offsetWidth;\n var height = element.offsetHeight;\n\n if (Math.abs(clientRect.width - width) <= 1) {\n width = clientRect.width;\n }\n\n if (Math.abs(clientRect.height - height) <= 1) {\n height = clientRect.height;\n }\n\n return {\n x: element.offsetLeft,\n y: element.offsetTop,\n width: width,\n height: height\n };\n}","import { isShadowRoot } from \"./instanceOf.js\";\nexport default function contains(parent, child) {\n var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method\n\n if (parent.contains(child)) {\n return true;\n } // then fallback to custom implementation with Shadow DOM support\n else if (rootNode && isShadowRoot(rootNode)) {\n var next = child;\n\n do {\n if (next && parent.isSameNode(next)) {\n return true;\n } // $FlowFixMe[prop-missing]: need a better way to handle this...\n\n\n next = next.parentNode || next.host;\n } while (next);\n } // Give up, the result is false\n\n\n return false;\n}","import getWindow from \"./getWindow.js\";\nexport default function getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}","import getNodeName from \"./getNodeName.js\";\nexport default function isTableElement(element) {\n return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;\n}","import { isElement } from \"./instanceOf.js\";\nexport default function getDocumentElement(element) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]\n element.document) || window.document).documentElement;\n}","import getNodeName from \"./getNodeName.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport { isShadowRoot } from \"./instanceOf.js\";\nexport default function getParentNode(element) {\n if (getNodeName(element) === 'html') {\n return element;\n }\n\n return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle\n // $FlowFixMe[incompatible-return]\n // $FlowFixMe[prop-missing]\n element.assignedSlot || // step into the shadow DOM of the parent of a slotted node\n element.parentNode || ( // DOM Element detected\n isShadowRoot(element) ? element.host : null) || // ShadowRoot detected\n // $FlowFixMe[incompatible-call]: HTMLElement is a Node\n getDocumentElement(element) // fallback\n\n );\n}","import getWindow from \"./getWindow.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isHTMLElement, isShadowRoot } from \"./instanceOf.js\";\nimport isTableElement from \"./isTableElement.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getUAString from \"../utils/userAgent.js\";\n\nfunction getTrueOffsetParent(element) {\n if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837\n getComputedStyle(element).position === 'fixed') {\n return null;\n }\n\n return element.offsetParent;\n} // `.offsetParent` reports `null` for fixed elements, while absolute elements\n// return the containing block\n\n\nfunction getContainingBlock(element) {\n var isFirefox = /firefox/i.test(getUAString());\n var isIE = /Trident/i.test(getUAString());\n\n if (isIE && isHTMLElement(element)) {\n // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport\n var elementCss = getComputedStyle(element);\n\n if (elementCss.position === 'fixed') {\n return null;\n }\n }\n\n var currentNode = getParentNode(element);\n\n if (isShadowRoot(currentNode)) {\n currentNode = currentNode.host;\n }\n\n while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {\n var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that\n // create a containing block.\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n\n if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {\n return currentNode;\n } else {\n currentNode = currentNode.parentNode;\n }\n }\n\n return null;\n} // Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\n\n\nexport default function getOffsetParent(element) {\n var window = getWindow(element);\n var offsetParent = getTrueOffsetParent(element);\n\n while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {\n offsetParent = getTrueOffsetParent(offsetParent);\n }\n\n if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {\n return window;\n }\n\n return offsetParent || getContainingBlock(element) || window;\n}","export default function getMainAxisFromPlacement(placement) {\n return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';\n}","import { max as mathMax, min as mathMin } from \"./math.js\";\nexport function within(min, value, max) {\n return mathMax(min, mathMin(value, max));\n}\nexport function withinMaxClamp(min, value, max) {\n var v = within(min, value, max);\n return v > max ? max : v;\n}","import getFreshSideObject from \"./getFreshSideObject.js\";\nexport default function mergePaddingObject(paddingObject) {\n return Object.assign({}, getFreshSideObject(), paddingObject);\n}","export default function getFreshSideObject() {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n}","export default function expandToHashMap(value, keys) {\n return keys.reduce(function (hashMap, key) {\n hashMap[key] = value;\n return hashMap;\n }, {});\n}","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport contains from \"../dom-utils/contains.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport { within } from \"../utils/within.js\";\nimport mergePaddingObject from \"../utils/mergePaddingObject.js\";\nimport expandToHashMap from \"../utils/expandToHashMap.js\";\nimport { left, right, basePlacements, top, bottom } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar toPaddingObject = function toPaddingObject(padding, state) {\n padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {\n placement: state.placement\n })) : padding;\n return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n};\n\nfunction arrow(_ref) {\n var _state$modifiersData$;\n\n var state = _ref.state,\n name = _ref.name,\n options = _ref.options;\n var arrowElement = state.elements.arrow;\n var popperOffsets = state.modifiersData.popperOffsets;\n var basePlacement = getBasePlacement(state.placement);\n var axis = getMainAxisFromPlacement(basePlacement);\n var isVertical = [left, right].indexOf(basePlacement) >= 0;\n var len = isVertical ? 'height' : 'width';\n\n if (!arrowElement || !popperOffsets) {\n return;\n }\n\n var paddingObject = toPaddingObject(options.padding, state);\n var arrowRect = getLayoutRect(arrowElement);\n var minProp = axis === 'y' ? top : left;\n var maxProp = axis === 'y' ? bottom : right;\n var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];\n var startDiff = popperOffsets[axis] - state.rects.reference[axis];\n var arrowOffsetParent = getOffsetParent(arrowElement);\n var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;\n var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is\n // outside of the popper bounds\n\n var min = paddingObject[minProp];\n var max = clientSize - arrowRect[len] - paddingObject[maxProp];\n var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;\n var offset = within(min, center, max); // Prevents breaking syntax highlighting...\n\n var axisProp = axis;\n state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state,\n options = _ref2.options;\n var _options$element = options.element,\n arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;\n\n if (arrowElement == null) {\n return;\n } // CSS selector\n\n\n if (typeof arrowElement === 'string') {\n arrowElement = state.elements.popper.querySelector(arrowElement);\n\n if (!arrowElement) {\n return;\n }\n }\n\n if (!contains(state.elements.popper, arrowElement)) {\n return;\n }\n\n state.elements.arrow = arrowElement;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'arrow',\n enabled: true,\n phase: 'main',\n fn: arrow,\n effect: effect,\n requires: ['popperOffsets'],\n requiresIfExists: ['preventOverflow']\n};","export default function getVariation(placement) {\n return placement.split('-')[1];\n}","import { top, left, right, bottom, end } from \"../enums.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getWindow from \"../dom-utils/getWindow.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getComputedStyle from \"../dom-utils/getComputedStyle.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport { round } from \"../utils/math.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar unsetSides = {\n top: 'auto',\n right: 'auto',\n bottom: 'auto',\n left: 'auto'\n}; // Round the offsets to the nearest suitable subpixel based on the DPR.\n// Zooming can change the DPR, but it seems to report a value that will\n// cleanly divide the values into the appropriate subpixels.\n\nfunction roundOffsetsByDPR(_ref, win) {\n var x = _ref.x,\n y = _ref.y;\n var dpr = win.devicePixelRatio || 1;\n return {\n x: round(x * dpr) / dpr || 0,\n y: round(y * dpr) / dpr || 0\n };\n}\n\nexport function mapToStyles(_ref2) {\n var _Object$assign2;\n\n var popper = _ref2.popper,\n popperRect = _ref2.popperRect,\n placement = _ref2.placement,\n variation = _ref2.variation,\n offsets = _ref2.offsets,\n position = _ref2.position,\n gpuAcceleration = _ref2.gpuAcceleration,\n adaptive = _ref2.adaptive,\n roundOffsets = _ref2.roundOffsets,\n isFixed = _ref2.isFixed;\n var _offsets$x = offsets.x,\n x = _offsets$x === void 0 ? 0 : _offsets$x,\n _offsets$y = offsets.y,\n y = _offsets$y === void 0 ? 0 : _offsets$y;\n\n var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({\n x: x,\n y: y\n }) : {\n x: x,\n y: y\n };\n\n x = _ref3.x;\n y = _ref3.y;\n var hasX = offsets.hasOwnProperty('x');\n var hasY = offsets.hasOwnProperty('y');\n var sideX = left;\n var sideY = top;\n var win = window;\n\n if (adaptive) {\n var offsetParent = getOffsetParent(popper);\n var heightProp = 'clientHeight';\n var widthProp = 'clientWidth';\n\n if (offsetParent === getWindow(popper)) {\n offsetParent = getDocumentElement(popper);\n\n if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {\n heightProp = 'scrollHeight';\n widthProp = 'scrollWidth';\n }\n } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it\n\n\n offsetParent = offsetParent;\n\n if (placement === top || (placement === left || placement === right) && variation === end) {\n sideY = bottom;\n var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]\n offsetParent[heightProp];\n y -= offsetY - popperRect.height;\n y *= gpuAcceleration ? 1 : -1;\n }\n\n if (placement === left || (placement === top || placement === bottom) && variation === end) {\n sideX = right;\n var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]\n offsetParent[widthProp];\n x -= offsetX - popperRect.width;\n x *= gpuAcceleration ? 1 : -1;\n }\n }\n\n var commonStyles = Object.assign({\n position: position\n }, adaptive && unsetSides);\n\n var _ref4 = roundOffsets === true ? roundOffsetsByDPR({\n x: x,\n y: y\n }, getWindow(popper)) : {\n x: x,\n y: y\n };\n\n x = _ref4.x;\n y = _ref4.y;\n\n if (gpuAcceleration) {\n var _Object$assign;\n\n return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? \"translate(\" + x + \"px, \" + y + \"px)\" : \"translate3d(\" + x + \"px, \" + y + \"px, 0)\", _Object$assign));\n }\n\n return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + \"px\" : '', _Object$assign2[sideX] = hasX ? x + \"px\" : '', _Object$assign2.transform = '', _Object$assign2));\n}\n\nfunction computeStyles(_ref5) {\n var state = _ref5.state,\n options = _ref5.options;\n var _options$gpuAccelerat = options.gpuAcceleration,\n gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,\n _options$adaptive = options.adaptive,\n adaptive = _options$adaptive === void 0 ? true : _options$adaptive,\n _options$roundOffsets = options.roundOffsets,\n roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;\n var commonStyles = {\n placement: getBasePlacement(state.placement),\n variation: getVariation(state.placement),\n popper: state.elements.popper,\n popperRect: state.rects.popper,\n gpuAcceleration: gpuAcceleration,\n isFixed: state.options.strategy === 'fixed'\n };\n\n if (state.modifiersData.popperOffsets != null) {\n state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.popperOffsets,\n position: state.options.strategy,\n adaptive: adaptive,\n roundOffsets: roundOffsets\n })));\n }\n\n if (state.modifiersData.arrow != null) {\n state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.arrow,\n position: 'absolute',\n adaptive: false,\n roundOffsets: roundOffsets\n })));\n }\n\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-placement': state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'computeStyles',\n enabled: true,\n phase: 'beforeWrite',\n fn: computeStyles,\n data: {}\n};","import getWindow from \"../dom-utils/getWindow.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar passive = {\n passive: true\n};\n\nfunction effect(_ref) {\n var state = _ref.state,\n instance = _ref.instance,\n options = _ref.options;\n var _options$scroll = options.scroll,\n scroll = _options$scroll === void 0 ? true : _options$scroll,\n _options$resize = options.resize,\n resize = _options$resize === void 0 ? true : _options$resize;\n var window = getWindow(state.elements.popper);\n var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);\n\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.addEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.addEventListener('resize', instance.update, passive);\n }\n\n return function () {\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.removeEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.removeEventListener('resize', instance.update, passive);\n }\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'eventListeners',\n enabled: true,\n phase: 'write',\n fn: function fn() {},\n effect: effect,\n data: {}\n};","var hash = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nexport default function getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}","var hash = {\n start: 'end',\n end: 'start'\n};\nexport default function getOppositeVariationPlacement(placement) {\n return placement.replace(/start|end/g, function (matched) {\n return hash[matched];\n });\n}","import getWindow from \"./getWindow.js\";\nexport default function getWindowScroll(node) {\n var win = getWindow(node);\n var scrollLeft = win.pageXOffset;\n var scrollTop = win.pageYOffset;\n return {\n scrollLeft: scrollLeft,\n scrollTop: scrollTop\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nexport default function getWindowScrollBarX(element) {\n // If has a CSS width greater than the viewport, then this will be\n // incorrect for RTL.\n // Popper 1 is broken in this case and never had a bug report so let's assume\n // it's not an issue. I don't think anyone ever specifies width on \n // anyway.\n // Browsers where the left scrollbar doesn't cause an issue report `0` for\n // this (e.g. Edge 2019, IE11, Safari)\n return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;\n}","import getComputedStyle from \"./getComputedStyle.js\";\nexport default function isScrollParent(element) {\n // Firefox wants us to check `-x` and `-y` variations as well\n var _getComputedStyle = getComputedStyle(element),\n overflow = _getComputedStyle.overflow,\n overflowX = _getComputedStyle.overflowX,\n overflowY = _getComputedStyle.overflowY;\n\n return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);\n}","import getParentNode from \"./getParentNode.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nexport default function getScrollParent(node) {\n if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return node.ownerDocument.body;\n }\n\n if (isHTMLElement(node) && isScrollParent(node)) {\n return node;\n }\n\n return getScrollParent(getParentNode(node));\n}","import getScrollParent from \"./getScrollParent.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getWindow from \"./getWindow.js\";\nimport isScrollParent from \"./isScrollParent.js\";\n/*\ngiven a DOM element, return the list of all scroll parents, up the list of ancesors\nuntil we get to the top window object. This list is what we attach scroll listeners\nto, because if any of these parent elements scroll, we'll need to re-calculate the\nreference element's position.\n*/\n\nexport default function listScrollParents(element, list) {\n var _element$ownerDocumen;\n\n if (list === void 0) {\n list = [];\n }\n\n var scrollParent = getScrollParent(element);\n var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);\n var win = getWindow(scrollParent);\n var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;\n var updatedList = list.concat(target);\n return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here\n updatedList.concat(listScrollParents(getParentNode(target)));\n}","export default function rectToClientRect(rect) {\n return Object.assign({}, rect, {\n left: rect.x,\n top: rect.y,\n right: rect.x + rect.width,\n bottom: rect.y + rect.height\n });\n}","import { viewport } from \"../enums.js\";\nimport getViewportRect from \"./getViewportRect.js\";\nimport getDocumentRect from \"./getDocumentRect.js\";\nimport listScrollParents from \"./listScrollParents.js\";\nimport getOffsetParent from \"./getOffsetParent.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport contains from \"./contains.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport rectToClientRect from \"../utils/rectToClientRect.js\";\nimport { max, min } from \"../utils/math.js\";\n\nfunction getInnerBoundingClientRect(element, strategy) {\n var rect = getBoundingClientRect(element, false, strategy === 'fixed');\n rect.top = rect.top + element.clientTop;\n rect.left = rect.left + element.clientLeft;\n rect.bottom = rect.top + element.clientHeight;\n rect.right = rect.left + element.clientWidth;\n rect.width = element.clientWidth;\n rect.height = element.clientHeight;\n rect.x = rect.left;\n rect.y = rect.top;\n return rect;\n}\n\nfunction getClientRectFromMixedType(element, clippingParent, strategy) {\n return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));\n} // A \"clipping parent\" is an overflowable container with the characteristic of\n// clipping (or hiding) overflowing elements with a position different from\n// `initial`\n\n\nfunction getClippingParents(element) {\n var clippingParents = listScrollParents(getParentNode(element));\n var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;\n var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;\n\n if (!isElement(clipperElement)) {\n return [];\n } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414\n\n\n return clippingParents.filter(function (clippingParent) {\n return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';\n });\n} // Gets the maximum area that the element is visible in due to any number of\n// clipping parents\n\n\nexport default function getClippingRect(element, boundary, rootBoundary, strategy) {\n var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);\n var clippingParents = [].concat(mainClippingParents, [rootBoundary]);\n var firstClippingParent = clippingParents[0];\n var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {\n var rect = getClientRectFromMixedType(element, clippingParent, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromMixedType(element, firstClippingParent, strategy));\n clippingRect.width = clippingRect.right - clippingRect.left;\n clippingRect.height = clippingRect.bottom - clippingRect.top;\n clippingRect.x = clippingRect.left;\n clippingRect.y = clippingRect.top;\n return clippingRect;\n}","import getWindow from \"./getWindow.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getViewportRect(element, strategy) {\n var win = getWindow(element);\n var html = getDocumentElement(element);\n var visualViewport = win.visualViewport;\n var width = html.clientWidth;\n var height = html.clientHeight;\n var x = 0;\n var y = 0;\n\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n var layoutViewport = isLayoutViewport();\n\n if (layoutViewport || !layoutViewport && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n\n return {\n width: width,\n height: height,\n x: x + getWindowScrollBarX(element),\n y: y\n };\n}","import getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nimport { max } from \"../utils/math.js\"; // Gets the entire size of the scrollable document area, even extending outside\n// of the `` and `` rect bounds if horizontally scrollable\n\nexport default function getDocumentRect(element) {\n var _element$ownerDocumen;\n\n var html = getDocumentElement(element);\n var winScroll = getWindowScroll(element);\n var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;\n var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);\n var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);\n var x = -winScroll.scrollLeft + getWindowScrollBarX(element);\n var y = -winScroll.scrollTop;\n\n if (getComputedStyle(body || html).direction === 'rtl') {\n x += max(html.clientWidth, body ? body.clientWidth : 0) - width;\n }\n\n return {\n width: width,\n height: height,\n x: x,\n y: y\n };\n}","import getBasePlacement from \"./getBasePlacement.js\";\nimport getVariation from \"./getVariation.js\";\nimport getMainAxisFromPlacement from \"./getMainAxisFromPlacement.js\";\nimport { top, right, bottom, left, start, end } from \"../enums.js\";\nexport default function computeOffsets(_ref) {\n var reference = _ref.reference,\n element = _ref.element,\n placement = _ref.placement;\n var basePlacement = placement ? getBasePlacement(placement) : null;\n var variation = placement ? getVariation(placement) : null;\n var commonX = reference.x + reference.width / 2 - element.width / 2;\n var commonY = reference.y + reference.height / 2 - element.height / 2;\n var offsets;\n\n switch (basePlacement) {\n case top:\n offsets = {\n x: commonX,\n y: reference.y - element.height\n };\n break;\n\n case bottom:\n offsets = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n\n case right:\n offsets = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n\n case left:\n offsets = {\n x: reference.x - element.width,\n y: commonY\n };\n break;\n\n default:\n offsets = {\n x: reference.x,\n y: reference.y\n };\n }\n\n var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;\n\n if (mainAxis != null) {\n var len = mainAxis === 'y' ? 'height' : 'width';\n\n switch (variation) {\n case start:\n offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);\n break;\n\n case end:\n offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);\n break;\n\n default:\n }\n }\n\n return offsets;\n}","import getClippingRect from \"../dom-utils/getClippingRect.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getBoundingClientRect from \"../dom-utils/getBoundingClientRect.js\";\nimport computeOffsets from \"./computeOffsets.js\";\nimport rectToClientRect from \"./rectToClientRect.js\";\nimport { clippingParents, reference, popper, bottom, top, right, basePlacements, viewport } from \"../enums.js\";\nimport { isElement } from \"../dom-utils/instanceOf.js\";\nimport mergePaddingObject from \"./mergePaddingObject.js\";\nimport expandToHashMap from \"./expandToHashMap.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport default function detectOverflow(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n _options$placement = _options.placement,\n placement = _options$placement === void 0 ? state.placement : _options$placement,\n _options$strategy = _options.strategy,\n strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,\n _options$boundary = _options.boundary,\n boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,\n _options$rootBoundary = _options.rootBoundary,\n rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,\n _options$elementConte = _options.elementContext,\n elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,\n _options$altBoundary = _options.altBoundary,\n altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,\n _options$padding = _options.padding,\n padding = _options$padding === void 0 ? 0 : _options$padding;\n var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n var altContext = elementContext === popper ? reference : popper;\n var popperRect = state.rects.popper;\n var element = state.elements[altBoundary ? altContext : elementContext];\n var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);\n var referenceClientRect = getBoundingClientRect(state.elements.reference);\n var popperOffsets = computeOffsets({\n reference: referenceClientRect,\n element: popperRect,\n strategy: 'absolute',\n placement: placement\n });\n var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));\n var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect\n // 0 or negative = within the clipping rect\n\n var overflowOffsets = {\n top: clippingClientRect.top - elementClientRect.top + paddingObject.top,\n bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - elementClientRect.left + paddingObject.left,\n right: elementClientRect.right - clippingClientRect.right + paddingObject.right\n };\n var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element\n\n if (elementContext === popper && offsetData) {\n var offset = offsetData[placement];\n Object.keys(overflowOffsets).forEach(function (key) {\n var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;\n var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key] += offset[axis] * multiply;\n });\n }\n\n return overflowOffsets;\n}","import getVariation from \"./getVariation.js\";\nimport { variationPlacements, basePlacements, placements as allPlacements } from \"../enums.js\";\nimport detectOverflow from \"./detectOverflow.js\";\nimport getBasePlacement from \"./getBasePlacement.js\";\nexport default function computeAutoPlacement(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n placement = _options.placement,\n boundary = _options.boundary,\n rootBoundary = _options.rootBoundary,\n padding = _options.padding,\n flipVariations = _options.flipVariations,\n _options$allowedAutoP = _options.allowedAutoPlacements,\n allowedAutoPlacements = _options$allowedAutoP === void 0 ? allPlacements : _options$allowedAutoP;\n var variation = getVariation(placement);\n var placements = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {\n return getVariation(placement) === variation;\n }) : basePlacements;\n var allowedPlacements = placements.filter(function (placement) {\n return allowedAutoPlacements.indexOf(placement) >= 0;\n });\n\n if (allowedPlacements.length === 0) {\n allowedPlacements = placements;\n } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...\n\n\n var overflows = allowedPlacements.reduce(function (acc, placement) {\n acc[placement] = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding\n })[getBasePlacement(placement)];\n return acc;\n }, {});\n return Object.keys(overflows).sort(function (a, b) {\n return overflows[a] - overflows[b];\n });\n}","import getOppositePlacement from \"../utils/getOppositePlacement.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getOppositeVariationPlacement from \"../utils/getOppositeVariationPlacement.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport computeAutoPlacement from \"../utils/computeAutoPlacement.js\";\nimport { bottom, top, start, right, left, auto } from \"../enums.js\";\nimport getVariation from \"../utils/getVariation.js\"; // eslint-disable-next-line import/no-unused-modules\n\nfunction getExpandedFallbackPlacements(placement) {\n if (getBasePlacement(placement) === auto) {\n return [];\n }\n\n var oppositePlacement = getOppositePlacement(placement);\n return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];\n}\n\nfunction flip(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n\n if (state.modifiersData[name]._skip) {\n return;\n }\n\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,\n specifiedFallbackPlacements = options.fallbackPlacements,\n padding = options.padding,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n _options$flipVariatio = options.flipVariations,\n flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,\n allowedAutoPlacements = options.allowedAutoPlacements;\n var preferredPlacement = state.options.placement;\n var basePlacement = getBasePlacement(preferredPlacement);\n var isBasePlacement = basePlacement === preferredPlacement;\n var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));\n var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {\n return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n flipVariations: flipVariations,\n allowedAutoPlacements: allowedAutoPlacements\n }) : placement);\n }, []);\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var checksMap = new Map();\n var makeFallbackChecks = true;\n var firstFittingPlacement = placements[0];\n\n for (var i = 0; i < placements.length; i++) {\n var placement = placements[i];\n\n var _basePlacement = getBasePlacement(placement);\n\n var isStartVariation = getVariation(placement) === start;\n var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;\n var len = isVertical ? 'width' : 'height';\n var overflow = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n altBoundary: altBoundary,\n padding: padding\n });\n var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;\n\n if (referenceRect[len] > popperRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide);\n }\n\n var altVariationSide = getOppositePlacement(mainVariationSide);\n var checks = [];\n\n if (checkMainAxis) {\n checks.push(overflow[_basePlacement] <= 0);\n }\n\n if (checkAltAxis) {\n checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);\n }\n\n if (checks.every(function (check) {\n return check;\n })) {\n firstFittingPlacement = placement;\n makeFallbackChecks = false;\n break;\n }\n\n checksMap.set(placement, checks);\n }\n\n if (makeFallbackChecks) {\n // `2` may be desired in some cases – research later\n var numberOfChecks = flipVariations ? 3 : 1;\n\n var _loop = function _loop(_i) {\n var fittingPlacement = placements.find(function (placement) {\n var checks = checksMap.get(placement);\n\n if (checks) {\n return checks.slice(0, _i).every(function (check) {\n return check;\n });\n }\n });\n\n if (fittingPlacement) {\n firstFittingPlacement = fittingPlacement;\n return \"break\";\n }\n };\n\n for (var _i = numberOfChecks; _i > 0; _i--) {\n var _ret = _loop(_i);\n\n if (_ret === \"break\") break;\n }\n }\n\n if (state.placement !== firstFittingPlacement) {\n state.modifiersData[name]._skip = true;\n state.placement = firstFittingPlacement;\n state.reset = true;\n }\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'flip',\n enabled: true,\n phase: 'main',\n fn: flip,\n requiresIfExists: ['offset'],\n data: {\n _skip: false\n }\n};","import { top, bottom, left, right } from \"../enums.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\n\nfunction getSideOffsets(overflow, rect, preventedOffsets) {\n if (preventedOffsets === void 0) {\n preventedOffsets = {\n x: 0,\n y: 0\n };\n }\n\n return {\n top: overflow.top - rect.height - preventedOffsets.y,\n right: overflow.right - rect.width + preventedOffsets.x,\n bottom: overflow.bottom - rect.height + preventedOffsets.y,\n left: overflow.left - rect.width - preventedOffsets.x\n };\n}\n\nfunction isAnySideFullyClipped(overflow) {\n return [top, right, bottom, left].some(function (side) {\n return overflow[side] >= 0;\n });\n}\n\nfunction hide(_ref) {\n var state = _ref.state,\n name = _ref.name;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var preventedOffsets = state.modifiersData.preventOverflow;\n var referenceOverflow = detectOverflow(state, {\n elementContext: 'reference'\n });\n var popperAltOverflow = detectOverflow(state, {\n altBoundary: true\n });\n var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);\n var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);\n var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);\n var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);\n state.modifiersData[name] = {\n referenceClippingOffsets: referenceClippingOffsets,\n popperEscapeOffsets: popperEscapeOffsets,\n isReferenceHidden: isReferenceHidden,\n hasPopperEscaped: hasPopperEscaped\n };\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-reference-hidden': isReferenceHidden,\n 'data-popper-escaped': hasPopperEscaped\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'hide',\n enabled: true,\n phase: 'main',\n requiresIfExists: ['preventOverflow'],\n fn: hide\n};","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport { top, left, right, placements } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport function distanceAndSkiddingToXY(placement, rects, offset) {\n var basePlacement = getBasePlacement(placement);\n var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;\n\n var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {\n placement: placement\n })) : offset,\n skidding = _ref[0],\n distance = _ref[1];\n\n skidding = skidding || 0;\n distance = (distance || 0) * invertDistance;\n return [left, right].indexOf(basePlacement) >= 0 ? {\n x: distance,\n y: skidding\n } : {\n x: skidding,\n y: distance\n };\n}\n\nfunction offset(_ref2) {\n var state = _ref2.state,\n options = _ref2.options,\n name = _ref2.name;\n var _options$offset = options.offset,\n offset = _options$offset === void 0 ? [0, 0] : _options$offset;\n var data = placements.reduce(function (acc, placement) {\n acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);\n return acc;\n }, {});\n var _data$state$placement = data[state.placement],\n x = _data$state$placement.x,\n y = _data$state$placement.y;\n\n if (state.modifiersData.popperOffsets != null) {\n state.modifiersData.popperOffsets.x += x;\n state.modifiersData.popperOffsets.y += y;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'offset',\n enabled: true,\n phase: 'main',\n requires: ['popperOffsets'],\n fn: offset\n};","import computeOffsets from \"../utils/computeOffsets.js\";\n\nfunction popperOffsets(_ref) {\n var state = _ref.state,\n name = _ref.name;\n // Offsets are the actual position the popper needs to have to be\n // properly positioned near its reference element\n // This is the most basic placement, and will be adjusted by\n // the modifiers in the next step\n state.modifiersData[name] = computeOffsets({\n reference: state.rects.reference,\n element: state.rects.popper,\n strategy: 'absolute',\n placement: state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'popperOffsets',\n enabled: true,\n phase: 'read',\n fn: popperOffsets,\n data: {}\n};","import { top, left, right, bottom, start } from \"../enums.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport getAltAxis from \"../utils/getAltAxis.js\";\nimport { within, withinMaxClamp } from \"../utils/within.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport getFreshSideObject from \"../utils/getFreshSideObject.js\";\nimport { min as mathMin, max as mathMax } from \"../utils/math.js\";\n\nfunction preventOverflow(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n padding = options.padding,\n _options$tether = options.tether,\n tether = _options$tether === void 0 ? true : _options$tether,\n _options$tetherOffset = options.tetherOffset,\n tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;\n var overflow = detectOverflow(state, {\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n altBoundary: altBoundary\n });\n var basePlacement = getBasePlacement(state.placement);\n var variation = getVariation(state.placement);\n var isBasePlacement = !variation;\n var mainAxis = getMainAxisFromPlacement(basePlacement);\n var altAxis = getAltAxis(mainAxis);\n var popperOffsets = state.modifiersData.popperOffsets;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {\n placement: state.placement\n })) : tetherOffset;\n var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {\n mainAxis: tetherOffsetValue,\n altAxis: tetherOffsetValue\n } : Object.assign({\n mainAxis: 0,\n altAxis: 0\n }, tetherOffsetValue);\n var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;\n var data = {\n x: 0,\n y: 0\n };\n\n if (!popperOffsets) {\n return;\n }\n\n if (checkMainAxis) {\n var _offsetModifierState$;\n\n var mainSide = mainAxis === 'y' ? top : left;\n var altSide = mainAxis === 'y' ? bottom : right;\n var len = mainAxis === 'y' ? 'height' : 'width';\n var offset = popperOffsets[mainAxis];\n var min = offset + overflow[mainSide];\n var max = offset - overflow[altSide];\n var additive = tether ? -popperRect[len] / 2 : 0;\n var minLen = variation === start ? referenceRect[len] : popperRect[len];\n var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go\n // outside the reference bounds\n\n var arrowElement = state.elements.arrow;\n var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {\n width: 0,\n height: 0\n };\n var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();\n var arrowPaddingMin = arrowPaddingObject[mainSide];\n var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want\n // to include its full size in the calculation. If the reference is small\n // and near the edge of a boundary, the popper can overflow even if the\n // reference is not overflowing as well (e.g. virtual elements with no\n // width or height)\n\n var arrowLen = within(0, referenceRect[len], arrowRect[len]);\n var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;\n var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;\n var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);\n var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;\n var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;\n var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;\n var tetherMax = offset + maxOffset - offsetModifierValue;\n var preventedOffset = within(tether ? mathMin(min, tetherMin) : min, offset, tether ? mathMax(max, tetherMax) : max);\n popperOffsets[mainAxis] = preventedOffset;\n data[mainAxis] = preventedOffset - offset;\n }\n\n if (checkAltAxis) {\n var _offsetModifierState$2;\n\n var _mainSide = mainAxis === 'x' ? top : left;\n\n var _altSide = mainAxis === 'x' ? bottom : right;\n\n var _offset = popperOffsets[altAxis];\n\n var _len = altAxis === 'y' ? 'height' : 'width';\n\n var _min = _offset + overflow[_mainSide];\n\n var _max = _offset - overflow[_altSide];\n\n var isOriginSide = [top, left].indexOf(basePlacement) !== -1;\n\n var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;\n\n var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;\n\n var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;\n\n var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);\n\n popperOffsets[altAxis] = _preventedOffset;\n data[altAxis] = _preventedOffset - _offset;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'preventOverflow',\n enabled: true,\n phase: 'main',\n fn: preventOverflow,\n requiresIfExists: ['offset']\n};","export default function getAltAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getNodeScroll from \"./getNodeScroll.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport { round } from \"../utils/math.js\";\n\nfunction isElementScaled(element) {\n var rect = element.getBoundingClientRect();\n var scaleX = round(rect.width) / element.offsetWidth || 1;\n var scaleY = round(rect.height) / element.offsetHeight || 1;\n return scaleX !== 1 || scaleY !== 1;\n} // Returns the composite rect of an element relative to its offsetParent.\n// Composite means it takes into account transforms as well as layout.\n\n\nexport default function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n\n var isOffsetParentAnElement = isHTMLElement(offsetParent);\n var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);\n var documentElement = getDocumentElement(offsetParent);\n var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);\n var scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n var offsets = {\n x: 0,\n y: 0\n };\n\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078\n isScrollParent(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n\n if (isHTMLElement(offsetParent)) {\n offsets = getBoundingClientRect(offsetParent, true);\n offsets.x += offsetParent.clientLeft;\n offsets.y += offsetParent.clientTop;\n } else if (documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n\n return {\n x: rect.left + scroll.scrollLeft - offsets.x,\n y: rect.top + scroll.scrollTop - offsets.y,\n width: rect.width,\n height: rect.height\n };\n}","import getWindowScroll from \"./getWindowScroll.js\";\nimport getWindow from \"./getWindow.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getHTMLElementScroll from \"./getHTMLElementScroll.js\";\nexport default function getNodeScroll(node) {\n if (node === getWindow(node) || !isHTMLElement(node)) {\n return getWindowScroll(node);\n } else {\n return getHTMLElementScroll(node);\n }\n}","export default function getHTMLElementScroll(element) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n}","import { modifierPhases } from \"../enums.js\"; // source: https://stackoverflow.com/questions/49875255\n\nfunction order(modifiers) {\n var map = new Map();\n var visited = new Set();\n var result = [];\n modifiers.forEach(function (modifier) {\n map.set(modifier.name, modifier);\n }); // On visiting object, check for its dependencies and visit them recursively\n\n function sort(modifier) {\n visited.add(modifier.name);\n var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);\n requires.forEach(function (dep) {\n if (!visited.has(dep)) {\n var depModifier = map.get(dep);\n\n if (depModifier) {\n sort(depModifier);\n }\n }\n });\n result.push(modifier);\n }\n\n modifiers.forEach(function (modifier) {\n if (!visited.has(modifier.name)) {\n // check for visited object\n sort(modifier);\n }\n });\n return result;\n}\n\nexport default function orderModifiers(modifiers) {\n // order based on dependencies\n var orderedModifiers = order(modifiers); // order based on phase\n\n return modifierPhases.reduce(function (acc, phase) {\n return acc.concat(orderedModifiers.filter(function (modifier) {\n return modifier.phase === phase;\n }));\n }, []);\n}","import getCompositeRect from \"./dom-utils/getCompositeRect.js\";\nimport getLayoutRect from \"./dom-utils/getLayoutRect.js\";\nimport listScrollParents from \"./dom-utils/listScrollParents.js\";\nimport getOffsetParent from \"./dom-utils/getOffsetParent.js\";\nimport orderModifiers from \"./utils/orderModifiers.js\";\nimport debounce from \"./utils/debounce.js\";\nimport mergeByName from \"./utils/mergeByName.js\";\nimport detectOverflow from \"./utils/detectOverflow.js\";\nimport { isElement } from \"./dom-utils/instanceOf.js\";\nvar DEFAULT_OPTIONS = {\n placement: 'bottom',\n modifiers: [],\n strategy: 'absolute'\n};\n\nfunction areValidElements() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return !args.some(function (element) {\n return !(element && typeof element.getBoundingClientRect === 'function');\n });\n}\n\nexport function popperGenerator(generatorOptions) {\n if (generatorOptions === void 0) {\n generatorOptions = {};\n }\n\n var _generatorOptions = generatorOptions,\n _generatorOptions$def = _generatorOptions.defaultModifiers,\n defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,\n _generatorOptions$def2 = _generatorOptions.defaultOptions,\n defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;\n return function createPopper(reference, popper, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n var state = {\n placement: 'bottom',\n orderedModifiers: [],\n options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),\n modifiersData: {},\n elements: {\n reference: reference,\n popper: popper\n },\n attributes: {},\n styles: {}\n };\n var effectCleanupFns = [];\n var isDestroyed = false;\n var instance = {\n state: state,\n setOptions: function setOptions(setOptionsAction) {\n var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;\n cleanupModifierEffects();\n state.options = Object.assign({}, defaultOptions, state.options, options);\n state.scrollParents = {\n reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],\n popper: listScrollParents(popper)\n }; // Orders the modifiers based on their dependencies and `phase`\n // properties\n\n var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers\n\n state.orderedModifiers = orderedModifiers.filter(function (m) {\n return m.enabled;\n });\n runModifierEffects();\n return instance.update();\n },\n // Sync update – it will always be executed, even if not necessary. This\n // is useful for low frequency updates where sync behavior simplifies the\n // logic.\n // For high frequency updates (e.g. `resize` and `scroll` events), always\n // prefer the async Popper#update method\n forceUpdate: function forceUpdate() {\n if (isDestroyed) {\n return;\n }\n\n var _state$elements = state.elements,\n reference = _state$elements.reference,\n popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements\n // anymore\n\n if (!areValidElements(reference, popper)) {\n return;\n } // Store the reference and popper rects to be read by modifiers\n\n\n state.rects = {\n reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),\n popper: getLayoutRect(popper)\n }; // Modifiers have the ability to reset the current update cycle. The\n // most common use case for this is the `flip` modifier changing the\n // placement, which then needs to re-run all the modifiers, because the\n // logic was previously ran for the previous placement and is therefore\n // stale/incorrect\n\n state.reset = false;\n state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier\n // is filled with the initial data specified by the modifier. This means\n // it doesn't persist and is fresh on each update.\n // To ensure persistent data, use `${name}#persistent`\n\n state.orderedModifiers.forEach(function (modifier) {\n return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);\n });\n\n for (var index = 0; index < state.orderedModifiers.length; index++) {\n if (state.reset === true) {\n state.reset = false;\n index = -1;\n continue;\n }\n\n var _state$orderedModifie = state.orderedModifiers[index],\n fn = _state$orderedModifie.fn,\n _state$orderedModifie2 = _state$orderedModifie.options,\n _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,\n name = _state$orderedModifie.name;\n\n if (typeof fn === 'function') {\n state = fn({\n state: state,\n options: _options,\n name: name,\n instance: instance\n }) || state;\n }\n }\n },\n // Async and optimistically optimized update – it will not be executed if\n // not necessary (debounced to run at most once-per-tick)\n update: debounce(function () {\n return new Promise(function (resolve) {\n instance.forceUpdate();\n resolve(state);\n });\n }),\n destroy: function destroy() {\n cleanupModifierEffects();\n isDestroyed = true;\n }\n };\n\n if (!areValidElements(reference, popper)) {\n return instance;\n }\n\n instance.setOptions(options).then(function (state) {\n if (!isDestroyed && options.onFirstUpdate) {\n options.onFirstUpdate(state);\n }\n }); // Modifiers have the ability to execute arbitrary code before the first\n // update cycle runs. They will be executed in the same order as the update\n // cycle. This is useful when a modifier adds some persistent data that\n // other modifiers need to use, but the modifier is run after the dependent\n // one.\n\n function runModifierEffects() {\n state.orderedModifiers.forEach(function (_ref) {\n var name = _ref.name,\n _ref$options = _ref.options,\n options = _ref$options === void 0 ? {} : _ref$options,\n effect = _ref.effect;\n\n if (typeof effect === 'function') {\n var cleanupFn = effect({\n state: state,\n name: name,\n instance: instance,\n options: options\n });\n\n var noopFn = function noopFn() {};\n\n effectCleanupFns.push(cleanupFn || noopFn);\n }\n });\n }\n\n function cleanupModifierEffects() {\n effectCleanupFns.forEach(function (fn) {\n return fn();\n });\n effectCleanupFns = [];\n }\n\n return instance;\n };\n}\nexport var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules\n\nexport { detectOverflow };","export default function debounce(fn) {\n var pending;\n return function () {\n if (!pending) {\n pending = new Promise(function (resolve) {\n Promise.resolve().then(function () {\n pending = undefined;\n resolve(fn());\n });\n });\n }\n\n return pending;\n };\n}","export default function mergeByName(modifiers) {\n var merged = modifiers.reduce(function (merged, current) {\n var existing = merged[current.name];\n merged[current.name] = existing ? Object.assign({}, existing, current, {\n options: Object.assign({}, existing.options, current.options),\n data: Object.assign({}, existing.data, current.data)\n }) : current;\n return merged;\n }, {}); // IE11 does not support Object.values\n\n return Object.keys(merged).map(function (key) {\n return merged[key];\n });\n}","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow };","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nimport offset from \"./modifiers/offset.js\";\nimport flip from \"./modifiers/flip.js\";\nimport preventOverflow from \"./modifiers/preventOverflow.js\";\nimport arrow from \"./modifiers/arrow.js\";\nimport hide from \"./modifiers/hide.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles, offset, flip, preventOverflow, arrow, hide];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow }; // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper as createPopperLite } from \"./popper-lite.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport * from \"./modifiers/index.js\";","/**\n * --------------------------------------------------------------------------\n * Bootstrap dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport * as Popper from '@popperjs/core'\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport Manipulator from './dom/manipulator.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n execute,\n getElement,\n getNextActiveElement,\n isDisabled,\n isElement,\n isRTL,\n isVisible,\n noop\n} from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'dropdown'\nconst DATA_KEY = 'bs.dropdown'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst ESCAPE_KEY = 'Escape'\nconst TAB_KEY = 'Tab'\nconst ARROW_UP_KEY = 'ArrowUp'\nconst ARROW_DOWN_KEY = 'ArrowDown'\nconst RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button\n\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_DROPUP = 'dropup'\nconst CLASS_NAME_DROPEND = 'dropend'\nconst CLASS_NAME_DROPSTART = 'dropstart'\nconst CLASS_NAME_DROPUP_CENTER = 'dropup-center'\nconst CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'\n\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"dropdown\"]:not(.disabled):not(:disabled)'\nconst SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}`\nconst SELECTOR_MENU = '.dropdown-menu'\nconst SELECTOR_NAVBAR = '.navbar'\nconst SELECTOR_NAVBAR_NAV = '.navbar-nav'\nconst SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n\nconst PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'\nconst PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'\nconst PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'\nconst PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'\nconst PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'\nconst PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'\nconst PLACEMENT_TOPCENTER = 'top'\nconst PLACEMENT_BOTTOMCENTER = 'bottom'\n\nconst Default = {\n autoClose: true,\n boundary: 'clippingParents',\n display: 'dynamic',\n offset: [0, 2],\n popperConfig: null,\n reference: 'toggle'\n}\n\nconst DefaultType = {\n autoClose: '(boolean|string)',\n boundary: '(string|element)',\n display: 'string',\n offset: '(array|string|function)',\n popperConfig: '(null|object|function)',\n reference: '(string|element|object)'\n}\n\n/**\n * Class definition\n */\n\nclass Dropdown extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._popper = null\n this._parent = this._element.parentNode // dropdown wrapper\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||\n SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||\n SelectorEngine.findOne(SELECTOR_MENU, this._parent)\n this._inNavbar = this._detectNavbar()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n return this._isShown() ? this.hide() : this.show()\n }\n\n show() {\n if (isDisabled(this._element) || this._isShown()) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, relatedTarget)\n\n if (showEvent.defaultPrevented) {\n return\n }\n\n this._createPopper()\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop)\n }\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n this._menu.classList.add(CLASS_NAME_SHOW)\n this._element.classList.add(CLASS_NAME_SHOW)\n EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget)\n }\n\n hide() {\n if (isDisabled(this._element) || !this._isShown()) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n\n this._completeHide(relatedTarget)\n }\n\n dispose() {\n if (this._popper) {\n this._popper.destroy()\n }\n\n super.dispose()\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper) {\n this._popper.update()\n }\n }\n\n // Private\n _completeHide(relatedTarget) {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget)\n if (hideEvent.defaultPrevented) {\n return\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop)\n }\n }\n\n if (this._popper) {\n this._popper.destroy()\n }\n\n this._menu.classList.remove(CLASS_NAME_SHOW)\n this._element.classList.remove(CLASS_NAME_SHOW)\n this._element.setAttribute('aria-expanded', 'false')\n Manipulator.removeDataAttribute(this._menu, 'popper')\n EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)\n }\n\n _getConfig(config) {\n config = super._getConfig(config)\n\n if (typeof config.reference === 'object' && !isElement(config.reference) &&\n typeof config.reference.getBoundingClientRect !== 'function'\n ) {\n // Popper virtual elements require a getBoundingClientRect method\n throw new TypeError(`${NAME.toUpperCase()}: Option \"reference\" provided type \"object\" without a required \"getBoundingClientRect\" method.`)\n }\n\n return config\n }\n\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s dropdowns require Popper (https://popper.js.org)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = this._parent\n } else if (isElement(this._config.reference)) {\n referenceElement = getElement(this._config.reference)\n } else if (typeof this._config.reference === 'object') {\n referenceElement = this._config.reference\n }\n\n const popperConfig = this._getPopperConfig()\n this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)\n }\n\n _isShown() {\n return this._menu.classList.contains(CLASS_NAME_SHOW)\n }\n\n _getPlacement() {\n const parentDropdown = this._parent\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {\n return PLACEMENT_RIGHT\n }\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {\n return PLACEMENT_LEFT\n }\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {\n return PLACEMENT_TOPCENTER\n }\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {\n return PLACEMENT_BOTTOMCENTER\n }\n\n // We need to trim the value because custom properties can also include spaces\n const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {\n return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP\n }\n\n return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM\n }\n\n _detectNavbar() {\n return this._element.closest(SELECTOR_NAVBAR) !== null\n }\n\n _getOffset() {\n const { offset } = this._config\n\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10))\n }\n\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element)\n }\n\n return offset\n }\n\n _getPopperConfig() {\n const defaultBsPopperConfig = {\n placement: this._getPlacement(),\n modifiers: [{\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n },\n {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n }]\n }\n\n // Disable Popper if we have a static display or Dropdown is in Navbar\n if (this._inNavbar || this._config.display === 'static') {\n Manipulator.setDataAttribute(this._menu, 'popper', 'static') // TODO: v6 remove\n defaultBsPopperConfig.modifiers = [{\n name: 'applyStyles',\n enabled: false\n }]\n }\n\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n }\n }\n\n _selectMenuItem({ key, target }) {\n const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))\n\n if (!items.length) {\n return\n }\n\n // if target isn't included in items (e.g. when expanding the dropdown)\n // allow cycling to get the last item in case key equals ARROW_UP_KEY\n getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Dropdown.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n\n static clearMenus(event) {\n if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {\n return\n }\n\n const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN)\n\n for (const toggle of openToggles) {\n const context = Dropdown.getInstance(toggle)\n if (!context || context._config.autoClose === false) {\n continue\n }\n\n const composedPath = event.composedPath()\n const isMenuTarget = composedPath.includes(context._menu)\n if (\n composedPath.includes(context._element) ||\n (context._config.autoClose === 'inside' && !isMenuTarget) ||\n (context._config.autoClose === 'outside' && isMenuTarget)\n ) {\n continue\n }\n\n // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu\n if (context._menu.contains(event.target) && ((event.type === 'keyup' && event.key === TAB_KEY) || /input|select|option|textarea|form/i.test(event.target.tagName))) {\n continue\n }\n\n const relatedTarget = { relatedTarget: context._element }\n\n if (event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n context._completeHide(relatedTarget)\n }\n }\n\n static dataApiKeydownHandler(event) {\n // If not an UP | DOWN | ESCAPE key => not a dropdown command\n // If input/textarea && if key is other than ESCAPE => not a dropdown command\n\n const isInput = /input|textarea/i.test(event.target.tagName)\n const isEscapeEvent = event.key === ESCAPE_KEY\n const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)\n\n if (!isUpOrDownEvent && !isEscapeEvent) {\n return\n }\n\n if (isInput && !isEscapeEvent) {\n return\n }\n\n event.preventDefault()\n\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ?\n this :\n (SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] ||\n SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0] ||\n SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode))\n\n const instance = Dropdown.getOrCreateInstance(getToggleButton)\n\n if (isUpOrDownEvent) {\n event.stopPropagation()\n instance.show()\n instance._selectMenuItem(event)\n return\n }\n\n if (instance._isShown()) { // else is escape and we check if it is shown\n event.stopPropagation()\n instance.hide()\n getToggleButton.focus()\n }\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)\nEventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)\nEventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n event.preventDefault()\n Dropdown.getOrCreateInstance(this).toggle()\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Dropdown)\n\nexport default Dropdown\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/backdrop.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport Config from './config.js'\nimport { execute, executeAfterTransition, getElement, reflow } from './index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'backdrop'\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\nconst EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`\n\nconst Default = {\n className: 'modal-backdrop',\n clickCallback: null,\n isAnimated: false,\n isVisible: true, // if false, we use the backdrop helper without adding any element to the dom\n rootElement: 'body' // give the choice to place backdrop under different elements\n}\n\nconst DefaultType = {\n className: 'string',\n clickCallback: '(function|null)',\n isAnimated: 'boolean',\n isVisible: 'boolean',\n rootElement: '(element|string)'\n}\n\n/**\n * Class definition\n */\n\nclass Backdrop extends Config {\n constructor(config) {\n super()\n this._config = this._getConfig(config)\n this._isAppended = false\n this._element = null\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n show(callback) {\n if (!this._config.isVisible) {\n execute(callback)\n return\n }\n\n this._append()\n\n const element = this._getElement()\n if (this._config.isAnimated) {\n reflow(element)\n }\n\n element.classList.add(CLASS_NAME_SHOW)\n\n this._emulateAnimation(() => {\n execute(callback)\n })\n }\n\n hide(callback) {\n if (!this._config.isVisible) {\n execute(callback)\n return\n }\n\n this._getElement().classList.remove(CLASS_NAME_SHOW)\n\n this._emulateAnimation(() => {\n this.dispose()\n execute(callback)\n })\n }\n\n dispose() {\n if (!this._isAppended) {\n return\n }\n\n EventHandler.off(this._element, EVENT_MOUSEDOWN)\n\n this._element.remove()\n this._isAppended = false\n }\n\n // Private\n _getElement() {\n if (!this._element) {\n const backdrop = document.createElement('div')\n backdrop.className = this._config.className\n if (this._config.isAnimated) {\n backdrop.classList.add(CLASS_NAME_FADE)\n }\n\n this._element = backdrop\n }\n\n return this._element\n }\n\n _configAfterMerge(config) {\n // use getElement() with the default \"body\" to get a fresh Element on each instantiation\n config.rootElement = getElement(config.rootElement)\n return config\n }\n\n _append() {\n if (this._isAppended) {\n return\n }\n\n const element = this._getElement()\n this._config.rootElement.append(element)\n\n EventHandler.on(element, EVENT_MOUSEDOWN, () => {\n execute(this._config.clickCallback)\n })\n\n this._isAppended = true\n }\n\n _emulateAnimation(callback) {\n executeAfterTransition(callback, this._getElement(), this._config.isAnimated)\n }\n}\n\nexport default Backdrop\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/focustrap.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport Config from './config.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'focustrap'\nconst DATA_KEY = 'bs.focustrap'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst EVENT_FOCUSIN = `focusin${EVENT_KEY}`\nconst EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}`\n\nconst TAB_KEY = 'Tab'\nconst TAB_NAV_FORWARD = 'forward'\nconst TAB_NAV_BACKWARD = 'backward'\n\nconst Default = {\n autofocus: true,\n trapElement: null // The element to trap focus inside of\n}\n\nconst DefaultType = {\n autofocus: 'boolean',\n trapElement: 'element'\n}\n\n/**\n * Class definition\n */\n\nclass FocusTrap extends Config {\n constructor(config) {\n super()\n this._config = this._getConfig(config)\n this._isActive = false\n this._lastTabNavDirection = null\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n activate() {\n if (this._isActive) {\n return\n }\n\n if (this._config.autofocus) {\n this._config.trapElement.focus()\n }\n\n EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop\n EventHandler.on(document, EVENT_FOCUSIN, event => this._handleFocusin(event))\n EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event))\n\n this._isActive = true\n }\n\n deactivate() {\n if (!this._isActive) {\n return\n }\n\n this._isActive = false\n EventHandler.off(document, EVENT_KEY)\n }\n\n // Private\n _handleFocusin(event) {\n const { trapElement } = this._config\n\n if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {\n return\n }\n\n const elements = SelectorEngine.focusableChildren(trapElement)\n\n if (elements.length === 0) {\n trapElement.focus()\n } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {\n elements[elements.length - 1].focus()\n } else {\n elements[0].focus()\n }\n }\n\n _handleKeydown(event) {\n if (event.key !== TAB_KEY) {\n return\n }\n\n this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD\n }\n}\n\nexport default FocusTrap\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/scrollBar.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Manipulator from '../dom/manipulator.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport { isElement } from './index.js'\n\n/**\n * Constants\n */\n\nconst SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'\nconst SELECTOR_STICKY_CONTENT = '.sticky-top'\nconst PROPERTY_PADDING = 'padding-right'\nconst PROPERTY_MARGIN = 'margin-right'\n\n/**\n * Class definition\n */\n\nclass ScrollBarHelper {\n constructor() {\n this._element = document.body\n }\n\n // Public\n getWidth() {\n // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes\n const documentWidth = document.documentElement.clientWidth\n return Math.abs(window.innerWidth - documentWidth)\n }\n\n hide() {\n const width = this.getWidth()\n this._disableOverFlow()\n // give padding to element to balance the hidden scrollbar width\n this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width)\n // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth\n this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width)\n this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width)\n }\n\n reset() {\n this._resetElementAttributes(this._element, 'overflow')\n this._resetElementAttributes(this._element, PROPERTY_PADDING)\n this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING)\n this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN)\n }\n\n isOverflowing() {\n return this.getWidth() > 0\n }\n\n // Private\n _disableOverFlow() {\n this._saveInitialAttribute(this._element, 'overflow')\n this._element.style.overflow = 'hidden'\n }\n\n _setElementAttributes(selector, styleProperty, callback) {\n const scrollbarWidth = this.getWidth()\n const manipulationCallBack = element => {\n if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {\n return\n }\n\n this._saveInitialAttribute(element, styleProperty)\n const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty)\n element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`)\n }\n\n this._applyManipulationCallback(selector, manipulationCallBack)\n }\n\n _saveInitialAttribute(element, styleProperty) {\n const actualValue = element.style.getPropertyValue(styleProperty)\n if (actualValue) {\n Manipulator.setDataAttribute(element, styleProperty, actualValue)\n }\n }\n\n _resetElementAttributes(selector, styleProperty) {\n const manipulationCallBack = element => {\n const value = Manipulator.getDataAttribute(element, styleProperty)\n // We only want to remove the property if the value is `null`; the value can also be zero\n if (value === null) {\n element.style.removeProperty(styleProperty)\n return\n }\n\n Manipulator.removeDataAttribute(element, styleProperty)\n element.style.setProperty(styleProperty, value)\n }\n\n this._applyManipulationCallback(selector, manipulationCallBack)\n }\n\n _applyManipulationCallback(selector, callBack) {\n if (isElement(selector)) {\n callBack(selector)\n return\n }\n\n for (const sel of SelectorEngine.find(selector, this._element)) {\n callBack(sel)\n }\n }\n}\n\nexport default ScrollBarHelper\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport Backdrop from './util/backdrop.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport FocusTrap from './util/focustrap.js'\nimport { defineJQueryPlugin, isRTL, isVisible, reflow } from './util/index.js'\nimport ScrollBarHelper from './util/scrollbar.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'modal'\nconst DATA_KEY = 'bs.modal'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst ESCAPE_KEY = 'Escape'\n\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_RESIZE = `resize${EVENT_KEY}`\nconst EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`\nconst EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}`\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_OPEN = 'modal-open'\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_STATIC = 'modal-static'\n\nconst OPEN_SELECTOR = '.modal.show'\nconst SELECTOR_DIALOG = '.modal-dialog'\nconst SELECTOR_MODAL_BODY = '.modal-body'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"modal\"]'\n\nconst Default = {\n backdrop: true,\n focus: true,\n keyboard: true\n}\n\nconst DefaultType = {\n backdrop: '(boolean|string)',\n focus: 'boolean',\n keyboard: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Modal extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element)\n this._backdrop = this._initializeBackDrop()\n this._focustrap = this._initializeFocusTrap()\n this._isShown = false\n this._isTransitioning = false\n this._scrollBar = new ScrollBarHelper()\n\n this._addEventListeners()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return\n }\n\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {\n relatedTarget\n })\n\n if (showEvent.defaultPrevented) {\n return\n }\n\n this._isShown = true\n this._isTransitioning = true\n\n this._scrollBar.hide()\n\n document.body.classList.add(CLASS_NAME_OPEN)\n\n this._adjustDialog()\n\n this._backdrop.show(() => this._showElement(relatedTarget))\n }\n\n hide() {\n if (!this._isShown || this._isTransitioning) {\n return\n }\n\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE)\n\n if (hideEvent.defaultPrevented) {\n return\n }\n\n this._isShown = false\n this._isTransitioning = true\n this._focustrap.deactivate()\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n this._queueCallback(() => this._hideModal(), this._element, this._isAnimated())\n }\n\n dispose() {\n EventHandler.off(window, EVENT_KEY)\n EventHandler.off(this._dialog, EVENT_KEY)\n\n this._backdrop.dispose()\n this._focustrap.deactivate()\n\n super.dispose()\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n _initializeBackDrop() {\n return new Backdrop({\n isVisible: Boolean(this._config.backdrop), // 'static' option will be translated to true, and booleans will keep their value,\n isAnimated: this._isAnimated()\n })\n }\n\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n })\n }\n\n _showElement(relatedTarget) {\n // try to append dynamic modal\n if (!document.body.contains(this._element)) {\n document.body.append(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.setAttribute('aria-modal', true)\n this._element.setAttribute('role', 'dialog')\n this._element.scrollTop = 0\n\n const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog)\n if (modalBody) {\n modalBody.scrollTop = 0\n }\n\n reflow(this._element)\n\n this._element.classList.add(CLASS_NAME_SHOW)\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._focustrap.activate()\n }\n\n this._isTransitioning = false\n EventHandler.trigger(this._element, EVENT_SHOWN, {\n relatedTarget\n })\n }\n\n this._queueCallback(transitionComplete, this._dialog, this._isAnimated())\n }\n\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n if (event.key !== ESCAPE_KEY) {\n return\n }\n\n if (this._config.keyboard) {\n this.hide()\n return\n }\n\n this._triggerBackdropTransition()\n })\n\n EventHandler.on(window, EVENT_RESIZE, () => {\n if (this._isShown && !this._isTransitioning) {\n this._adjustDialog()\n }\n })\n\n EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => {\n // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks\n EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => {\n if (this._element !== event.target || this._element !== event2.target) {\n return\n }\n\n if (this._config.backdrop === 'static') {\n this._triggerBackdropTransition()\n return\n }\n\n if (this._config.backdrop) {\n this.hide()\n }\n })\n })\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._element.removeAttribute('aria-modal')\n this._element.removeAttribute('role')\n this._isTransitioning = false\n\n this._backdrop.hide(() => {\n document.body.classList.remove(CLASS_NAME_OPEN)\n this._resetAdjustments()\n this._scrollBar.reset()\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n })\n }\n\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_FADE)\n }\n\n _triggerBackdropTransition() {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)\n if (hideEvent.defaultPrevented) {\n return\n }\n\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight\n const initialOverflowY = this._element.style.overflowY\n // return if the following background transition hasn't yet completed\n if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {\n return\n }\n\n if (!isModalOverflowing) {\n this._element.style.overflowY = 'hidden'\n }\n\n this._element.classList.add(CLASS_NAME_STATIC)\n this._queueCallback(() => {\n this._element.classList.remove(CLASS_NAME_STATIC)\n this._queueCallback(() => {\n this._element.style.overflowY = initialOverflowY\n }, this._dialog)\n }, this._dialog)\n\n this._element.focus()\n }\n\n /**\n * The following methods are used to handle overflowing modals\n */\n\n _adjustDialog() {\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight\n const scrollbarWidth = this._scrollBar.getWidth()\n const isBodyOverflowing = scrollbarWidth > 0\n\n if (isBodyOverflowing && !isModalOverflowing) {\n const property = isRTL() ? 'paddingLeft' : 'paddingRight'\n this._element.style[property] = `${scrollbarWidth}px`\n }\n\n if (!isBodyOverflowing && isModalOverflowing) {\n const property = isRTL() ? 'paddingRight' : 'paddingLeft'\n this._element.style[property] = `${scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n // Static\n static jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n const data = Modal.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](relatedTarget)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this)\n\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n EventHandler.one(target, EVENT_SHOW, showEvent => {\n if (showEvent.defaultPrevented) {\n // only register focus restorer if modal will actually get shown\n return\n }\n\n EventHandler.one(target, EVENT_HIDDEN, () => {\n if (isVisible(this)) {\n this.focus()\n }\n })\n })\n\n // avoid conflict when clicking modal toggler while another one is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR)\n if (alreadyOpen) {\n Modal.getInstance(alreadyOpen).hide()\n }\n\n const data = Modal.getOrCreateInstance(target)\n\n data.toggle(this)\n})\n\nenableDismissTrigger(Modal)\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Modal)\n\nexport default Modal\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap offcanvas.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport Backdrop from './util/backdrop.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport FocusTrap from './util/focustrap.js'\nimport {\n defineJQueryPlugin,\n isDisabled,\n isVisible\n} from './util/index.js'\nimport ScrollBarHelper from './util/scrollbar.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'offcanvas'\nconst DATA_KEY = 'bs.offcanvas'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\nconst ESCAPE_KEY = 'Escape'\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_SHOWING = 'showing'\nconst CLASS_NAME_HIDING = 'hiding'\nconst CLASS_NAME_BACKDROP = 'offcanvas-backdrop'\nconst OPEN_SELECTOR = '.offcanvas.show'\n\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_RESIZE = `resize${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`\n\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"offcanvas\"]'\n\nconst Default = {\n backdrop: true,\n keyboard: true,\n scroll: false\n}\n\nconst DefaultType = {\n backdrop: '(boolean|string)',\n keyboard: 'boolean',\n scroll: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Offcanvas extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._isShown = false\n this._backdrop = this._initializeBackDrop()\n this._focustrap = this._initializeFocusTrap()\n this._addEventListeners()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown) {\n return\n }\n\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { relatedTarget })\n\n if (showEvent.defaultPrevented) {\n return\n }\n\n this._isShown = true\n this._backdrop.show()\n\n if (!this._config.scroll) {\n new ScrollBarHelper().hide()\n }\n\n this._element.setAttribute('aria-modal', true)\n this._element.setAttribute('role', 'dialog')\n this._element.classList.add(CLASS_NAME_SHOWING)\n\n const completeCallBack = () => {\n if (!this._config.scroll || this._config.backdrop) {\n this._focustrap.activate()\n }\n\n this._element.classList.add(CLASS_NAME_SHOW)\n this._element.classList.remove(CLASS_NAME_SHOWING)\n EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget })\n }\n\n this._queueCallback(completeCallBack, this._element, true)\n }\n\n hide() {\n if (!this._isShown) {\n return\n }\n\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE)\n\n if (hideEvent.defaultPrevented) {\n return\n }\n\n this._focustrap.deactivate()\n this._element.blur()\n this._isShown = false\n this._element.classList.add(CLASS_NAME_HIDING)\n this._backdrop.hide()\n\n const completeCallback = () => {\n this._element.classList.remove(CLASS_NAME_SHOW, CLASS_NAME_HIDING)\n this._element.removeAttribute('aria-modal')\n this._element.removeAttribute('role')\n\n if (!this._config.scroll) {\n new ScrollBarHelper().reset()\n }\n\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n }\n\n this._queueCallback(completeCallback, this._element, true)\n }\n\n dispose() {\n this._backdrop.dispose()\n this._focustrap.deactivate()\n super.dispose()\n }\n\n // Private\n _initializeBackDrop() {\n const clickCallback = () => {\n if (this._config.backdrop === 'static') {\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)\n return\n }\n\n this.hide()\n }\n\n // 'static' option will be translated to true, and booleans will keep their value\n const isVisible = Boolean(this._config.backdrop)\n\n return new Backdrop({\n className: CLASS_NAME_BACKDROP,\n isVisible,\n isAnimated: true,\n rootElement: this._element.parentNode,\n clickCallback: isVisible ? clickCallback : null\n })\n }\n\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n })\n }\n\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n if (event.key !== ESCAPE_KEY) {\n return\n }\n\n if (this._config.keyboard) {\n this.hide()\n return\n }\n\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)\n })\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Offcanvas.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](this)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this)\n\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n if (isDisabled(this)) {\n return\n }\n\n EventHandler.one(target, EVENT_HIDDEN, () => {\n // focus on trigger when it is closed\n if (isVisible(this)) {\n this.focus()\n }\n })\n\n // avoid conflict when clicking a toggler of an offcanvas, while another is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR)\n if (alreadyOpen && alreadyOpen !== target) {\n Offcanvas.getInstance(alreadyOpen).hide()\n }\n\n const data = Offcanvas.getOrCreateInstance(target)\n data.toggle(this)\n})\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {\n Offcanvas.getOrCreateInstance(selector).show()\n }\n})\n\nEventHandler.on(window, EVENT_RESIZE, () => {\n for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {\n if (getComputedStyle(element).position !== 'fixed') {\n Offcanvas.getOrCreateInstance(element).hide()\n }\n }\n})\n\nenableDismissTrigger(Offcanvas)\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Offcanvas)\n\nexport default Offcanvas\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/sanitizer.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n// js-docs-start allow-list\nconst ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i\n\nexport const DefaultAllowlist = {\n // Global attributes allowed on any supplied element below.\n '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n a: ['target', 'href', 'title', 'rel'],\n area: [],\n b: [],\n br: [],\n col: [],\n code: [],\n div: [],\n em: [],\n hr: [],\n h1: [],\n h2: [],\n h3: [],\n h4: [],\n h5: [],\n h6: [],\n i: [],\n img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n li: [],\n ol: [],\n p: [],\n pre: [],\n s: [],\n small: [],\n span: [],\n sub: [],\n sup: [],\n strong: [],\n u: [],\n ul: []\n}\n// js-docs-end allow-list\n\nconst uriAttributes = new Set([\n 'background',\n 'cite',\n 'href',\n 'itemtype',\n 'longdesc',\n 'poster',\n 'src',\n 'xlink:href'\n])\n\n/**\n * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation\n * contexts.\n *\n * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38\n */\n// eslint-disable-next-line unicorn/better-regex\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i\n\nconst allowedAttribute = (attribute, allowedAttributeList) => {\n const attributeName = attribute.nodeName.toLowerCase()\n\n if (allowedAttributeList.includes(attributeName)) {\n if (uriAttributes.has(attributeName)) {\n return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue))\n }\n\n return true\n }\n\n // Check if a regular expression validates the attribute.\n return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)\n .some(regex => regex.test(attributeName))\n}\n\nexport function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {\n if (!unsafeHtml.length) {\n return unsafeHtml\n }\n\n if (sanitizeFunction && typeof sanitizeFunction === 'function') {\n return sanitizeFunction(unsafeHtml)\n }\n\n const domParser = new window.DOMParser()\n const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')\n const elements = [].concat(...createdDocument.body.querySelectorAll('*'))\n\n for (const element of elements) {\n const elementName = element.nodeName.toLowerCase()\n\n if (!Object.keys(allowList).includes(elementName)) {\n element.remove()\n continue\n }\n\n const attributeList = [].concat(...element.attributes)\n const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || [])\n\n for (const attribute of attributeList) {\n if (!allowedAttribute(attribute, allowedAttributes)) {\n element.removeAttribute(attribute.nodeName)\n }\n }\n }\n\n return createdDocument.body.innerHTML\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/template-factory.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport SelectorEngine from '../dom/selector-engine.js'\nimport Config from './config.js'\nimport { DefaultAllowlist, sanitizeHtml } from './sanitizer.js'\nimport { execute, getElement, isElement } from './index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'TemplateFactory'\n\nconst Default = {\n allowList: DefaultAllowlist,\n content: {}, // { selector : text , selector2 : text2 , }\n extraClass: '',\n html: false,\n sanitize: true,\n sanitizeFn: null,\n template: '
'\n}\n\nconst DefaultType = {\n allowList: 'object',\n content: 'object',\n extraClass: '(string|function)',\n html: 'boolean',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n template: 'string'\n}\n\nconst DefaultContentType = {\n entry: '(string|element|function|null)',\n selector: '(string|element)'\n}\n\n/**\n * Class definition\n */\n\nclass TemplateFactory extends Config {\n constructor(config) {\n super()\n this._config = this._getConfig(config)\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n getContent() {\n return Object.values(this._config.content)\n .map(config => this._resolvePossibleFunction(config))\n .filter(Boolean)\n }\n\n hasContent() {\n return this.getContent().length > 0\n }\n\n changeContent(content) {\n this._checkContent(content)\n this._config.content = { ...this._config.content, ...content }\n return this\n }\n\n toHtml() {\n const templateWrapper = document.createElement('div')\n templateWrapper.innerHTML = this._maybeSanitize(this._config.template)\n\n for (const [selector, text] of Object.entries(this._config.content)) {\n this._setContent(templateWrapper, text, selector)\n }\n\n const template = templateWrapper.children[0]\n const extraClass = this._resolvePossibleFunction(this._config.extraClass)\n\n if (extraClass) {\n template.classList.add(...extraClass.split(' '))\n }\n\n return template\n }\n\n // Private\n _typeCheckConfig(config) {\n super._typeCheckConfig(config)\n this._checkContent(config.content)\n }\n\n _checkContent(arg) {\n for (const [selector, content] of Object.entries(arg)) {\n super._typeCheckConfig({ selector, entry: content }, DefaultContentType)\n }\n }\n\n _setContent(template, content, selector) {\n const templateElement = SelectorEngine.findOne(selector, template)\n\n if (!templateElement) {\n return\n }\n\n content = this._resolvePossibleFunction(content)\n\n if (!content) {\n templateElement.remove()\n return\n }\n\n if (isElement(content)) {\n this._putElementInTemplate(getElement(content), templateElement)\n return\n }\n\n if (this._config.html) {\n templateElement.innerHTML = this._maybeSanitize(content)\n return\n }\n\n templateElement.textContent = content\n }\n\n _maybeSanitize(arg) {\n return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg\n }\n\n _resolvePossibleFunction(arg) {\n return execute(arg, [this])\n }\n\n _putElementInTemplate(element, templateElement) {\n if (this._config.html) {\n templateElement.innerHTML = ''\n templateElement.append(element)\n return\n }\n\n templateElement.textContent = element.textContent\n }\n}\n\nexport default TemplateFactory\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport * as Popper from '@popperjs/core'\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport Manipulator from './dom/manipulator.js'\nimport { defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index.js'\nimport { DefaultAllowlist } from './util/sanitizer.js'\nimport TemplateFactory from './util/template-factory.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'tooltip'\nconst DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn'])\n\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_MODAL = 'modal'\nconst CLASS_NAME_SHOW = 'show'\n\nconst SELECTOR_TOOLTIP_INNER = '.tooltip-inner'\nconst SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`\n\nconst EVENT_MODAL_HIDE = 'hide.bs.modal'\n\nconst TRIGGER_HOVER = 'hover'\nconst TRIGGER_FOCUS = 'focus'\nconst TRIGGER_CLICK = 'click'\nconst TRIGGER_MANUAL = 'manual'\n\nconst EVENT_HIDE = 'hide'\nconst EVENT_HIDDEN = 'hidden'\nconst EVENT_SHOW = 'show'\nconst EVENT_SHOWN = 'shown'\nconst EVENT_INSERTED = 'inserted'\nconst EVENT_CLICK = 'click'\nconst EVENT_FOCUSIN = 'focusin'\nconst EVENT_FOCUSOUT = 'focusout'\nconst EVENT_MOUSEENTER = 'mouseenter'\nconst EVENT_MOUSELEAVE = 'mouseleave'\n\nconst AttachmentMap = {\n AUTO: 'auto',\n TOP: 'top',\n RIGHT: isRTL() ? 'left' : 'right',\n BOTTOM: 'bottom',\n LEFT: isRTL() ? 'right' : 'left'\n}\n\nconst Default = {\n allowList: DefaultAllowlist,\n animation: true,\n boundary: 'clippingParents',\n container: false,\n customClass: '',\n delay: 0,\n fallbackPlacements: ['top', 'right', 'bottom', 'left'],\n html: false,\n offset: [0, 6],\n placement: 'top',\n popperConfig: null,\n sanitize: true,\n sanitizeFn: null,\n selector: false,\n template: '
' +\n '
' +\n '
' +\n '
',\n title: '',\n trigger: 'hover focus'\n}\n\nconst DefaultType = {\n allowList: 'object',\n animation: 'boolean',\n boundary: '(string|element)',\n container: '(string|element|boolean)',\n customClass: '(string|function)',\n delay: '(number|object)',\n fallbackPlacements: 'array',\n html: 'boolean',\n offset: '(array|string|function)',\n placement: '(string|function)',\n popperConfig: '(null|object|function)',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n selector: '(string|boolean)',\n template: 'string',\n title: '(string|element|function)',\n trigger: 'string'\n}\n\n/**\n * Class definition\n */\n\nclass Tooltip extends BaseComponent {\n constructor(element, config) {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s tooltips require Popper (https://popper.js.org)')\n }\n\n super(element, config)\n\n // Private\n this._isEnabled = true\n this._timeout = 0\n this._isHovered = null\n this._activeTrigger = {}\n this._popper = null\n this._templateFactory = null\n this._newContent = null\n\n // Protected\n this.tip = null\n\n this._setListeners()\n\n if (!this._config.selector) {\n this._fixTitle()\n }\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle() {\n if (!this._isEnabled) {\n return\n }\n\n this._activeTrigger.click = !this._activeTrigger.click\n if (this._isShown()) {\n this._leave()\n return\n }\n\n this._enter()\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler)\n\n if (this._element.getAttribute('data-bs-original-title')) {\n this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'))\n }\n\n this._disposePopper()\n super.dispose()\n }\n\n show() {\n if (this._element.style.display === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n if (!(this._isWithContent() && this._isEnabled)) {\n return\n }\n\n const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW))\n const shadowRoot = findShadowRoot(this._element)\n const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element)\n\n if (showEvent.defaultPrevented || !isInTheDom) {\n return\n }\n\n // TODO: v6 remove this or make it optional\n this._disposePopper()\n\n const tip = this._getTipElement()\n\n this._element.setAttribute('aria-describedby', tip.getAttribute('id'))\n\n const { container } = this._config\n\n if (!this._element.ownerDocument.documentElement.contains(this.tip)) {\n container.append(tip)\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED))\n }\n\n this._popper = this._createPopper(tip)\n\n tip.classList.add(CLASS_NAME_SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop)\n }\n }\n\n const complete = () => {\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN))\n\n if (this._isHovered === false) {\n this._leave()\n }\n\n this._isHovered = false\n }\n\n this._queueCallback(complete, this.tip, this._isAnimated())\n }\n\n hide() {\n if (!this._isShown()) {\n return\n }\n\n const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE))\n if (hideEvent.defaultPrevented) {\n return\n }\n\n const tip = this._getTipElement()\n tip.classList.remove(CLASS_NAME_SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop)\n }\n }\n\n this._activeTrigger[TRIGGER_CLICK] = false\n this._activeTrigger[TRIGGER_FOCUS] = false\n this._activeTrigger[TRIGGER_HOVER] = false\n this._isHovered = null // it is a trick to support manual triggering\n\n const complete = () => {\n if (this._isWithActiveTrigger()) {\n return\n }\n\n if (!this._isHovered) {\n this._disposePopper()\n }\n\n this._element.removeAttribute('aria-describedby')\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN))\n }\n\n this._queueCallback(complete, this.tip, this._isAnimated())\n }\n\n update() {\n if (this._popper) {\n this._popper.update()\n }\n }\n\n // Protected\n _isWithContent() {\n return Boolean(this._getTitle())\n }\n\n _getTipElement() {\n if (!this.tip) {\n this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())\n }\n\n return this.tip\n }\n\n _createTipElement(content) {\n const tip = this._getTemplateFactory(content).toHtml()\n\n // TODO: remove this check in v6\n if (!tip) {\n return null\n }\n\n tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)\n // TODO: v6 the following can be achieved with CSS only\n tip.classList.add(`bs-${this.constructor.NAME}-auto`)\n\n const tipId = getUID(this.constructor.NAME).toString()\n\n tip.setAttribute('id', tipId)\n\n if (this._isAnimated()) {\n tip.classList.add(CLASS_NAME_FADE)\n }\n\n return tip\n }\n\n setContent(content) {\n this._newContent = content\n if (this._isShown()) {\n this._disposePopper()\n this.show()\n }\n }\n\n _getTemplateFactory(content) {\n if (this._templateFactory) {\n this._templateFactory.changeContent(content)\n } else {\n this._templateFactory = new TemplateFactory({\n ...this._config,\n // the `content` var has to be after `this._config`\n // to override config.content in case of popover\n content,\n extraClass: this._resolvePossibleFunction(this._config.customClass)\n })\n }\n\n return this._templateFactory\n }\n\n _getContentForTemplate() {\n return {\n [SELECTOR_TOOLTIP_INNER]: this._getTitle()\n }\n }\n\n _getTitle() {\n return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title')\n }\n\n // Private\n _initializeOnDelegatedTarget(event) {\n return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig())\n }\n\n _isAnimated() {\n return this._config.animation || (this.tip && this.tip.classList.contains(CLASS_NAME_FADE))\n }\n\n _isShown() {\n return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW)\n }\n\n _createPopper(tip) {\n const placement = execute(this._config.placement, [this, tip, this._element])\n const attachment = AttachmentMap[placement.toUpperCase()]\n return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))\n }\n\n _getOffset() {\n const { offset } = this._config\n\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10))\n }\n\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element)\n }\n\n return offset\n }\n\n _resolvePossibleFunction(arg) {\n return execute(arg, [this._element])\n }\n\n _getPopperConfig(attachment) {\n const defaultBsPopperConfig = {\n placement: attachment,\n modifiers: [\n {\n name: 'flip',\n options: {\n fallbackPlacements: this._config.fallbackPlacements\n }\n },\n {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n },\n {\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n },\n {\n name: 'arrow',\n options: {\n element: `.${this.constructor.NAME}-arrow`\n }\n },\n {\n name: 'preSetPlacement',\n enabled: true,\n phase: 'beforeMain',\n fn: data => {\n // Pre-set Popper's placement attribute in order to read the arrow sizes properly.\n // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement\n this._getTipElement().setAttribute('data-popper-placement', data.state.placement)\n }\n }\n ]\n }\n\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n }\n }\n\n _setListeners() {\n const triggers = this._config.trigger.split(' ')\n\n for (const trigger of triggers) {\n if (trigger === 'click') {\n EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event)\n context.toggle()\n })\n } else if (trigger !== TRIGGER_MANUAL) {\n const eventIn = trigger === TRIGGER_HOVER ?\n this.constructor.eventName(EVENT_MOUSEENTER) :\n this.constructor.eventName(EVENT_FOCUSIN)\n const eventOut = trigger === TRIGGER_HOVER ?\n this.constructor.eventName(EVENT_MOUSELEAVE) :\n this.constructor.eventName(EVENT_FOCUSOUT)\n\n EventHandler.on(this._element, eventIn, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event)\n context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true\n context._enter()\n })\n EventHandler.on(this._element, eventOut, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event)\n context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] =\n context._element.contains(event.relatedTarget)\n\n context._leave()\n })\n }\n }\n\n this._hideModalHandler = () => {\n if (this._element) {\n this.hide()\n }\n }\n\n EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler)\n }\n\n _fixTitle() {\n const title = this._element.getAttribute('title')\n\n if (!title) {\n return\n }\n\n if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {\n this._element.setAttribute('aria-label', title)\n }\n\n this._element.setAttribute('data-bs-original-title', title) // DO NOT USE IT. Is only for backwards compatibility\n this._element.removeAttribute('title')\n }\n\n _enter() {\n if (this._isShown() || this._isHovered) {\n this._isHovered = true\n return\n }\n\n this._isHovered = true\n\n this._setTimeout(() => {\n if (this._isHovered) {\n this.show()\n }\n }, this._config.delay.show)\n }\n\n _leave() {\n if (this._isWithActiveTrigger()) {\n return\n }\n\n this._isHovered = false\n\n this._setTimeout(() => {\n if (!this._isHovered) {\n this.hide()\n }\n }, this._config.delay.hide)\n }\n\n _setTimeout(handler, timeout) {\n clearTimeout(this._timeout)\n this._timeout = setTimeout(handler, timeout)\n }\n\n _isWithActiveTrigger() {\n return Object.values(this._activeTrigger).includes(true)\n }\n\n _getConfig(config) {\n const dataAttributes = Manipulator.getDataAttributes(this._element)\n\n for (const dataAttribute of Object.keys(dataAttributes)) {\n if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {\n delete dataAttributes[dataAttribute]\n }\n }\n\n config = {\n ...dataAttributes,\n ...(typeof config === 'object' && config ? config : {})\n }\n config = this._mergeConfigObj(config)\n config = this._configAfterMerge(config)\n this._typeCheckConfig(config)\n return config\n }\n\n _configAfterMerge(config) {\n config.container = config.container === false ? document.body : getElement(config.container)\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n for (const [key, value] of Object.entries(this._config)) {\n if (this.constructor.Default[key] !== value) {\n config[key] = value\n }\n }\n\n config.selector = false\n config.trigger = 'manual'\n\n // In the future can be replaced with:\n // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])\n // `Object.fromEntries(keysWithDifferentValues)`\n return config\n }\n\n _disposePopper() {\n if (this._popper) {\n this._popper.destroy()\n this._popper = null\n }\n\n if (this.tip) {\n this.tip.remove()\n this.tip = null\n }\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Tooltip.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Tooltip)\n\nexport default Tooltip\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Tooltip from './tooltip.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'popover'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Default = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '
' +\n '
' +\n '

' +\n '
' +\n '
',\n trigger: 'click'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n}\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent()\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n }\n }\n\n _getContent() {\n return this._resolvePossibleFunction(this._config.content)\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Popover.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Popover)\n\nexport default Popover\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport { defineJQueryPlugin, getElement, isDisabled, isVisible } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'scrollspy'\nconst DATA_KEY = 'bs.scrollspy'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst EVENT_ACTIVATE = `activate${EVENT_KEY}`\nconst EVENT_CLICK = `click${EVENT_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'\nconst CLASS_NAME_ACTIVE = 'active'\n\nconst SELECTOR_DATA_SPY = '[data-bs-spy=\"scroll\"]'\nconst SELECTOR_TARGET_LINKS = '[href]'\nconst SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'\nconst SELECTOR_NAV_LINKS = '.nav-link'\nconst SELECTOR_NAV_ITEMS = '.nav-item'\nconst SELECTOR_LIST_ITEMS = '.list-group-item'\nconst SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`\nconst SELECTOR_DROPDOWN = '.dropdown'\nconst SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'\n\nconst Default = {\n offset: null, // TODO: v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: '0px 0px -25%',\n smoothScroll: false,\n target: null,\n threshold: [0.1, 0.5, 1]\n}\n\nconst DefaultType = {\n offset: '(number|null)', // TODO v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: 'string',\n smoothScroll: 'boolean',\n target: 'element',\n threshold: 'array'\n}\n\n/**\n * Class definition\n */\n\nclass ScrollSpy extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n // this._element is the observablesContainer and config.target the menu links wrapper\n this._targetLinks = new Map()\n this._observableSections = new Map()\n this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element\n this._activeTarget = null\n this._observer = null\n this._previousScrollData = {\n visibleEntryTop: 0,\n parentScrollTop: 0\n }\n this.refresh() // initialize\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n refresh() {\n this._initializeTargetsAndObservables()\n this._maybeEnableSmoothScroll()\n\n if (this._observer) {\n this._observer.disconnect()\n } else {\n this._observer = this._getNewObserver()\n }\n\n for (const section of this._observableSections.values()) {\n this._observer.observe(section)\n }\n }\n\n dispose() {\n this._observer.disconnect()\n super.dispose()\n }\n\n // Private\n _configAfterMerge(config) {\n // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case\n config.target = getElement(config.target) || document.body\n\n // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only\n config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin\n\n if (typeof config.threshold === 'string') {\n config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value))\n }\n\n return config\n }\n\n _maybeEnableSmoothScroll() {\n if (!this._config.smoothScroll) {\n return\n }\n\n // unregister any previous listeners\n EventHandler.off(this._config.target, EVENT_CLICK)\n\n EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {\n const observableSection = this._observableSections.get(event.target.hash)\n if (observableSection) {\n event.preventDefault()\n const root = this._rootElement || window\n const height = observableSection.offsetTop - this._element.offsetTop\n if (root.scrollTo) {\n root.scrollTo({ top: height, behavior: 'smooth' })\n return\n }\n\n // Chrome 60 doesn't support `scrollTo`\n root.scrollTop = height\n }\n })\n }\n\n _getNewObserver() {\n const options = {\n root: this._rootElement,\n threshold: this._config.threshold,\n rootMargin: this._config.rootMargin\n }\n\n return new IntersectionObserver(entries => this._observerCallback(entries), options)\n }\n\n // The logic of selection\n _observerCallback(entries) {\n const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`)\n const activate = entry => {\n this._previousScrollData.visibleEntryTop = entry.target.offsetTop\n this._process(targetElement(entry))\n }\n\n const parentScrollTop = (this._rootElement || document.documentElement).scrollTop\n const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop\n this._previousScrollData.parentScrollTop = parentScrollTop\n\n for (const entry of entries) {\n if (!entry.isIntersecting) {\n this._activeTarget = null\n this._clearActiveClass(targetElement(entry))\n\n continue\n }\n\n const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop\n // if we are scrolling down, pick the bigger offsetTop\n if (userScrollsDown && entryIsLowerThanPrevious) {\n activate(entry)\n // if parent isn't scrolled, let's keep the first visible item, breaking the iteration\n if (!parentScrollTop) {\n return\n }\n\n continue\n }\n\n // if we are scrolling up, pick the smallest offsetTop\n if (!userScrollsDown && !entryIsLowerThanPrevious) {\n activate(entry)\n }\n }\n }\n\n _initializeTargetsAndObservables() {\n this._targetLinks = new Map()\n this._observableSections = new Map()\n\n const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target)\n\n for (const anchor of targetLinks) {\n // ensure that the anchor has an id and is not disabled\n if (!anchor.hash || isDisabled(anchor)) {\n continue\n }\n\n const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element)\n\n // ensure that the observableSection exists & is visible\n if (isVisible(observableSection)) {\n this._targetLinks.set(decodeURI(anchor.hash), anchor)\n this._observableSections.set(anchor.hash, observableSection)\n }\n }\n }\n\n _process(target) {\n if (this._activeTarget === target) {\n return\n }\n\n this._clearActiveClass(this._config.target)\n this._activeTarget = target\n target.classList.add(CLASS_NAME_ACTIVE)\n this._activateParents(target)\n\n EventHandler.trigger(this._element, EVENT_ACTIVATE, { relatedTarget: target })\n }\n\n _activateParents(target) {\n // Activate dropdown parents\n if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {\n SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, target.closest(SELECTOR_DROPDOWN))\n .classList.add(CLASS_NAME_ACTIVE)\n return\n }\n\n for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {\n // Set triggered links parents as active\n // With both
    and
')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(e,t){var n=a('
');n.attr("href","#"+e),n.text(t);var r=a("
  • ");return r.append(n),r},generateNavItem:function(e){var t=this.generateAnchor(e),n=a(e),r=n.data("toc-text")||n.text();return this.generateNavEl(t,r)},getTopLevel:function(e){for(var t=1;t<=6;t++){if(1 + + + + + + + + + + + + diff --git a/deps/font-awesome-6.5.2/css/all.css b/deps/font-awesome-6.5.2/css/all.css new file mode 100644 index 0000000..151dd57 --- /dev/null +++ b/deps/font-awesome-6.5.2/css/all.css @@ -0,0 +1,8028 @@ +/*! + * Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +.fa { + font-family: var(--fa-style-family, "Font Awesome 6 Free"); + font-weight: var(--fa-style, 900); } + +.fa, +.fa-classic, +.fa-sharp, +.fas, +.fa-solid, +.far, +.fa-regular, +.fab, +.fa-brands { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: var(--fa-display, inline-block); + font-style: normal; + font-variant: normal; + line-height: 1; + text-rendering: auto; } + +.fas, +.fa-classic, +.fa-solid, +.far, +.fa-regular { + font-family: 'Font Awesome 6 Free'; } + +.fab, +.fa-brands { + font-family: 'Font Awesome 6 Brands'; } + +.fa-1x { + font-size: 1em; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-6x { + font-size: 6em; } + +.fa-7x { + font-size: 7em; } + +.fa-8x { + font-size: 8em; } + +.fa-9x { + font-size: 9em; } + +.fa-10x { + font-size: 10em; } + +.fa-2xs { + font-size: 0.625em; + line-height: 0.1em; + vertical-align: 0.225em; } + +.fa-xs { + font-size: 0.75em; + line-height: 0.08333em; + vertical-align: 0.125em; } + +.fa-sm { + font-size: 0.875em; + line-height: 0.07143em; + vertical-align: 0.05357em; } + +.fa-lg { + font-size: 1.25em; + line-height: 0.05em; + vertical-align: -0.075em; } + +.fa-xl { + font-size: 1.5em; + line-height: 0.04167em; + vertical-align: -0.125em; } + +.fa-2xl { + font-size: 2em; + line-height: 0.03125em; + vertical-align: -0.1875em; } + +.fa-fw { + text-align: center; + width: 1.25em; } + +.fa-ul { + list-style-type: none; + margin-left: var(--fa-li-margin, 2.5em); + padding-left: 0; } + .fa-ul > li { + position: relative; } + +.fa-li { + left: calc(var(--fa-li-width, 2em) * -1); + position: absolute; + text-align: center; + width: var(--fa-li-width, 2em); + line-height: inherit; } + +.fa-border { + border-color: var(--fa-border-color, #eee); + border-radius: var(--fa-border-radius, 0.1em); + border-style: var(--fa-border-style, solid); + border-width: var(--fa-border-width, 0.08em); + padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); } + +.fa-pull-left { + float: left; + margin-right: var(--fa-pull-margin, 0.3em); } + +.fa-pull-right { + float: right; + margin-left: var(--fa-pull-margin, 0.3em); } + +.fa-beat { + -webkit-animation-name: fa-beat; + animation-name: fa-beat; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); + animation-timing-function: var(--fa-animation-timing, ease-in-out); } + +.fa-bounce { + -webkit-animation-name: fa-bounce; + animation-name: fa-bounce; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); } + +.fa-fade { + -webkit-animation-name: fa-fade; + animation-name: fa-fade; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } + +.fa-beat-fade { + -webkit-animation-name: fa-beat-fade; + animation-name: fa-beat-fade; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } + +.fa-flip { + -webkit-animation-name: fa-flip; + animation-name: fa-flip; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); + animation-timing-function: var(--fa-animation-timing, ease-in-out); } + +.fa-shake { + -webkit-animation-name: fa-shake; + animation-name: fa-shake; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, linear); + animation-timing-function: var(--fa-animation-timing, linear); } + +.fa-spin { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 2s); + animation-duration: var(--fa-animation-duration, 2s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, linear); + animation-timing-function: var(--fa-animation-timing, linear); } + +.fa-spin-reverse { + --fa-animation-direction: reverse; } + +.fa-pulse, +.fa-spin-pulse { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, steps(8)); + animation-timing-function: var(--fa-animation-timing, steps(8)); } + +@media (prefers-reduced-motion: reduce) { + .fa-beat, + .fa-bounce, + .fa-fade, + .fa-beat-fade, + .fa-flip, + .fa-pulse, + .fa-shake, + .fa-spin, + .fa-spin-pulse { + -webkit-animation-delay: -1ms; + animation-delay: -1ms; + -webkit-animation-duration: 1ms; + animation-duration: 1ms; + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + -webkit-transition-delay: 0s; + transition-delay: 0s; + -webkit-transition-duration: 0s; + transition-duration: 0s; } } + +@-webkit-keyframes fa-beat { + 0%, 90% { + -webkit-transform: scale(1); + transform: scale(1); } + 45% { + -webkit-transform: scale(var(--fa-beat-scale, 1.25)); + transform: scale(var(--fa-beat-scale, 1.25)); } } + +@keyframes fa-beat { + 0%, 90% { + -webkit-transform: scale(1); + transform: scale(1); } + 45% { + -webkit-transform: scale(var(--fa-beat-scale, 1.25)); + transform: scale(var(--fa-beat-scale, 1.25)); } } + +@-webkit-keyframes fa-bounce { + 0% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); + transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { + -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); + transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } + 64% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 100% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } } + +@keyframes fa-bounce { + 0% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); + transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { + -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); + transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } + 64% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 100% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } } + +@-webkit-keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity, 0.4); } } + +@keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity, 0.4); } } + +@-webkit-keyframes fa-beat-fade { + 0%, 100% { + opacity: var(--fa-beat-fade-opacity, 0.4); + -webkit-transform: scale(1); + transform: scale(1); } + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); + transform: scale(var(--fa-beat-fade-scale, 1.125)); } } + +@keyframes fa-beat-fade { + 0%, 100% { + opacity: var(--fa-beat-fade-opacity, 0.4); + -webkit-transform: scale(1); + transform: scale(1); } + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); + transform: scale(var(--fa-beat-fade-scale, 1.125)); } } + +@-webkit-keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); + transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } + +@keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); + transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } + +@-webkit-keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg); } + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); } + 8%, 24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg); } + 12%, 28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg); } + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg); } + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg); } + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg); } + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg); } + 40%, 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } } + +@keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg); } + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); } + 8%, 24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg); } + 12%, 28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg); } + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg); } + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg); } + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg); } + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg); } + 40%, 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, +.fa-flip-horizontal.fa-flip-vertical { + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +.fa-rotate-by { + -webkit-transform: rotate(var(--fa-rotate-angle, 0)); + transform: rotate(var(--fa-rotate-angle, 0)); } + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2.5em; } + +.fa-stack-1x, +.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: var(--fa-stack-z-index, auto); } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: var(--fa-inverse, #fff); } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ + +.fa-0::before { + content: "\30"; } + +.fa-1::before { + content: "\31"; } + +.fa-2::before { + content: "\32"; } + +.fa-3::before { + content: "\33"; } + +.fa-4::before { + content: "\34"; } + +.fa-5::before { + content: "\35"; } + +.fa-6::before { + content: "\36"; } + +.fa-7::before { + content: "\37"; } + +.fa-8::before { + content: "\38"; } + +.fa-9::before { + content: "\39"; } + +.fa-fill-drip::before { + content: "\f576"; } + +.fa-arrows-to-circle::before { + content: "\e4bd"; } + +.fa-circle-chevron-right::before { + content: "\f138"; } + +.fa-chevron-circle-right::before { + content: "\f138"; } + +.fa-at::before { + content: "\40"; } + +.fa-trash-can::before { + content: "\f2ed"; } + +.fa-trash-alt::before { + content: "\f2ed"; } + +.fa-text-height::before { + content: "\f034"; } + +.fa-user-xmark::before { + content: "\f235"; } + +.fa-user-times::before { + content: "\f235"; } + +.fa-stethoscope::before { + content: "\f0f1"; } + +.fa-message::before { + content: "\f27a"; } + +.fa-comment-alt::before { + content: "\f27a"; } + +.fa-info::before { + content: "\f129"; } + +.fa-down-left-and-up-right-to-center::before { + content: "\f422"; } + +.fa-compress-alt::before { + content: "\f422"; } + +.fa-explosion::before { + content: "\e4e9"; } + +.fa-file-lines::before { + content: "\f15c"; } + +.fa-file-alt::before { + content: "\f15c"; } + +.fa-file-text::before { + content: "\f15c"; } + +.fa-wave-square::before { + content: "\f83e"; } + +.fa-ring::before { + content: "\f70b"; } + +.fa-building-un::before { + content: "\e4d9"; } + +.fa-dice-three::before { + content: "\f527"; } + +.fa-calendar-days::before { + content: "\f073"; } + +.fa-calendar-alt::before { + content: "\f073"; } + +.fa-anchor-circle-check::before { + content: "\e4aa"; } + +.fa-building-circle-arrow-right::before { + content: "\e4d1"; } + +.fa-volleyball::before { + content: "\f45f"; } + +.fa-volleyball-ball::before { + content: "\f45f"; } + +.fa-arrows-up-to-line::before { + content: "\e4c2"; } + +.fa-sort-down::before { + content: "\f0dd"; } + +.fa-sort-desc::before { + content: "\f0dd"; } + +.fa-circle-minus::before { + content: "\f056"; } + +.fa-minus-circle::before { + content: "\f056"; } + +.fa-door-open::before { + content: "\f52b"; } + +.fa-right-from-bracket::before { + content: "\f2f5"; } + +.fa-sign-out-alt::before { + content: "\f2f5"; } + +.fa-atom::before { + content: "\f5d2"; } + +.fa-soap::before { + content: "\e06e"; } + +.fa-icons::before { + content: "\f86d"; } + +.fa-heart-music-camera-bolt::before { + content: "\f86d"; } + +.fa-microphone-lines-slash::before { + content: "\f539"; } + +.fa-microphone-alt-slash::before { + content: "\f539"; } + +.fa-bridge-circle-check::before { + content: "\e4c9"; } + +.fa-pump-medical::before { + content: "\e06a"; } + +.fa-fingerprint::before { + content: "\f577"; } + +.fa-hand-point-right::before { + content: "\f0a4"; } + +.fa-magnifying-glass-location::before { + content: "\f689"; } + +.fa-search-location::before { + content: "\f689"; } + +.fa-forward-step::before { + content: "\f051"; } + +.fa-step-forward::before { + content: "\f051"; } + +.fa-face-smile-beam::before { + content: "\f5b8"; } + +.fa-smile-beam::before { + content: "\f5b8"; } + +.fa-flag-checkered::before { + content: "\f11e"; } + +.fa-football::before { + content: "\f44e"; } + +.fa-football-ball::before { + content: "\f44e"; } + +.fa-school-circle-exclamation::before { + content: "\e56c"; } + +.fa-crop::before { + content: "\f125"; } + +.fa-angles-down::before { + content: "\f103"; } + +.fa-angle-double-down::before { + content: "\f103"; } + +.fa-users-rectangle::before { + content: "\e594"; } + +.fa-people-roof::before { + content: "\e537"; } + +.fa-people-line::before { + content: "\e534"; } + +.fa-beer-mug-empty::before { + content: "\f0fc"; } + +.fa-beer::before { + content: "\f0fc"; } + +.fa-diagram-predecessor::before { + content: "\e477"; } + +.fa-arrow-up-long::before { + content: "\f176"; } + +.fa-long-arrow-up::before { + content: "\f176"; } + +.fa-fire-flame-simple::before { + content: "\f46a"; } + +.fa-burn::before { + content: "\f46a"; } + +.fa-person::before { + content: "\f183"; } + +.fa-male::before { + content: "\f183"; } + +.fa-laptop::before { + content: "\f109"; } + +.fa-file-csv::before { + content: "\f6dd"; } + +.fa-menorah::before { + content: "\f676"; } + +.fa-truck-plane::before { + content: "\e58f"; } + +.fa-record-vinyl::before { + content: "\f8d9"; } + +.fa-face-grin-stars::before { + content: "\f587"; } + +.fa-grin-stars::before { + content: "\f587"; } + +.fa-bong::before { + content: "\f55c"; } + +.fa-spaghetti-monster-flying::before { + content: "\f67b"; } + +.fa-pastafarianism::before { + content: "\f67b"; } + +.fa-arrow-down-up-across-line::before { + content: "\e4af"; } + +.fa-spoon::before { + content: "\f2e5"; } + +.fa-utensil-spoon::before { + content: "\f2e5"; } + +.fa-jar-wheat::before { + content: "\e517"; } + +.fa-envelopes-bulk::before { + content: "\f674"; } + +.fa-mail-bulk::before { + content: "\f674"; } + +.fa-file-circle-exclamation::before { + content: "\e4eb"; } + +.fa-circle-h::before { + content: "\f47e"; } + +.fa-hospital-symbol::before { + content: "\f47e"; } + +.fa-pager::before { + content: "\f815"; } + +.fa-address-book::before { + content: "\f2b9"; } + +.fa-contact-book::before { + content: "\f2b9"; } + +.fa-strikethrough::before { + content: "\f0cc"; } + +.fa-k::before { + content: "\4b"; } + +.fa-landmark-flag::before { + content: "\e51c"; } + +.fa-pencil::before { + content: "\f303"; } + +.fa-pencil-alt::before { + content: "\f303"; } + +.fa-backward::before { + content: "\f04a"; } + +.fa-caret-right::before { + content: "\f0da"; } + +.fa-comments::before { + content: "\f086"; } + +.fa-paste::before { + content: "\f0ea"; } + +.fa-file-clipboard::before { + content: "\f0ea"; } + +.fa-code-pull-request::before { + content: "\e13c"; } + +.fa-clipboard-list::before { + content: "\f46d"; } + +.fa-truck-ramp-box::before { + content: "\f4de"; } + +.fa-truck-loading::before { + content: "\f4de"; } + +.fa-user-check::before { + content: "\f4fc"; } + +.fa-vial-virus::before { + content: "\e597"; } + +.fa-sheet-plastic::before { + content: "\e571"; } + +.fa-blog::before { + content: "\f781"; } + +.fa-user-ninja::before { + content: "\f504"; } + +.fa-person-arrow-up-from-line::before { + content: "\e539"; } + +.fa-scroll-torah::before { + content: "\f6a0"; } + +.fa-torah::before { + content: "\f6a0"; } + +.fa-broom-ball::before { + content: "\f458"; } + +.fa-quidditch::before { + content: "\f458"; } + +.fa-quidditch-broom-ball::before { + content: "\f458"; } + +.fa-toggle-off::before { + content: "\f204"; } + +.fa-box-archive::before { + content: "\f187"; } + +.fa-archive::before { + content: "\f187"; } + +.fa-person-drowning::before { + content: "\e545"; } + +.fa-arrow-down-9-1::before { + content: "\f886"; } + +.fa-sort-numeric-desc::before { + content: "\f886"; } + +.fa-sort-numeric-down-alt::before { + content: "\f886"; } + +.fa-face-grin-tongue-squint::before { + content: "\f58a"; } + +.fa-grin-tongue-squint::before { + content: "\f58a"; } + +.fa-spray-can::before { + content: "\f5bd"; } + +.fa-truck-monster::before { + content: "\f63b"; } + +.fa-w::before { + content: "\57"; } + +.fa-earth-africa::before { + content: "\f57c"; } + +.fa-globe-africa::before { + content: "\f57c"; } + +.fa-rainbow::before { + content: "\f75b"; } + +.fa-circle-notch::before { + content: "\f1ce"; } + +.fa-tablet-screen-button::before { + content: "\f3fa"; } + +.fa-tablet-alt::before { + content: "\f3fa"; } + +.fa-paw::before { + content: "\f1b0"; } + +.fa-cloud::before { + content: "\f0c2"; } + +.fa-trowel-bricks::before { + content: "\e58a"; } + +.fa-face-flushed::before { + content: "\f579"; } + +.fa-flushed::before { + content: "\f579"; } + +.fa-hospital-user::before { + content: "\f80d"; } + +.fa-tent-arrow-left-right::before { + content: "\e57f"; } + +.fa-gavel::before { + content: "\f0e3"; } + +.fa-legal::before { + content: "\f0e3"; } + +.fa-binoculars::before { + content: "\f1e5"; } + +.fa-microphone-slash::before { + content: "\f131"; } + +.fa-box-tissue::before { + content: "\e05b"; } + +.fa-motorcycle::before { + content: "\f21c"; } + +.fa-bell-concierge::before { + content: "\f562"; } + +.fa-concierge-bell::before { + content: "\f562"; } + +.fa-pen-ruler::before { + content: "\f5ae"; } + +.fa-pencil-ruler::before { + content: "\f5ae"; } + +.fa-people-arrows::before { + content: "\e068"; } + +.fa-people-arrows-left-right::before { + content: "\e068"; } + +.fa-mars-and-venus-burst::before { + content: "\e523"; } + +.fa-square-caret-right::before { + content: "\f152"; } + +.fa-caret-square-right::before { + content: "\f152"; } + +.fa-scissors::before { + content: "\f0c4"; } + +.fa-cut::before { + content: "\f0c4"; } + +.fa-sun-plant-wilt::before { + content: "\e57a"; } + +.fa-toilets-portable::before { + content: "\e584"; } + +.fa-hockey-puck::before { + content: "\f453"; } + +.fa-table::before { + content: "\f0ce"; } + +.fa-magnifying-glass-arrow-right::before { + content: "\e521"; } + +.fa-tachograph-digital::before { + content: "\f566"; } + +.fa-digital-tachograph::before { + content: "\f566"; } + +.fa-users-slash::before { + content: "\e073"; } + +.fa-clover::before { + content: "\e139"; } + +.fa-reply::before { + content: "\f3e5"; } + +.fa-mail-reply::before { + content: "\f3e5"; } + +.fa-star-and-crescent::before { + content: "\f699"; } + +.fa-house-fire::before { + content: "\e50c"; } + +.fa-square-minus::before { + content: "\f146"; } + +.fa-minus-square::before { + content: "\f146"; } + +.fa-helicopter::before { + content: "\f533"; } + +.fa-compass::before { + content: "\f14e"; } + +.fa-square-caret-down::before { + content: "\f150"; } + +.fa-caret-square-down::before { + content: "\f150"; } + +.fa-file-circle-question::before { + content: "\e4ef"; } + +.fa-laptop-code::before { + content: "\f5fc"; } + +.fa-swatchbook::before { + content: "\f5c3"; } + +.fa-prescription-bottle::before { + content: "\f485"; } + +.fa-bars::before { + content: "\f0c9"; } + +.fa-navicon::before { + content: "\f0c9"; } + +.fa-people-group::before { + content: "\e533"; } + +.fa-hourglass-end::before { + content: "\f253"; } + +.fa-hourglass-3::before { + content: "\f253"; } + +.fa-heart-crack::before { + content: "\f7a9"; } + +.fa-heart-broken::before { + content: "\f7a9"; } + +.fa-square-up-right::before { + content: "\f360"; } + +.fa-external-link-square-alt::before { + content: "\f360"; } + +.fa-face-kiss-beam::before { + content: "\f597"; } + +.fa-kiss-beam::before { + content: "\f597"; } + +.fa-film::before { + content: "\f008"; } + +.fa-ruler-horizontal::before { + content: "\f547"; } + +.fa-people-robbery::before { + content: "\e536"; } + +.fa-lightbulb::before { + content: "\f0eb"; } + +.fa-caret-left::before { + content: "\f0d9"; } + +.fa-circle-exclamation::before { + content: "\f06a"; } + +.fa-exclamation-circle::before { + content: "\f06a"; } + +.fa-school-circle-xmark::before { + content: "\e56d"; } + +.fa-arrow-right-from-bracket::before { + content: "\f08b"; } + +.fa-sign-out::before { + content: "\f08b"; } + +.fa-circle-chevron-down::before { + content: "\f13a"; } + +.fa-chevron-circle-down::before { + content: "\f13a"; } + +.fa-unlock-keyhole::before { + content: "\f13e"; } + +.fa-unlock-alt::before { + content: "\f13e"; } + +.fa-cloud-showers-heavy::before { + content: "\f740"; } + +.fa-headphones-simple::before { + content: "\f58f"; } + +.fa-headphones-alt::before { + content: "\f58f"; } + +.fa-sitemap::before { + content: "\f0e8"; } + +.fa-circle-dollar-to-slot::before { + content: "\f4b9"; } + +.fa-donate::before { + content: "\f4b9"; } + +.fa-memory::before { + content: "\f538"; } + +.fa-road-spikes::before { + content: "\e568"; } + +.fa-fire-burner::before { + content: "\e4f1"; } + +.fa-flag::before { + content: "\f024"; } + +.fa-hanukiah::before { + content: "\f6e6"; } + +.fa-feather::before { + content: "\f52d"; } + +.fa-volume-low::before { + content: "\f027"; } + +.fa-volume-down::before { + content: "\f027"; } + +.fa-comment-slash::before { + content: "\f4b3"; } + +.fa-cloud-sun-rain::before { + content: "\f743"; } + +.fa-compress::before { + content: "\f066"; } + +.fa-wheat-awn::before { + content: "\e2cd"; } + +.fa-wheat-alt::before { + content: "\e2cd"; } + +.fa-ankh::before { + content: "\f644"; } + +.fa-hands-holding-child::before { + content: "\e4fa"; } + +.fa-asterisk::before { + content: "\2a"; } + +.fa-square-check::before { + content: "\f14a"; } + +.fa-check-square::before { + content: "\f14a"; } + +.fa-peseta-sign::before { + content: "\e221"; } + +.fa-heading::before { + content: "\f1dc"; } + +.fa-header::before { + content: "\f1dc"; } + +.fa-ghost::before { + content: "\f6e2"; } + +.fa-list::before { + content: "\f03a"; } + +.fa-list-squares::before { + content: "\f03a"; } + +.fa-square-phone-flip::before { + content: "\f87b"; } + +.fa-phone-square-alt::before { + content: "\f87b"; } + +.fa-cart-plus::before { + content: "\f217"; } + +.fa-gamepad::before { + content: "\f11b"; } + +.fa-circle-dot::before { + content: "\f192"; } + +.fa-dot-circle::before { + content: "\f192"; } + +.fa-face-dizzy::before { + content: "\f567"; } + +.fa-dizzy::before { + content: "\f567"; } + +.fa-egg::before { + content: "\f7fb"; } + +.fa-house-medical-circle-xmark::before { + content: "\e513"; } + +.fa-campground::before { + content: "\f6bb"; } + +.fa-folder-plus::before { + content: "\f65e"; } + +.fa-futbol::before { + content: "\f1e3"; } + +.fa-futbol-ball::before { + content: "\f1e3"; } + +.fa-soccer-ball::before { + content: "\f1e3"; } + +.fa-paintbrush::before { + content: "\f1fc"; } + +.fa-paint-brush::before { + content: "\f1fc"; } + +.fa-lock::before { + content: "\f023"; } + +.fa-gas-pump::before { + content: "\f52f"; } + +.fa-hot-tub-person::before { + content: "\f593"; } + +.fa-hot-tub::before { + content: "\f593"; } + +.fa-map-location::before { + content: "\f59f"; } + +.fa-map-marked::before { + content: "\f59f"; } + +.fa-house-flood-water::before { + content: "\e50e"; } + +.fa-tree::before { + content: "\f1bb"; } + +.fa-bridge-lock::before { + content: "\e4cc"; } + +.fa-sack-dollar::before { + content: "\f81d"; } + +.fa-pen-to-square::before { + content: "\f044"; } + +.fa-edit::before { + content: "\f044"; } + +.fa-car-side::before { + content: "\f5e4"; } + +.fa-share-nodes::before { + content: "\f1e0"; } + +.fa-share-alt::before { + content: "\f1e0"; } + +.fa-heart-circle-minus::before { + content: "\e4ff"; } + +.fa-hourglass-half::before { + content: "\f252"; } + +.fa-hourglass-2::before { + content: "\f252"; } + +.fa-microscope::before { + content: "\f610"; } + +.fa-sink::before { + content: "\e06d"; } + +.fa-bag-shopping::before { + content: "\f290"; } + +.fa-shopping-bag::before { + content: "\f290"; } + +.fa-arrow-down-z-a::before { + content: "\f881"; } + +.fa-sort-alpha-desc::before { + content: "\f881"; } + +.fa-sort-alpha-down-alt::before { + content: "\f881"; } + +.fa-mitten::before { + content: "\f7b5"; } + +.fa-person-rays::before { + content: "\e54d"; } + +.fa-users::before { + content: "\f0c0"; } + +.fa-eye-slash::before { + content: "\f070"; } + +.fa-flask-vial::before { + content: "\e4f3"; } + +.fa-hand::before { + content: "\f256"; } + +.fa-hand-paper::before { + content: "\f256"; } + +.fa-om::before { + content: "\f679"; } + +.fa-worm::before { + content: "\e599"; } + +.fa-house-circle-xmark::before { + content: "\e50b"; } + +.fa-plug::before { + content: "\f1e6"; } + +.fa-chevron-up::before { + content: "\f077"; } + +.fa-hand-spock::before { + content: "\f259"; } + +.fa-stopwatch::before { + content: "\f2f2"; } + +.fa-face-kiss::before { + content: "\f596"; } + +.fa-kiss::before { + content: "\f596"; } + +.fa-bridge-circle-xmark::before { + content: "\e4cb"; } + +.fa-face-grin-tongue::before { + content: "\f589"; } + +.fa-grin-tongue::before { + content: "\f589"; } + +.fa-chess-bishop::before { + content: "\f43a"; } + +.fa-face-grin-wink::before { + content: "\f58c"; } + +.fa-grin-wink::before { + content: "\f58c"; } + +.fa-ear-deaf::before { + content: "\f2a4"; } + +.fa-deaf::before { + content: "\f2a4"; } + +.fa-deafness::before { + content: "\f2a4"; } + +.fa-hard-of-hearing::before { + content: "\f2a4"; } + +.fa-road-circle-check::before { + content: "\e564"; } + +.fa-dice-five::before { + content: "\f523"; } + +.fa-square-rss::before { + content: "\f143"; } + +.fa-rss-square::before { + content: "\f143"; } + +.fa-land-mine-on::before { + content: "\e51b"; } + +.fa-i-cursor::before { + content: "\f246"; } + +.fa-stamp::before { + content: "\f5bf"; } + +.fa-stairs::before { + content: "\e289"; } + +.fa-i::before { + content: "\49"; } + +.fa-hryvnia-sign::before { + content: "\f6f2"; } + +.fa-hryvnia::before { + content: "\f6f2"; } + +.fa-pills::before { + content: "\f484"; } + +.fa-face-grin-wide::before { + content: "\f581"; } + +.fa-grin-alt::before { + content: "\f581"; } + +.fa-tooth::before { + content: "\f5c9"; } + +.fa-v::before { + content: "\56"; } + +.fa-bangladeshi-taka-sign::before { + content: "\e2e6"; } + +.fa-bicycle::before { + content: "\f206"; } + +.fa-staff-snake::before { + content: "\e579"; } + +.fa-rod-asclepius::before { + content: "\e579"; } + +.fa-rod-snake::before { + content: "\e579"; } + +.fa-staff-aesculapius::before { + content: "\e579"; } + +.fa-head-side-cough-slash::before { + content: "\e062"; } + +.fa-truck-medical::before { + content: "\f0f9"; } + +.fa-ambulance::before { + content: "\f0f9"; } + +.fa-wheat-awn-circle-exclamation::before { + content: "\e598"; } + +.fa-snowman::before { + content: "\f7d0"; } + +.fa-mortar-pestle::before { + content: "\f5a7"; } + +.fa-road-barrier::before { + content: "\e562"; } + +.fa-school::before { + content: "\f549"; } + +.fa-igloo::before { + content: "\f7ae"; } + +.fa-joint::before { + content: "\f595"; } + +.fa-angle-right::before { + content: "\f105"; } + +.fa-horse::before { + content: "\f6f0"; } + +.fa-q::before { + content: "\51"; } + +.fa-g::before { + content: "\47"; } + +.fa-notes-medical::before { + content: "\f481"; } + +.fa-temperature-half::before { + content: "\f2c9"; } + +.fa-temperature-2::before { + content: "\f2c9"; } + +.fa-thermometer-2::before { + content: "\f2c9"; } + +.fa-thermometer-half::before { + content: "\f2c9"; } + +.fa-dong-sign::before { + content: "\e169"; } + +.fa-capsules::before { + content: "\f46b"; } + +.fa-poo-storm::before { + content: "\f75a"; } + +.fa-poo-bolt::before { + content: "\f75a"; } + +.fa-face-frown-open::before { + content: "\f57a"; } + +.fa-frown-open::before { + content: "\f57a"; } + +.fa-hand-point-up::before { + content: "\f0a6"; } + +.fa-money-bill::before { + content: "\f0d6"; } + +.fa-bookmark::before { + content: "\f02e"; } + +.fa-align-justify::before { + content: "\f039"; } + +.fa-umbrella-beach::before { + content: "\f5ca"; } + +.fa-helmet-un::before { + content: "\e503"; } + +.fa-bullseye::before { + content: "\f140"; } + +.fa-bacon::before { + content: "\f7e5"; } + +.fa-hand-point-down::before { + content: "\f0a7"; } + +.fa-arrow-up-from-bracket::before { + content: "\e09a"; } + +.fa-folder::before { + content: "\f07b"; } + +.fa-folder-blank::before { + content: "\f07b"; } + +.fa-file-waveform::before { + content: "\f478"; } + +.fa-file-medical-alt::before { + content: "\f478"; } + +.fa-radiation::before { + content: "\f7b9"; } + +.fa-chart-simple::before { + content: "\e473"; } + +.fa-mars-stroke::before { + content: "\f229"; } + +.fa-vial::before { + content: "\f492"; } + +.fa-gauge::before { + content: "\f624"; } + +.fa-dashboard::before { + content: "\f624"; } + +.fa-gauge-med::before { + content: "\f624"; } + +.fa-tachometer-alt-average::before { + content: "\f624"; } + +.fa-wand-magic-sparkles::before { + content: "\e2ca"; } + +.fa-magic-wand-sparkles::before { + content: "\e2ca"; } + +.fa-e::before { + content: "\45"; } + +.fa-pen-clip::before { + content: "\f305"; } + +.fa-pen-alt::before { + content: "\f305"; } + +.fa-bridge-circle-exclamation::before { + content: "\e4ca"; } + +.fa-user::before { + content: "\f007"; } + +.fa-school-circle-check::before { + content: "\e56b"; } + +.fa-dumpster::before { + content: "\f793"; } + +.fa-van-shuttle::before { + content: "\f5b6"; } + +.fa-shuttle-van::before { + content: "\f5b6"; } + +.fa-building-user::before { + content: "\e4da"; } + +.fa-square-caret-left::before { + content: "\f191"; } + +.fa-caret-square-left::before { + content: "\f191"; } + +.fa-highlighter::before { + content: "\f591"; } + +.fa-key::before { + content: "\f084"; } + +.fa-bullhorn::before { + content: "\f0a1"; } + +.fa-globe::before { + content: "\f0ac"; } + +.fa-synagogue::before { + content: "\f69b"; } + +.fa-person-half-dress::before { + content: "\e548"; } + +.fa-road-bridge::before { + content: "\e563"; } + +.fa-location-arrow::before { + content: "\f124"; } + +.fa-c::before { + content: "\43"; } + +.fa-tablet-button::before { + content: "\f10a"; } + +.fa-building-lock::before { + content: "\e4d6"; } + +.fa-pizza-slice::before { + content: "\f818"; } + +.fa-money-bill-wave::before { + content: "\f53a"; } + +.fa-chart-area::before { + content: "\f1fe"; } + +.fa-area-chart::before { + content: "\f1fe"; } + +.fa-house-flag::before { + content: "\e50d"; } + +.fa-person-circle-minus::before { + content: "\e540"; } + +.fa-ban::before { + content: "\f05e"; } + +.fa-cancel::before { + content: "\f05e"; } + +.fa-camera-rotate::before { + content: "\e0d8"; } + +.fa-spray-can-sparkles::before { + content: "\f5d0"; } + +.fa-air-freshener::before { + content: "\f5d0"; } + +.fa-star::before { + content: "\f005"; } + +.fa-repeat::before { + content: "\f363"; } + +.fa-cross::before { + content: "\f654"; } + +.fa-box::before { + content: "\f466"; } + +.fa-venus-mars::before { + content: "\f228"; } + +.fa-arrow-pointer::before { + content: "\f245"; } + +.fa-mouse-pointer::before { + content: "\f245"; } + +.fa-maximize::before { + content: "\f31e"; } + +.fa-expand-arrows-alt::before { + content: "\f31e"; } + +.fa-charging-station::before { + content: "\f5e7"; } + +.fa-shapes::before { + content: "\f61f"; } + +.fa-triangle-circle-square::before { + content: "\f61f"; } + +.fa-shuffle::before { + content: "\f074"; } + +.fa-random::before { + content: "\f074"; } + +.fa-person-running::before { + content: "\f70c"; } + +.fa-running::before { + content: "\f70c"; } + +.fa-mobile-retro::before { + content: "\e527"; } + +.fa-grip-lines-vertical::before { + content: "\f7a5"; } + +.fa-spider::before { + content: "\f717"; } + +.fa-hands-bound::before { + content: "\e4f9"; } + +.fa-file-invoice-dollar::before { + content: "\f571"; } + +.fa-plane-circle-exclamation::before { + content: "\e556"; } + +.fa-x-ray::before { + content: "\f497"; } + +.fa-spell-check::before { + content: "\f891"; } + +.fa-slash::before { + content: "\f715"; } + +.fa-computer-mouse::before { + content: "\f8cc"; } + +.fa-mouse::before { + content: "\f8cc"; } + +.fa-arrow-right-to-bracket::before { + content: "\f090"; } + +.fa-sign-in::before { + content: "\f090"; } + +.fa-shop-slash::before { + content: "\e070"; } + +.fa-store-alt-slash::before { + content: "\e070"; } + +.fa-server::before { + content: "\f233"; } + +.fa-virus-covid-slash::before { + content: "\e4a9"; } + +.fa-shop-lock::before { + content: "\e4a5"; } + +.fa-hourglass-start::before { + content: "\f251"; } + +.fa-hourglass-1::before { + content: "\f251"; } + +.fa-blender-phone::before { + content: "\f6b6"; } + +.fa-building-wheat::before { + content: "\e4db"; } + +.fa-person-breastfeeding::before { + content: "\e53a"; } + +.fa-right-to-bracket::before { + content: "\f2f6"; } + +.fa-sign-in-alt::before { + content: "\f2f6"; } + +.fa-venus::before { + content: "\f221"; } + +.fa-passport::before { + content: "\f5ab"; } + +.fa-heart-pulse::before { + content: "\f21e"; } + +.fa-heartbeat::before { + content: "\f21e"; } + +.fa-people-carry-box::before { + content: "\f4ce"; } + +.fa-people-carry::before { + content: "\f4ce"; } + +.fa-temperature-high::before { + content: "\f769"; } + +.fa-microchip::before { + content: "\f2db"; } + +.fa-crown::before { + content: "\f521"; } + +.fa-weight-hanging::before { + content: "\f5cd"; } + +.fa-xmarks-lines::before { + content: "\e59a"; } + +.fa-file-prescription::before { + content: "\f572"; } + +.fa-weight-scale::before { + content: "\f496"; } + +.fa-weight::before { + content: "\f496"; } + +.fa-user-group::before { + content: "\f500"; } + +.fa-user-friends::before { + content: "\f500"; } + +.fa-arrow-up-a-z::before { + content: "\f15e"; } + +.fa-sort-alpha-up::before { + content: "\f15e"; } + +.fa-chess-knight::before { + content: "\f441"; } + +.fa-face-laugh-squint::before { + content: "\f59b"; } + +.fa-laugh-squint::before { + content: "\f59b"; } + +.fa-wheelchair::before { + content: "\f193"; } + +.fa-circle-arrow-up::before { + content: "\f0aa"; } + +.fa-arrow-circle-up::before { + content: "\f0aa"; } + +.fa-toggle-on::before { + content: "\f205"; } + +.fa-person-walking::before { + content: "\f554"; } + +.fa-walking::before { + content: "\f554"; } + +.fa-l::before { + content: "\4c"; } + +.fa-fire::before { + content: "\f06d"; } + +.fa-bed-pulse::before { + content: "\f487"; } + +.fa-procedures::before { + content: "\f487"; } + +.fa-shuttle-space::before { + content: "\f197"; } + +.fa-space-shuttle::before { + content: "\f197"; } + +.fa-face-laugh::before { + content: "\f599"; } + +.fa-laugh::before { + content: "\f599"; } + +.fa-folder-open::before { + content: "\f07c"; } + +.fa-heart-circle-plus::before { + content: "\e500"; } + +.fa-code-fork::before { + content: "\e13b"; } + +.fa-city::before { + content: "\f64f"; } + +.fa-microphone-lines::before { + content: "\f3c9"; } + +.fa-microphone-alt::before { + content: "\f3c9"; } + +.fa-pepper-hot::before { + content: "\f816"; } + +.fa-unlock::before { + content: "\f09c"; } + +.fa-colon-sign::before { + content: "\e140"; } + +.fa-headset::before { + content: "\f590"; } + +.fa-store-slash::before { + content: "\e071"; } + +.fa-road-circle-xmark::before { + content: "\e566"; } + +.fa-user-minus::before { + content: "\f503"; } + +.fa-mars-stroke-up::before { + content: "\f22a"; } + +.fa-mars-stroke-v::before { + content: "\f22a"; } + +.fa-champagne-glasses::before { + content: "\f79f"; } + +.fa-glass-cheers::before { + content: "\f79f"; } + +.fa-clipboard::before { + content: "\f328"; } + +.fa-house-circle-exclamation::before { + content: "\e50a"; } + +.fa-file-arrow-up::before { + content: "\f574"; } + +.fa-file-upload::before { + content: "\f574"; } + +.fa-wifi::before { + content: "\f1eb"; } + +.fa-wifi-3::before { + content: "\f1eb"; } + +.fa-wifi-strong::before { + content: "\f1eb"; } + +.fa-bath::before { + content: "\f2cd"; } + +.fa-bathtub::before { + content: "\f2cd"; } + +.fa-underline::before { + content: "\f0cd"; } + +.fa-user-pen::before { + content: "\f4ff"; } + +.fa-user-edit::before { + content: "\f4ff"; } + +.fa-signature::before { + content: "\f5b7"; } + +.fa-stroopwafel::before { + content: "\f551"; } + +.fa-bold::before { + content: "\f032"; } + +.fa-anchor-lock::before { + content: "\e4ad"; } + +.fa-building-ngo::before { + content: "\e4d7"; } + +.fa-manat-sign::before { + content: "\e1d5"; } + +.fa-not-equal::before { + content: "\f53e"; } + +.fa-border-top-left::before { + content: "\f853"; } + +.fa-border-style::before { + content: "\f853"; } + +.fa-map-location-dot::before { + content: "\f5a0"; } + +.fa-map-marked-alt::before { + content: "\f5a0"; } + +.fa-jedi::before { + content: "\f669"; } + +.fa-square-poll-vertical::before { + content: "\f681"; } + +.fa-poll::before { + content: "\f681"; } + +.fa-mug-hot::before { + content: "\f7b6"; } + +.fa-car-battery::before { + content: "\f5df"; } + +.fa-battery-car::before { + content: "\f5df"; } + +.fa-gift::before { + content: "\f06b"; } + +.fa-dice-two::before { + content: "\f528"; } + +.fa-chess-queen::before { + content: "\f445"; } + +.fa-glasses::before { + content: "\f530"; } + +.fa-chess-board::before { + content: "\f43c"; } + +.fa-building-circle-check::before { + content: "\e4d2"; } + +.fa-person-chalkboard::before { + content: "\e53d"; } + +.fa-mars-stroke-right::before { + content: "\f22b"; } + +.fa-mars-stroke-h::before { + content: "\f22b"; } + +.fa-hand-back-fist::before { + content: "\f255"; } + +.fa-hand-rock::before { + content: "\f255"; } + +.fa-square-caret-up::before { + content: "\f151"; } + +.fa-caret-square-up::before { + content: "\f151"; } + +.fa-cloud-showers-water::before { + content: "\e4e4"; } + +.fa-chart-bar::before { + content: "\f080"; } + +.fa-bar-chart::before { + content: "\f080"; } + +.fa-hands-bubbles::before { + content: "\e05e"; } + +.fa-hands-wash::before { + content: "\e05e"; } + +.fa-less-than-equal::before { + content: "\f537"; } + +.fa-train::before { + content: "\f238"; } + +.fa-eye-low-vision::before { + content: "\f2a8"; } + +.fa-low-vision::before { + content: "\f2a8"; } + +.fa-crow::before { + content: "\f520"; } + +.fa-sailboat::before { + content: "\e445"; } + +.fa-window-restore::before { + content: "\f2d2"; } + +.fa-square-plus::before { + content: "\f0fe"; } + +.fa-plus-square::before { + content: "\f0fe"; } + +.fa-torii-gate::before { + content: "\f6a1"; } + +.fa-frog::before { + content: "\f52e"; } + +.fa-bucket::before { + content: "\e4cf"; } + +.fa-image::before { + content: "\f03e"; } + +.fa-microphone::before { + content: "\f130"; } + +.fa-cow::before { + content: "\f6c8"; } + +.fa-caret-up::before { + content: "\f0d8"; } + +.fa-screwdriver::before { + content: "\f54a"; } + +.fa-folder-closed::before { + content: "\e185"; } + +.fa-house-tsunami::before { + content: "\e515"; } + +.fa-square-nfi::before { + content: "\e576"; } + +.fa-arrow-up-from-ground-water::before { + content: "\e4b5"; } + +.fa-martini-glass::before { + content: "\f57b"; } + +.fa-glass-martini-alt::before { + content: "\f57b"; } + +.fa-rotate-left::before { + content: "\f2ea"; } + +.fa-rotate-back::before { + content: "\f2ea"; } + +.fa-rotate-backward::before { + content: "\f2ea"; } + +.fa-undo-alt::before { + content: "\f2ea"; } + +.fa-table-columns::before { + content: "\f0db"; } + +.fa-columns::before { + content: "\f0db"; } + +.fa-lemon::before { + content: "\f094"; } + +.fa-head-side-mask::before { + content: "\e063"; } + +.fa-handshake::before { + content: "\f2b5"; } + +.fa-gem::before { + content: "\f3a5"; } + +.fa-dolly::before { + content: "\f472"; } + +.fa-dolly-box::before { + content: "\f472"; } + +.fa-smoking::before { + content: "\f48d"; } + +.fa-minimize::before { + content: "\f78c"; } + +.fa-compress-arrows-alt::before { + content: "\f78c"; } + +.fa-monument::before { + content: "\f5a6"; } + +.fa-snowplow::before { + content: "\f7d2"; } + +.fa-angles-right::before { + content: "\f101"; } + +.fa-angle-double-right::before { + content: "\f101"; } + +.fa-cannabis::before { + content: "\f55f"; } + +.fa-circle-play::before { + content: "\f144"; } + +.fa-play-circle::before { + content: "\f144"; } + +.fa-tablets::before { + content: "\f490"; } + +.fa-ethernet::before { + content: "\f796"; } + +.fa-euro-sign::before { + content: "\f153"; } + +.fa-eur::before { + content: "\f153"; } + +.fa-euro::before { + content: "\f153"; } + +.fa-chair::before { + content: "\f6c0"; } + +.fa-circle-check::before { + content: "\f058"; } + +.fa-check-circle::before { + content: "\f058"; } + +.fa-circle-stop::before { + content: "\f28d"; } + +.fa-stop-circle::before { + content: "\f28d"; } + +.fa-compass-drafting::before { + content: "\f568"; } + +.fa-drafting-compass::before { + content: "\f568"; } + +.fa-plate-wheat::before { + content: "\e55a"; } + +.fa-icicles::before { + content: "\f7ad"; } + +.fa-person-shelter::before { + content: "\e54f"; } + +.fa-neuter::before { + content: "\f22c"; } + +.fa-id-badge::before { + content: "\f2c1"; } + +.fa-marker::before { + content: "\f5a1"; } + +.fa-face-laugh-beam::before { + content: "\f59a"; } + +.fa-laugh-beam::before { + content: "\f59a"; } + +.fa-helicopter-symbol::before { + content: "\e502"; } + +.fa-universal-access::before { + content: "\f29a"; } + +.fa-circle-chevron-up::before { + content: "\f139"; } + +.fa-chevron-circle-up::before { + content: "\f139"; } + +.fa-lari-sign::before { + content: "\e1c8"; } + +.fa-volcano::before { + content: "\f770"; } + +.fa-person-walking-dashed-line-arrow-right::before { + content: "\e553"; } + +.fa-sterling-sign::before { + content: "\f154"; } + +.fa-gbp::before { + content: "\f154"; } + +.fa-pound-sign::before { + content: "\f154"; } + +.fa-viruses::before { + content: "\e076"; } + +.fa-square-person-confined::before { + content: "\e577"; } + +.fa-user-tie::before { + content: "\f508"; } + +.fa-arrow-down-long::before { + content: "\f175"; } + +.fa-long-arrow-down::before { + content: "\f175"; } + +.fa-tent-arrow-down-to-line::before { + content: "\e57e"; } + +.fa-certificate::before { + content: "\f0a3"; } + +.fa-reply-all::before { + content: "\f122"; } + +.fa-mail-reply-all::before { + content: "\f122"; } + +.fa-suitcase::before { + content: "\f0f2"; } + +.fa-person-skating::before { + content: "\f7c5"; } + +.fa-skating::before { + content: "\f7c5"; } + +.fa-filter-circle-dollar::before { + content: "\f662"; } + +.fa-funnel-dollar::before { + content: "\f662"; } + +.fa-camera-retro::before { + content: "\f083"; } + +.fa-circle-arrow-down::before { + content: "\f0ab"; } + +.fa-arrow-circle-down::before { + content: "\f0ab"; } + +.fa-file-import::before { + content: "\f56f"; } + +.fa-arrow-right-to-file::before { + content: "\f56f"; } + +.fa-square-arrow-up-right::before { + content: "\f14c"; } + +.fa-external-link-square::before { + content: "\f14c"; } + +.fa-box-open::before { + content: "\f49e"; } + +.fa-scroll::before { + content: "\f70e"; } + +.fa-spa::before { + content: "\f5bb"; } + +.fa-location-pin-lock::before { + content: "\e51f"; } + +.fa-pause::before { + content: "\f04c"; } + +.fa-hill-avalanche::before { + content: "\e507"; } + +.fa-temperature-empty::before { + content: "\f2cb"; } + +.fa-temperature-0::before { + content: "\f2cb"; } + +.fa-thermometer-0::before { + content: "\f2cb"; } + +.fa-thermometer-empty::before { + content: "\f2cb"; } + +.fa-bomb::before { + content: "\f1e2"; } + +.fa-registered::before { + content: "\f25d"; } + +.fa-address-card::before { + content: "\f2bb"; } + +.fa-contact-card::before { + content: "\f2bb"; } + +.fa-vcard::before { + content: "\f2bb"; } + +.fa-scale-unbalanced-flip::before { + content: "\f516"; } + +.fa-balance-scale-right::before { + content: "\f516"; } + +.fa-subscript::before { + content: "\f12c"; } + +.fa-diamond-turn-right::before { + content: "\f5eb"; } + +.fa-directions::before { + content: "\f5eb"; } + +.fa-burst::before { + content: "\e4dc"; } + +.fa-house-laptop::before { + content: "\e066"; } + +.fa-laptop-house::before { + content: "\e066"; } + +.fa-face-tired::before { + content: "\f5c8"; } + +.fa-tired::before { + content: "\f5c8"; } + +.fa-money-bills::before { + content: "\e1f3"; } + +.fa-smog::before { + content: "\f75f"; } + +.fa-crutch::before { + content: "\f7f7"; } + +.fa-cloud-arrow-up::before { + content: "\f0ee"; } + +.fa-cloud-upload::before { + content: "\f0ee"; } + +.fa-cloud-upload-alt::before { + content: "\f0ee"; } + +.fa-palette::before { + content: "\f53f"; } + +.fa-arrows-turn-right::before { + content: "\e4c0"; } + +.fa-vest::before { + content: "\e085"; } + +.fa-ferry::before { + content: "\e4ea"; } + +.fa-arrows-down-to-people::before { + content: "\e4b9"; } + +.fa-seedling::before { + content: "\f4d8"; } + +.fa-sprout::before { + content: "\f4d8"; } + +.fa-left-right::before { + content: "\f337"; } + +.fa-arrows-alt-h::before { + content: "\f337"; } + +.fa-boxes-packing::before { + content: "\e4c7"; } + +.fa-circle-arrow-left::before { + content: "\f0a8"; } + +.fa-arrow-circle-left::before { + content: "\f0a8"; } + +.fa-group-arrows-rotate::before { + content: "\e4f6"; } + +.fa-bowl-food::before { + content: "\e4c6"; } + +.fa-candy-cane::before { + content: "\f786"; } + +.fa-arrow-down-wide-short::before { + content: "\f160"; } + +.fa-sort-amount-asc::before { + content: "\f160"; } + +.fa-sort-amount-down::before { + content: "\f160"; } + +.fa-cloud-bolt::before { + content: "\f76c"; } + +.fa-thunderstorm::before { + content: "\f76c"; } + +.fa-text-slash::before { + content: "\f87d"; } + +.fa-remove-format::before { + content: "\f87d"; } + +.fa-face-smile-wink::before { + content: "\f4da"; } + +.fa-smile-wink::before { + content: "\f4da"; } + +.fa-file-word::before { + content: "\f1c2"; } + +.fa-file-powerpoint::before { + content: "\f1c4"; } + +.fa-arrows-left-right::before { + content: "\f07e"; } + +.fa-arrows-h::before { + content: "\f07e"; } + +.fa-house-lock::before { + content: "\e510"; } + +.fa-cloud-arrow-down::before { + content: "\f0ed"; } + +.fa-cloud-download::before { + content: "\f0ed"; } + +.fa-cloud-download-alt::before { + content: "\f0ed"; } + +.fa-children::before { + content: "\e4e1"; } + +.fa-chalkboard::before { + content: "\f51b"; } + +.fa-blackboard::before { + content: "\f51b"; } + +.fa-user-large-slash::before { + content: "\f4fa"; } + +.fa-user-alt-slash::before { + content: "\f4fa"; } + +.fa-envelope-open::before { + content: "\f2b6"; } + +.fa-handshake-simple-slash::before { + content: "\e05f"; } + +.fa-handshake-alt-slash::before { + content: "\e05f"; } + +.fa-mattress-pillow::before { + content: "\e525"; } + +.fa-guarani-sign::before { + content: "\e19a"; } + +.fa-arrows-rotate::before { + content: "\f021"; } + +.fa-refresh::before { + content: "\f021"; } + +.fa-sync::before { + content: "\f021"; } + +.fa-fire-extinguisher::before { + content: "\f134"; } + +.fa-cruzeiro-sign::before { + content: "\e152"; } + +.fa-greater-than-equal::before { + content: "\f532"; } + +.fa-shield-halved::before { + content: "\f3ed"; } + +.fa-shield-alt::before { + content: "\f3ed"; } + +.fa-book-atlas::before { + content: "\f558"; } + +.fa-atlas::before { + content: "\f558"; } + +.fa-virus::before { + content: "\e074"; } + +.fa-envelope-circle-check::before { + content: "\e4e8"; } + +.fa-layer-group::before { + content: "\f5fd"; } + +.fa-arrows-to-dot::before { + content: "\e4be"; } + +.fa-archway::before { + content: "\f557"; } + +.fa-heart-circle-check::before { + content: "\e4fd"; } + +.fa-house-chimney-crack::before { + content: "\f6f1"; } + +.fa-house-damage::before { + content: "\f6f1"; } + +.fa-file-zipper::before { + content: "\f1c6"; } + +.fa-file-archive::before { + content: "\f1c6"; } + +.fa-square::before { + content: "\f0c8"; } + +.fa-martini-glass-empty::before { + content: "\f000"; } + +.fa-glass-martini::before { + content: "\f000"; } + +.fa-couch::before { + content: "\f4b8"; } + +.fa-cedi-sign::before { + content: "\e0df"; } + +.fa-italic::before { + content: "\f033"; } + +.fa-table-cells-column-lock::before { + content: "\e678"; } + +.fa-church::before { + content: "\f51d"; } + +.fa-comments-dollar::before { + content: "\f653"; } + +.fa-democrat::before { + content: "\f747"; } + +.fa-z::before { + content: "\5a"; } + +.fa-person-skiing::before { + content: "\f7c9"; } + +.fa-skiing::before { + content: "\f7c9"; } + +.fa-road-lock::before { + content: "\e567"; } + +.fa-a::before { + content: "\41"; } + +.fa-temperature-arrow-down::before { + content: "\e03f"; } + +.fa-temperature-down::before { + content: "\e03f"; } + +.fa-feather-pointed::before { + content: "\f56b"; } + +.fa-feather-alt::before { + content: "\f56b"; } + +.fa-p::before { + content: "\50"; } + +.fa-snowflake::before { + content: "\f2dc"; } + +.fa-newspaper::before { + content: "\f1ea"; } + +.fa-rectangle-ad::before { + content: "\f641"; } + +.fa-ad::before { + content: "\f641"; } + +.fa-circle-arrow-right::before { + content: "\f0a9"; } + +.fa-arrow-circle-right::before { + content: "\f0a9"; } + +.fa-filter-circle-xmark::before { + content: "\e17b"; } + +.fa-locust::before { + content: "\e520"; } + +.fa-sort::before { + content: "\f0dc"; } + +.fa-unsorted::before { + content: "\f0dc"; } + +.fa-list-ol::before { + content: "\f0cb"; } + +.fa-list-1-2::before { + content: "\f0cb"; } + +.fa-list-numeric::before { + content: "\f0cb"; } + +.fa-person-dress-burst::before { + content: "\e544"; } + +.fa-money-check-dollar::before { + content: "\f53d"; } + +.fa-money-check-alt::before { + content: "\f53d"; } + +.fa-vector-square::before { + content: "\f5cb"; } + +.fa-bread-slice::before { + content: "\f7ec"; } + +.fa-language::before { + content: "\f1ab"; } + +.fa-face-kiss-wink-heart::before { + content: "\f598"; } + +.fa-kiss-wink-heart::before { + content: "\f598"; } + +.fa-filter::before { + content: "\f0b0"; } + +.fa-question::before { + content: "\3f"; } + +.fa-file-signature::before { + content: "\f573"; } + +.fa-up-down-left-right::before { + content: "\f0b2"; } + +.fa-arrows-alt::before { + content: "\f0b2"; } + +.fa-house-chimney-user::before { + content: "\e065"; } + +.fa-hand-holding-heart::before { + content: "\f4be"; } + +.fa-puzzle-piece::before { + content: "\f12e"; } + +.fa-money-check::before { + content: "\f53c"; } + +.fa-star-half-stroke::before { + content: "\f5c0"; } + +.fa-star-half-alt::before { + content: "\f5c0"; } + +.fa-code::before { + content: "\f121"; } + +.fa-whiskey-glass::before { + content: "\f7a0"; } + +.fa-glass-whiskey::before { + content: "\f7a0"; } + +.fa-building-circle-exclamation::before { + content: "\e4d3"; } + +.fa-magnifying-glass-chart::before { + content: "\e522"; } + +.fa-arrow-up-right-from-square::before { + content: "\f08e"; } + +.fa-external-link::before { + content: "\f08e"; } + +.fa-cubes-stacked::before { + content: "\e4e6"; } + +.fa-won-sign::before { + content: "\f159"; } + +.fa-krw::before { + content: "\f159"; } + +.fa-won::before { + content: "\f159"; } + +.fa-virus-covid::before { + content: "\e4a8"; } + +.fa-austral-sign::before { + content: "\e0a9"; } + +.fa-f::before { + content: "\46"; } + +.fa-leaf::before { + content: "\f06c"; } + +.fa-road::before { + content: "\f018"; } + +.fa-taxi::before { + content: "\f1ba"; } + +.fa-cab::before { + content: "\f1ba"; } + +.fa-person-circle-plus::before { + content: "\e541"; } + +.fa-chart-pie::before { + content: "\f200"; } + +.fa-pie-chart::before { + content: "\f200"; } + +.fa-bolt-lightning::before { + content: "\e0b7"; } + +.fa-sack-xmark::before { + content: "\e56a"; } + +.fa-file-excel::before { + content: "\f1c3"; } + +.fa-file-contract::before { + content: "\f56c"; } + +.fa-fish-fins::before { + content: "\e4f2"; } + +.fa-building-flag::before { + content: "\e4d5"; } + +.fa-face-grin-beam::before { + content: "\f582"; } + +.fa-grin-beam::before { + content: "\f582"; } + +.fa-object-ungroup::before { + content: "\f248"; } + +.fa-poop::before { + content: "\f619"; } + +.fa-location-pin::before { + content: "\f041"; } + +.fa-map-marker::before { + content: "\f041"; } + +.fa-kaaba::before { + content: "\f66b"; } + +.fa-toilet-paper::before { + content: "\f71e"; } + +.fa-helmet-safety::before { + content: "\f807"; } + +.fa-hard-hat::before { + content: "\f807"; } + +.fa-hat-hard::before { + content: "\f807"; } + +.fa-eject::before { + content: "\f052"; } + +.fa-circle-right::before { + content: "\f35a"; } + +.fa-arrow-alt-circle-right::before { + content: "\f35a"; } + +.fa-plane-circle-check::before { + content: "\e555"; } + +.fa-face-rolling-eyes::before { + content: "\f5a5"; } + +.fa-meh-rolling-eyes::before { + content: "\f5a5"; } + +.fa-object-group::before { + content: "\f247"; } + +.fa-chart-line::before { + content: "\f201"; } + +.fa-line-chart::before { + content: "\f201"; } + +.fa-mask-ventilator::before { + content: "\e524"; } + +.fa-arrow-right::before { + content: "\f061"; } + +.fa-signs-post::before { + content: "\f277"; } + +.fa-map-signs::before { + content: "\f277"; } + +.fa-cash-register::before { + content: "\f788"; } + +.fa-person-circle-question::before { + content: "\e542"; } + +.fa-h::before { + content: "\48"; } + +.fa-tarp::before { + content: "\e57b"; } + +.fa-screwdriver-wrench::before { + content: "\f7d9"; } + +.fa-tools::before { + content: "\f7d9"; } + +.fa-arrows-to-eye::before { + content: "\e4bf"; } + +.fa-plug-circle-bolt::before { + content: "\e55b"; } + +.fa-heart::before { + content: "\f004"; } + +.fa-mars-and-venus::before { + content: "\f224"; } + +.fa-house-user::before { + content: "\e1b0"; } + +.fa-home-user::before { + content: "\e1b0"; } + +.fa-dumpster-fire::before { + content: "\f794"; } + +.fa-house-crack::before { + content: "\e3b1"; } + +.fa-martini-glass-citrus::before { + content: "\f561"; } + +.fa-cocktail::before { + content: "\f561"; } + +.fa-face-surprise::before { + content: "\f5c2"; } + +.fa-surprise::before { + content: "\f5c2"; } + +.fa-bottle-water::before { + content: "\e4c5"; } + +.fa-circle-pause::before { + content: "\f28b"; } + +.fa-pause-circle::before { + content: "\f28b"; } + +.fa-toilet-paper-slash::before { + content: "\e072"; } + +.fa-apple-whole::before { + content: "\f5d1"; } + +.fa-apple-alt::before { + content: "\f5d1"; } + +.fa-kitchen-set::before { + content: "\e51a"; } + +.fa-r::before { + content: "\52"; } + +.fa-temperature-quarter::before { + content: "\f2ca"; } + +.fa-temperature-1::before { + content: "\f2ca"; } + +.fa-thermometer-1::before { + content: "\f2ca"; } + +.fa-thermometer-quarter::before { + content: "\f2ca"; } + +.fa-cube::before { + content: "\f1b2"; } + +.fa-bitcoin-sign::before { + content: "\e0b4"; } + +.fa-shield-dog::before { + content: "\e573"; } + +.fa-solar-panel::before { + content: "\f5ba"; } + +.fa-lock-open::before { + content: "\f3c1"; } + +.fa-elevator::before { + content: "\e16d"; } + +.fa-money-bill-transfer::before { + content: "\e528"; } + +.fa-money-bill-trend-up::before { + content: "\e529"; } + +.fa-house-flood-water-circle-arrow-right::before { + content: "\e50f"; } + +.fa-square-poll-horizontal::before { + content: "\f682"; } + +.fa-poll-h::before { + content: "\f682"; } + +.fa-circle::before { + content: "\f111"; } + +.fa-backward-fast::before { + content: "\f049"; } + +.fa-fast-backward::before { + content: "\f049"; } + +.fa-recycle::before { + content: "\f1b8"; } + +.fa-user-astronaut::before { + content: "\f4fb"; } + +.fa-plane-slash::before { + content: "\e069"; } + +.fa-trademark::before { + content: "\f25c"; } + +.fa-basketball::before { + content: "\f434"; } + +.fa-basketball-ball::before { + content: "\f434"; } + +.fa-satellite-dish::before { + content: "\f7c0"; } + +.fa-circle-up::before { + content: "\f35b"; } + +.fa-arrow-alt-circle-up::before { + content: "\f35b"; } + +.fa-mobile-screen-button::before { + content: "\f3cd"; } + +.fa-mobile-alt::before { + content: "\f3cd"; } + +.fa-volume-high::before { + content: "\f028"; } + +.fa-volume-up::before { + content: "\f028"; } + +.fa-users-rays::before { + content: "\e593"; } + +.fa-wallet::before { + content: "\f555"; } + +.fa-clipboard-check::before { + content: "\f46c"; } + +.fa-file-audio::before { + content: "\f1c7"; } + +.fa-burger::before { + content: "\f805"; } + +.fa-hamburger::before { + content: "\f805"; } + +.fa-wrench::before { + content: "\f0ad"; } + +.fa-bugs::before { + content: "\e4d0"; } + +.fa-rupee-sign::before { + content: "\f156"; } + +.fa-rupee::before { + content: "\f156"; } + +.fa-file-image::before { + content: "\f1c5"; } + +.fa-circle-question::before { + content: "\f059"; } + +.fa-question-circle::before { + content: "\f059"; } + +.fa-plane-departure::before { + content: "\f5b0"; } + +.fa-handshake-slash::before { + content: "\e060"; } + +.fa-book-bookmark::before { + content: "\e0bb"; } + +.fa-code-branch::before { + content: "\f126"; } + +.fa-hat-cowboy::before { + content: "\f8c0"; } + +.fa-bridge::before { + content: "\e4c8"; } + +.fa-phone-flip::before { + content: "\f879"; } + +.fa-phone-alt::before { + content: "\f879"; } + +.fa-truck-front::before { + content: "\e2b7"; } + +.fa-cat::before { + content: "\f6be"; } + +.fa-anchor-circle-exclamation::before { + content: "\e4ab"; } + +.fa-truck-field::before { + content: "\e58d"; } + +.fa-route::before { + content: "\f4d7"; } + +.fa-clipboard-question::before { + content: "\e4e3"; } + +.fa-panorama::before { + content: "\e209"; } + +.fa-comment-medical::before { + content: "\f7f5"; } + +.fa-teeth-open::before { + content: "\f62f"; } + +.fa-file-circle-minus::before { + content: "\e4ed"; } + +.fa-tags::before { + content: "\f02c"; } + +.fa-wine-glass::before { + content: "\f4e3"; } + +.fa-forward-fast::before { + content: "\f050"; } + +.fa-fast-forward::before { + content: "\f050"; } + +.fa-face-meh-blank::before { + content: "\f5a4"; } + +.fa-meh-blank::before { + content: "\f5a4"; } + +.fa-square-parking::before { + content: "\f540"; } + +.fa-parking::before { + content: "\f540"; } + +.fa-house-signal::before { + content: "\e012"; } + +.fa-bars-progress::before { + content: "\f828"; } + +.fa-tasks-alt::before { + content: "\f828"; } + +.fa-faucet-drip::before { + content: "\e006"; } + +.fa-cart-flatbed::before { + content: "\f474"; } + +.fa-dolly-flatbed::before { + content: "\f474"; } + +.fa-ban-smoking::before { + content: "\f54d"; } + +.fa-smoking-ban::before { + content: "\f54d"; } + +.fa-terminal::before { + content: "\f120"; } + +.fa-mobile-button::before { + content: "\f10b"; } + +.fa-house-medical-flag::before { + content: "\e514"; } + +.fa-basket-shopping::before { + content: "\f291"; } + +.fa-shopping-basket::before { + content: "\f291"; } + +.fa-tape::before { + content: "\f4db"; } + +.fa-bus-simple::before { + content: "\f55e"; } + +.fa-bus-alt::before { + content: "\f55e"; } + +.fa-eye::before { + content: "\f06e"; } + +.fa-face-sad-cry::before { + content: "\f5b3"; } + +.fa-sad-cry::before { + content: "\f5b3"; } + +.fa-audio-description::before { + content: "\f29e"; } + +.fa-person-military-to-person::before { + content: "\e54c"; } + +.fa-file-shield::before { + content: "\e4f0"; } + +.fa-user-slash::before { + content: "\f506"; } + +.fa-pen::before { + content: "\f304"; } + +.fa-tower-observation::before { + content: "\e586"; } + +.fa-file-code::before { + content: "\f1c9"; } + +.fa-signal::before { + content: "\f012"; } + +.fa-signal-5::before { + content: "\f012"; } + +.fa-signal-perfect::before { + content: "\f012"; } + +.fa-bus::before { + content: "\f207"; } + +.fa-heart-circle-xmark::before { + content: "\e501"; } + +.fa-house-chimney::before { + content: "\e3af"; } + +.fa-home-lg::before { + content: "\e3af"; } + +.fa-window-maximize::before { + content: "\f2d0"; } + +.fa-face-frown::before { + content: "\f119"; } + +.fa-frown::before { + content: "\f119"; } + +.fa-prescription::before { + content: "\f5b1"; } + +.fa-shop::before { + content: "\f54f"; } + +.fa-store-alt::before { + content: "\f54f"; } + +.fa-floppy-disk::before { + content: "\f0c7"; } + +.fa-save::before { + content: "\f0c7"; } + +.fa-vihara::before { + content: "\f6a7"; } + +.fa-scale-unbalanced::before { + content: "\f515"; } + +.fa-balance-scale-left::before { + content: "\f515"; } + +.fa-sort-up::before { + content: "\f0de"; } + +.fa-sort-asc::before { + content: "\f0de"; } + +.fa-comment-dots::before { + content: "\f4ad"; } + +.fa-commenting::before { + content: "\f4ad"; } + +.fa-plant-wilt::before { + content: "\e5aa"; } + +.fa-diamond::before { + content: "\f219"; } + +.fa-face-grin-squint::before { + content: "\f585"; } + +.fa-grin-squint::before { + content: "\f585"; } + +.fa-hand-holding-dollar::before { + content: "\f4c0"; } + +.fa-hand-holding-usd::before { + content: "\f4c0"; } + +.fa-bacterium::before { + content: "\e05a"; } + +.fa-hand-pointer::before { + content: "\f25a"; } + +.fa-drum-steelpan::before { + content: "\f56a"; } + +.fa-hand-scissors::before { + content: "\f257"; } + +.fa-hands-praying::before { + content: "\f684"; } + +.fa-praying-hands::before { + content: "\f684"; } + +.fa-arrow-rotate-right::before { + content: "\f01e"; } + +.fa-arrow-right-rotate::before { + content: "\f01e"; } + +.fa-arrow-rotate-forward::before { + content: "\f01e"; } + +.fa-redo::before { + content: "\f01e"; } + +.fa-biohazard::before { + content: "\f780"; } + +.fa-location-crosshairs::before { + content: "\f601"; } + +.fa-location::before { + content: "\f601"; } + +.fa-mars-double::before { + content: "\f227"; } + +.fa-child-dress::before { + content: "\e59c"; } + +.fa-users-between-lines::before { + content: "\e591"; } + +.fa-lungs-virus::before { + content: "\e067"; } + +.fa-face-grin-tears::before { + content: "\f588"; } + +.fa-grin-tears::before { + content: "\f588"; } + +.fa-phone::before { + content: "\f095"; } + +.fa-calendar-xmark::before { + content: "\f273"; } + +.fa-calendar-times::before { + content: "\f273"; } + +.fa-child-reaching::before { + content: "\e59d"; } + +.fa-head-side-virus::before { + content: "\e064"; } + +.fa-user-gear::before { + content: "\f4fe"; } + +.fa-user-cog::before { + content: "\f4fe"; } + +.fa-arrow-up-1-9::before { + content: "\f163"; } + +.fa-sort-numeric-up::before { + content: "\f163"; } + +.fa-door-closed::before { + content: "\f52a"; } + +.fa-shield-virus::before { + content: "\e06c"; } + +.fa-dice-six::before { + content: "\f526"; } + +.fa-mosquito-net::before { + content: "\e52c"; } + +.fa-bridge-water::before { + content: "\e4ce"; } + +.fa-person-booth::before { + content: "\f756"; } + +.fa-text-width::before { + content: "\f035"; } + +.fa-hat-wizard::before { + content: "\f6e8"; } + +.fa-pen-fancy::before { + content: "\f5ac"; } + +.fa-person-digging::before { + content: "\f85e"; } + +.fa-digging::before { + content: "\f85e"; } + +.fa-trash::before { + content: "\f1f8"; } + +.fa-gauge-simple::before { + content: "\f629"; } + +.fa-gauge-simple-med::before { + content: "\f629"; } + +.fa-tachometer-average::before { + content: "\f629"; } + +.fa-book-medical::before { + content: "\f7e6"; } + +.fa-poo::before { + content: "\f2fe"; } + +.fa-quote-right::before { + content: "\f10e"; } + +.fa-quote-right-alt::before { + content: "\f10e"; } + +.fa-shirt::before { + content: "\f553"; } + +.fa-t-shirt::before { + content: "\f553"; } + +.fa-tshirt::before { + content: "\f553"; } + +.fa-cubes::before { + content: "\f1b3"; } + +.fa-divide::before { + content: "\f529"; } + +.fa-tenge-sign::before { + content: "\f7d7"; } + +.fa-tenge::before { + content: "\f7d7"; } + +.fa-headphones::before { + content: "\f025"; } + +.fa-hands-holding::before { + content: "\f4c2"; } + +.fa-hands-clapping::before { + content: "\e1a8"; } + +.fa-republican::before { + content: "\f75e"; } + +.fa-arrow-left::before { + content: "\f060"; } + +.fa-person-circle-xmark::before { + content: "\e543"; } + +.fa-ruler::before { + content: "\f545"; } + +.fa-align-left::before { + content: "\f036"; } + +.fa-dice-d6::before { + content: "\f6d1"; } + +.fa-restroom::before { + content: "\f7bd"; } + +.fa-j::before { + content: "\4a"; } + +.fa-users-viewfinder::before { + content: "\e595"; } + +.fa-file-video::before { + content: "\f1c8"; } + +.fa-up-right-from-square::before { + content: "\f35d"; } + +.fa-external-link-alt::before { + content: "\f35d"; } + +.fa-table-cells::before { + content: "\f00a"; } + +.fa-th::before { + content: "\f00a"; } + +.fa-file-pdf::before { + content: "\f1c1"; } + +.fa-book-bible::before { + content: "\f647"; } + +.fa-bible::before { + content: "\f647"; } + +.fa-o::before { + content: "\4f"; } + +.fa-suitcase-medical::before { + content: "\f0fa"; } + +.fa-medkit::before { + content: "\f0fa"; } + +.fa-user-secret::before { + content: "\f21b"; } + +.fa-otter::before { + content: "\f700"; } + +.fa-person-dress::before { + content: "\f182"; } + +.fa-female::before { + content: "\f182"; } + +.fa-comment-dollar::before { + content: "\f651"; } + +.fa-business-time::before { + content: "\f64a"; } + +.fa-briefcase-clock::before { + content: "\f64a"; } + +.fa-table-cells-large::before { + content: "\f009"; } + +.fa-th-large::before { + content: "\f009"; } + +.fa-book-tanakh::before { + content: "\f827"; } + +.fa-tanakh::before { + content: "\f827"; } + +.fa-phone-volume::before { + content: "\f2a0"; } + +.fa-volume-control-phone::before { + content: "\f2a0"; } + +.fa-hat-cowboy-side::before { + content: "\f8c1"; } + +.fa-clipboard-user::before { + content: "\f7f3"; } + +.fa-child::before { + content: "\f1ae"; } + +.fa-lira-sign::before { + content: "\f195"; } + +.fa-satellite::before { + content: "\f7bf"; } + +.fa-plane-lock::before { + content: "\e558"; } + +.fa-tag::before { + content: "\f02b"; } + +.fa-comment::before { + content: "\f075"; } + +.fa-cake-candles::before { + content: "\f1fd"; } + +.fa-birthday-cake::before { + content: "\f1fd"; } + +.fa-cake::before { + content: "\f1fd"; } + +.fa-envelope::before { + content: "\f0e0"; } + +.fa-angles-up::before { + content: "\f102"; } + +.fa-angle-double-up::before { + content: "\f102"; } + +.fa-paperclip::before { + content: "\f0c6"; } + +.fa-arrow-right-to-city::before { + content: "\e4b3"; } + +.fa-ribbon::before { + content: "\f4d6"; } + +.fa-lungs::before { + content: "\f604"; } + +.fa-arrow-up-9-1::before { + content: "\f887"; } + +.fa-sort-numeric-up-alt::before { + content: "\f887"; } + +.fa-litecoin-sign::before { + content: "\e1d3"; } + +.fa-border-none::before { + content: "\f850"; } + +.fa-circle-nodes::before { + content: "\e4e2"; } + +.fa-parachute-box::before { + content: "\f4cd"; } + +.fa-indent::before { + content: "\f03c"; } + +.fa-truck-field-un::before { + content: "\e58e"; } + +.fa-hourglass::before { + content: "\f254"; } + +.fa-hourglass-empty::before { + content: "\f254"; } + +.fa-mountain::before { + content: "\f6fc"; } + +.fa-user-doctor::before { + content: "\f0f0"; } + +.fa-user-md::before { + content: "\f0f0"; } + +.fa-circle-info::before { + content: "\f05a"; } + +.fa-info-circle::before { + content: "\f05a"; } + +.fa-cloud-meatball::before { + content: "\f73b"; } + +.fa-camera::before { + content: "\f030"; } + +.fa-camera-alt::before { + content: "\f030"; } + +.fa-square-virus::before { + content: "\e578"; } + +.fa-meteor::before { + content: "\f753"; } + +.fa-car-on::before { + content: "\e4dd"; } + +.fa-sleigh::before { + content: "\f7cc"; } + +.fa-arrow-down-1-9::before { + content: "\f162"; } + +.fa-sort-numeric-asc::before { + content: "\f162"; } + +.fa-sort-numeric-down::before { + content: "\f162"; } + +.fa-hand-holding-droplet::before { + content: "\f4c1"; } + +.fa-hand-holding-water::before { + content: "\f4c1"; } + +.fa-water::before { + content: "\f773"; } + +.fa-calendar-check::before { + content: "\f274"; } + +.fa-braille::before { + content: "\f2a1"; } + +.fa-prescription-bottle-medical::before { + content: "\f486"; } + +.fa-prescription-bottle-alt::before { + content: "\f486"; } + +.fa-landmark::before { + content: "\f66f"; } + +.fa-truck::before { + content: "\f0d1"; } + +.fa-crosshairs::before { + content: "\f05b"; } + +.fa-person-cane::before { + content: "\e53c"; } + +.fa-tent::before { + content: "\e57d"; } + +.fa-vest-patches::before { + content: "\e086"; } + +.fa-check-double::before { + content: "\f560"; } + +.fa-arrow-down-a-z::before { + content: "\f15d"; } + +.fa-sort-alpha-asc::before { + content: "\f15d"; } + +.fa-sort-alpha-down::before { + content: "\f15d"; } + +.fa-money-bill-wheat::before { + content: "\e52a"; } + +.fa-cookie::before { + content: "\f563"; } + +.fa-arrow-rotate-left::before { + content: "\f0e2"; } + +.fa-arrow-left-rotate::before { + content: "\f0e2"; } + +.fa-arrow-rotate-back::before { + content: "\f0e2"; } + +.fa-arrow-rotate-backward::before { + content: "\f0e2"; } + +.fa-undo::before { + content: "\f0e2"; } + +.fa-hard-drive::before { + content: "\f0a0"; } + +.fa-hdd::before { + content: "\f0a0"; } + +.fa-face-grin-squint-tears::before { + content: "\f586"; } + +.fa-grin-squint-tears::before { + content: "\f586"; } + +.fa-dumbbell::before { + content: "\f44b"; } + +.fa-rectangle-list::before { + content: "\f022"; } + +.fa-list-alt::before { + content: "\f022"; } + +.fa-tarp-droplet::before { + content: "\e57c"; } + +.fa-house-medical-circle-check::before { + content: "\e511"; } + +.fa-person-skiing-nordic::before { + content: "\f7ca"; } + +.fa-skiing-nordic::before { + content: "\f7ca"; } + +.fa-calendar-plus::before { + content: "\f271"; } + +.fa-plane-arrival::before { + content: "\f5af"; } + +.fa-circle-left::before { + content: "\f359"; } + +.fa-arrow-alt-circle-left::before { + content: "\f359"; } + +.fa-train-subway::before { + content: "\f239"; } + +.fa-subway::before { + content: "\f239"; } + +.fa-chart-gantt::before { + content: "\e0e4"; } + +.fa-indian-rupee-sign::before { + content: "\e1bc"; } + +.fa-indian-rupee::before { + content: "\e1bc"; } + +.fa-inr::before { + content: "\e1bc"; } + +.fa-crop-simple::before { + content: "\f565"; } + +.fa-crop-alt::before { + content: "\f565"; } + +.fa-money-bill-1::before { + content: "\f3d1"; } + +.fa-money-bill-alt::before { + content: "\f3d1"; } + +.fa-left-long::before { + content: "\f30a"; } + +.fa-long-arrow-alt-left::before { + content: "\f30a"; } + +.fa-dna::before { + content: "\f471"; } + +.fa-virus-slash::before { + content: "\e075"; } + +.fa-minus::before { + content: "\f068"; } + +.fa-subtract::before { + content: "\f068"; } + +.fa-chess::before { + content: "\f439"; } + +.fa-arrow-left-long::before { + content: "\f177"; } + +.fa-long-arrow-left::before { + content: "\f177"; } + +.fa-plug-circle-check::before { + content: "\e55c"; } + +.fa-street-view::before { + content: "\f21d"; } + +.fa-franc-sign::before { + content: "\e18f"; } + +.fa-volume-off::before { + content: "\f026"; } + +.fa-hands-asl-interpreting::before { + content: "\f2a3"; } + +.fa-american-sign-language-interpreting::before { + content: "\f2a3"; } + +.fa-asl-interpreting::before { + content: "\f2a3"; } + +.fa-hands-american-sign-language-interpreting::before { + content: "\f2a3"; } + +.fa-gear::before { + content: "\f013"; } + +.fa-cog::before { + content: "\f013"; } + +.fa-droplet-slash::before { + content: "\f5c7"; } + +.fa-tint-slash::before { + content: "\f5c7"; } + +.fa-mosque::before { + content: "\f678"; } + +.fa-mosquito::before { + content: "\e52b"; } + +.fa-star-of-david::before { + content: "\f69a"; } + +.fa-person-military-rifle::before { + content: "\e54b"; } + +.fa-cart-shopping::before { + content: "\f07a"; } + +.fa-shopping-cart::before { + content: "\f07a"; } + +.fa-vials::before { + content: "\f493"; } + +.fa-plug-circle-plus::before { + content: "\e55f"; } + +.fa-place-of-worship::before { + content: "\f67f"; } + +.fa-grip-vertical::before { + content: "\f58e"; } + +.fa-arrow-turn-up::before { + content: "\f148"; } + +.fa-level-up::before { + content: "\f148"; } + +.fa-u::before { + content: "\55"; } + +.fa-square-root-variable::before { + content: "\f698"; } + +.fa-square-root-alt::before { + content: "\f698"; } + +.fa-clock::before { + content: "\f017"; } + +.fa-clock-four::before { + content: "\f017"; } + +.fa-backward-step::before { + content: "\f048"; } + +.fa-step-backward::before { + content: "\f048"; } + +.fa-pallet::before { + content: "\f482"; } + +.fa-faucet::before { + content: "\e005"; } + +.fa-baseball-bat-ball::before { + content: "\f432"; } + +.fa-s::before { + content: "\53"; } + +.fa-timeline::before { + content: "\e29c"; } + +.fa-keyboard::before { + content: "\f11c"; } + +.fa-caret-down::before { + content: "\f0d7"; } + +.fa-house-chimney-medical::before { + content: "\f7f2"; } + +.fa-clinic-medical::before { + content: "\f7f2"; } + +.fa-temperature-three-quarters::before { + content: "\f2c8"; } + +.fa-temperature-3::before { + content: "\f2c8"; } + +.fa-thermometer-3::before { + content: "\f2c8"; } + +.fa-thermometer-three-quarters::before { + content: "\f2c8"; } + +.fa-mobile-screen::before { + content: "\f3cf"; } + +.fa-mobile-android-alt::before { + content: "\f3cf"; } + +.fa-plane-up::before { + content: "\e22d"; } + +.fa-piggy-bank::before { + content: "\f4d3"; } + +.fa-battery-half::before { + content: "\f242"; } + +.fa-battery-3::before { + content: "\f242"; } + +.fa-mountain-city::before { + content: "\e52e"; } + +.fa-coins::before { + content: "\f51e"; } + +.fa-khanda::before { + content: "\f66d"; } + +.fa-sliders::before { + content: "\f1de"; } + +.fa-sliders-h::before { + content: "\f1de"; } + +.fa-folder-tree::before { + content: "\f802"; } + +.fa-network-wired::before { + content: "\f6ff"; } + +.fa-map-pin::before { + content: "\f276"; } + +.fa-hamsa::before { + content: "\f665"; } + +.fa-cent-sign::before { + content: "\e3f5"; } + +.fa-flask::before { + content: "\f0c3"; } + +.fa-person-pregnant::before { + content: "\e31e"; } + +.fa-wand-sparkles::before { + content: "\f72b"; } + +.fa-ellipsis-vertical::before { + content: "\f142"; } + +.fa-ellipsis-v::before { + content: "\f142"; } + +.fa-ticket::before { + content: "\f145"; } + +.fa-power-off::before { + content: "\f011"; } + +.fa-right-long::before { + content: "\f30b"; } + +.fa-long-arrow-alt-right::before { + content: "\f30b"; } + +.fa-flag-usa::before { + content: "\f74d"; } + +.fa-laptop-file::before { + content: "\e51d"; } + +.fa-tty::before { + content: "\f1e4"; } + +.fa-teletype::before { + content: "\f1e4"; } + +.fa-diagram-next::before { + content: "\e476"; } + +.fa-person-rifle::before { + content: "\e54e"; } + +.fa-house-medical-circle-exclamation::before { + content: "\e512"; } + +.fa-closed-captioning::before { + content: "\f20a"; } + +.fa-person-hiking::before { + content: "\f6ec"; } + +.fa-hiking::before { + content: "\f6ec"; } + +.fa-venus-double::before { + content: "\f226"; } + +.fa-images::before { + content: "\f302"; } + +.fa-calculator::before { + content: "\f1ec"; } + +.fa-people-pulling::before { + content: "\e535"; } + +.fa-n::before { + content: "\4e"; } + +.fa-cable-car::before { + content: "\f7da"; } + +.fa-tram::before { + content: "\f7da"; } + +.fa-cloud-rain::before { + content: "\f73d"; } + +.fa-building-circle-xmark::before { + content: "\e4d4"; } + +.fa-ship::before { + content: "\f21a"; } + +.fa-arrows-down-to-line::before { + content: "\e4b8"; } + +.fa-download::before { + content: "\f019"; } + +.fa-face-grin::before { + content: "\f580"; } + +.fa-grin::before { + content: "\f580"; } + +.fa-delete-left::before { + content: "\f55a"; } + +.fa-backspace::before { + content: "\f55a"; } + +.fa-eye-dropper::before { + content: "\f1fb"; } + +.fa-eye-dropper-empty::before { + content: "\f1fb"; } + +.fa-eyedropper::before { + content: "\f1fb"; } + +.fa-file-circle-check::before { + content: "\e5a0"; } + +.fa-forward::before { + content: "\f04e"; } + +.fa-mobile::before { + content: "\f3ce"; } + +.fa-mobile-android::before { + content: "\f3ce"; } + +.fa-mobile-phone::before { + content: "\f3ce"; } + +.fa-face-meh::before { + content: "\f11a"; } + +.fa-meh::before { + content: "\f11a"; } + +.fa-align-center::before { + content: "\f037"; } + +.fa-book-skull::before { + content: "\f6b7"; } + +.fa-book-dead::before { + content: "\f6b7"; } + +.fa-id-card::before { + content: "\f2c2"; } + +.fa-drivers-license::before { + content: "\f2c2"; } + +.fa-outdent::before { + content: "\f03b"; } + +.fa-dedent::before { + content: "\f03b"; } + +.fa-heart-circle-exclamation::before { + content: "\e4fe"; } + +.fa-house::before { + content: "\f015"; } + +.fa-home::before { + content: "\f015"; } + +.fa-home-alt::before { + content: "\f015"; } + +.fa-home-lg-alt::before { + content: "\f015"; } + +.fa-calendar-week::before { + content: "\f784"; } + +.fa-laptop-medical::before { + content: "\f812"; } + +.fa-b::before { + content: "\42"; } + +.fa-file-medical::before { + content: "\f477"; } + +.fa-dice-one::before { + content: "\f525"; } + +.fa-kiwi-bird::before { + content: "\f535"; } + +.fa-arrow-right-arrow-left::before { + content: "\f0ec"; } + +.fa-exchange::before { + content: "\f0ec"; } + +.fa-rotate-right::before { + content: "\f2f9"; } + +.fa-redo-alt::before { + content: "\f2f9"; } + +.fa-rotate-forward::before { + content: "\f2f9"; } + +.fa-utensils::before { + content: "\f2e7"; } + +.fa-cutlery::before { + content: "\f2e7"; } + +.fa-arrow-up-wide-short::before { + content: "\f161"; } + +.fa-sort-amount-up::before { + content: "\f161"; } + +.fa-mill-sign::before { + content: "\e1ed"; } + +.fa-bowl-rice::before { + content: "\e2eb"; } + +.fa-skull::before { + content: "\f54c"; } + +.fa-tower-broadcast::before { + content: "\f519"; } + +.fa-broadcast-tower::before { + content: "\f519"; } + +.fa-truck-pickup::before { + content: "\f63c"; } + +.fa-up-long::before { + content: "\f30c"; } + +.fa-long-arrow-alt-up::before { + content: "\f30c"; } + +.fa-stop::before { + content: "\f04d"; } + +.fa-code-merge::before { + content: "\f387"; } + +.fa-upload::before { + content: "\f093"; } + +.fa-hurricane::before { + content: "\f751"; } + +.fa-mound::before { + content: "\e52d"; } + +.fa-toilet-portable::before { + content: "\e583"; } + +.fa-compact-disc::before { + content: "\f51f"; } + +.fa-file-arrow-down::before { + content: "\f56d"; } + +.fa-file-download::before { + content: "\f56d"; } + +.fa-caravan::before { + content: "\f8ff"; } + +.fa-shield-cat::before { + content: "\e572"; } + +.fa-bolt::before { + content: "\f0e7"; } + +.fa-zap::before { + content: "\f0e7"; } + +.fa-glass-water::before { + content: "\e4f4"; } + +.fa-oil-well::before { + content: "\e532"; } + +.fa-vault::before { + content: "\e2c5"; } + +.fa-mars::before { + content: "\f222"; } + +.fa-toilet::before { + content: "\f7d8"; } + +.fa-plane-circle-xmark::before { + content: "\e557"; } + +.fa-yen-sign::before { + content: "\f157"; } + +.fa-cny::before { + content: "\f157"; } + +.fa-jpy::before { + content: "\f157"; } + +.fa-rmb::before { + content: "\f157"; } + +.fa-yen::before { + content: "\f157"; } + +.fa-ruble-sign::before { + content: "\f158"; } + +.fa-rouble::before { + content: "\f158"; } + +.fa-rub::before { + content: "\f158"; } + +.fa-ruble::before { + content: "\f158"; } + +.fa-sun::before { + content: "\f185"; } + +.fa-guitar::before { + content: "\f7a6"; } + +.fa-face-laugh-wink::before { + content: "\f59c"; } + +.fa-laugh-wink::before { + content: "\f59c"; } + +.fa-horse-head::before { + content: "\f7ab"; } + +.fa-bore-hole::before { + content: "\e4c3"; } + +.fa-industry::before { + content: "\f275"; } + +.fa-circle-down::before { + content: "\f358"; } + +.fa-arrow-alt-circle-down::before { + content: "\f358"; } + +.fa-arrows-turn-to-dots::before { + content: "\e4c1"; } + +.fa-florin-sign::before { + content: "\e184"; } + +.fa-arrow-down-short-wide::before { + content: "\f884"; } + +.fa-sort-amount-desc::before { + content: "\f884"; } + +.fa-sort-amount-down-alt::before { + content: "\f884"; } + +.fa-less-than::before { + content: "\3c"; } + +.fa-angle-down::before { + content: "\f107"; } + +.fa-car-tunnel::before { + content: "\e4de"; } + +.fa-head-side-cough::before { + content: "\e061"; } + +.fa-grip-lines::before { + content: "\f7a4"; } + +.fa-thumbs-down::before { + content: "\f165"; } + +.fa-user-lock::before { + content: "\f502"; } + +.fa-arrow-right-long::before { + content: "\f178"; } + +.fa-long-arrow-right::before { + content: "\f178"; } + +.fa-anchor-circle-xmark::before { + content: "\e4ac"; } + +.fa-ellipsis::before { + content: "\f141"; } + +.fa-ellipsis-h::before { + content: "\f141"; } + +.fa-chess-pawn::before { + content: "\f443"; } + +.fa-kit-medical::before { + content: "\f479"; } + +.fa-first-aid::before { + content: "\f479"; } + +.fa-person-through-window::before { + content: "\e5a9"; } + +.fa-toolbox::before { + content: "\f552"; } + +.fa-hands-holding-circle::before { + content: "\e4fb"; } + +.fa-bug::before { + content: "\f188"; } + +.fa-credit-card::before { + content: "\f09d"; } + +.fa-credit-card-alt::before { + content: "\f09d"; } + +.fa-car::before { + content: "\f1b9"; } + +.fa-automobile::before { + content: "\f1b9"; } + +.fa-hand-holding-hand::before { + content: "\e4f7"; } + +.fa-book-open-reader::before { + content: "\f5da"; } + +.fa-book-reader::before { + content: "\f5da"; } + +.fa-mountain-sun::before { + content: "\e52f"; } + +.fa-arrows-left-right-to-line::before { + content: "\e4ba"; } + +.fa-dice-d20::before { + content: "\f6cf"; } + +.fa-truck-droplet::before { + content: "\e58c"; } + +.fa-file-circle-xmark::before { + content: "\e5a1"; } + +.fa-temperature-arrow-up::before { + content: "\e040"; } + +.fa-temperature-up::before { + content: "\e040"; } + +.fa-medal::before { + content: "\f5a2"; } + +.fa-bed::before { + content: "\f236"; } + +.fa-square-h::before { + content: "\f0fd"; } + +.fa-h-square::before { + content: "\f0fd"; } + +.fa-podcast::before { + content: "\f2ce"; } + +.fa-temperature-full::before { + content: "\f2c7"; } + +.fa-temperature-4::before { + content: "\f2c7"; } + +.fa-thermometer-4::before { + content: "\f2c7"; } + +.fa-thermometer-full::before { + content: "\f2c7"; } + +.fa-bell::before { + content: "\f0f3"; } + +.fa-superscript::before { + content: "\f12b"; } + +.fa-plug-circle-xmark::before { + content: "\e560"; } + +.fa-star-of-life::before { + content: "\f621"; } + +.fa-phone-slash::before { + content: "\f3dd"; } + +.fa-paint-roller::before { + content: "\f5aa"; } + +.fa-handshake-angle::before { + content: "\f4c4"; } + +.fa-hands-helping::before { + content: "\f4c4"; } + +.fa-location-dot::before { + content: "\f3c5"; } + +.fa-map-marker-alt::before { + content: "\f3c5"; } + +.fa-file::before { + content: "\f15b"; } + +.fa-greater-than::before { + content: "\3e"; } + +.fa-person-swimming::before { + content: "\f5c4"; } + +.fa-swimmer::before { + content: "\f5c4"; } + +.fa-arrow-down::before { + content: "\f063"; } + +.fa-droplet::before { + content: "\f043"; } + +.fa-tint::before { + content: "\f043"; } + +.fa-eraser::before { + content: "\f12d"; } + +.fa-earth-americas::before { + content: "\f57d"; } + +.fa-earth::before { + content: "\f57d"; } + +.fa-earth-america::before { + content: "\f57d"; } + +.fa-globe-americas::before { + content: "\f57d"; } + +.fa-person-burst::before { + content: "\e53b"; } + +.fa-dove::before { + content: "\f4ba"; } + +.fa-battery-empty::before { + content: "\f244"; } + +.fa-battery-0::before { + content: "\f244"; } + +.fa-socks::before { + content: "\f696"; } + +.fa-inbox::before { + content: "\f01c"; } + +.fa-section::before { + content: "\e447"; } + +.fa-gauge-high::before { + content: "\f625"; } + +.fa-tachometer-alt::before { + content: "\f625"; } + +.fa-tachometer-alt-fast::before { + content: "\f625"; } + +.fa-envelope-open-text::before { + content: "\f658"; } + +.fa-hospital::before { + content: "\f0f8"; } + +.fa-hospital-alt::before { + content: "\f0f8"; } + +.fa-hospital-wide::before { + content: "\f0f8"; } + +.fa-wine-bottle::before { + content: "\f72f"; } + +.fa-chess-rook::before { + content: "\f447"; } + +.fa-bars-staggered::before { + content: "\f550"; } + +.fa-reorder::before { + content: "\f550"; } + +.fa-stream::before { + content: "\f550"; } + +.fa-dharmachakra::before { + content: "\f655"; } + +.fa-hotdog::before { + content: "\f80f"; } + +.fa-person-walking-with-cane::before { + content: "\f29d"; } + +.fa-blind::before { + content: "\f29d"; } + +.fa-drum::before { + content: "\f569"; } + +.fa-ice-cream::before { + content: "\f810"; } + +.fa-heart-circle-bolt::before { + content: "\e4fc"; } + +.fa-fax::before { + content: "\f1ac"; } + +.fa-paragraph::before { + content: "\f1dd"; } + +.fa-check-to-slot::before { + content: "\f772"; } + +.fa-vote-yea::before { + content: "\f772"; } + +.fa-star-half::before { + content: "\f089"; } + +.fa-boxes-stacked::before { + content: "\f468"; } + +.fa-boxes::before { + content: "\f468"; } + +.fa-boxes-alt::before { + content: "\f468"; } + +.fa-link::before { + content: "\f0c1"; } + +.fa-chain::before { + content: "\f0c1"; } + +.fa-ear-listen::before { + content: "\f2a2"; } + +.fa-assistive-listening-systems::before { + content: "\f2a2"; } + +.fa-tree-city::before { + content: "\e587"; } + +.fa-play::before { + content: "\f04b"; } + +.fa-font::before { + content: "\f031"; } + +.fa-table-cells-row-lock::before { + content: "\e67a"; } + +.fa-rupiah-sign::before { + content: "\e23d"; } + +.fa-magnifying-glass::before { + content: "\f002"; } + +.fa-search::before { + content: "\f002"; } + +.fa-table-tennis-paddle-ball::before { + content: "\f45d"; } + +.fa-ping-pong-paddle-ball::before { + content: "\f45d"; } + +.fa-table-tennis::before { + content: "\f45d"; } + +.fa-person-dots-from-line::before { + content: "\f470"; } + +.fa-diagnoses::before { + content: "\f470"; } + +.fa-trash-can-arrow-up::before { + content: "\f82a"; } + +.fa-trash-restore-alt::before { + content: "\f82a"; } + +.fa-naira-sign::before { + content: "\e1f6"; } + +.fa-cart-arrow-down::before { + content: "\f218"; } + +.fa-walkie-talkie::before { + content: "\f8ef"; } + +.fa-file-pen::before { + content: "\f31c"; } + +.fa-file-edit::before { + content: "\f31c"; } + +.fa-receipt::before { + content: "\f543"; } + +.fa-square-pen::before { + content: "\f14b"; } + +.fa-pen-square::before { + content: "\f14b"; } + +.fa-pencil-square::before { + content: "\f14b"; } + +.fa-suitcase-rolling::before { + content: "\f5c1"; } + +.fa-person-circle-exclamation::before { + content: "\e53f"; } + +.fa-chevron-down::before { + content: "\f078"; } + +.fa-battery-full::before { + content: "\f240"; } + +.fa-battery::before { + content: "\f240"; } + +.fa-battery-5::before { + content: "\f240"; } + +.fa-skull-crossbones::before { + content: "\f714"; } + +.fa-code-compare::before { + content: "\e13a"; } + +.fa-list-ul::before { + content: "\f0ca"; } + +.fa-list-dots::before { + content: "\f0ca"; } + +.fa-school-lock::before { + content: "\e56f"; } + +.fa-tower-cell::before { + content: "\e585"; } + +.fa-down-long::before { + content: "\f309"; } + +.fa-long-arrow-alt-down::before { + content: "\f309"; } + +.fa-ranking-star::before { + content: "\e561"; } + +.fa-chess-king::before { + content: "\f43f"; } + +.fa-person-harassing::before { + content: "\e549"; } + +.fa-brazilian-real-sign::before { + content: "\e46c"; } + +.fa-landmark-dome::before { + content: "\f752"; } + +.fa-landmark-alt::before { + content: "\f752"; } + +.fa-arrow-up::before { + content: "\f062"; } + +.fa-tv::before { + content: "\f26c"; } + +.fa-television::before { + content: "\f26c"; } + +.fa-tv-alt::before { + content: "\f26c"; } + +.fa-shrimp::before { + content: "\e448"; } + +.fa-list-check::before { + content: "\f0ae"; } + +.fa-tasks::before { + content: "\f0ae"; } + +.fa-jug-detergent::before { + content: "\e519"; } + +.fa-circle-user::before { + content: "\f2bd"; } + +.fa-user-circle::before { + content: "\f2bd"; } + +.fa-user-shield::before { + content: "\f505"; } + +.fa-wind::before { + content: "\f72e"; } + +.fa-car-burst::before { + content: "\f5e1"; } + +.fa-car-crash::before { + content: "\f5e1"; } + +.fa-y::before { + content: "\59"; } + +.fa-person-snowboarding::before { + content: "\f7ce"; } + +.fa-snowboarding::before { + content: "\f7ce"; } + +.fa-truck-fast::before { + content: "\f48b"; } + +.fa-shipping-fast::before { + content: "\f48b"; } + +.fa-fish::before { + content: "\f578"; } + +.fa-user-graduate::before { + content: "\f501"; } + +.fa-circle-half-stroke::before { + content: "\f042"; } + +.fa-adjust::before { + content: "\f042"; } + +.fa-clapperboard::before { + content: "\e131"; } + +.fa-circle-radiation::before { + content: "\f7ba"; } + +.fa-radiation-alt::before { + content: "\f7ba"; } + +.fa-baseball::before { + content: "\f433"; } + +.fa-baseball-ball::before { + content: "\f433"; } + +.fa-jet-fighter-up::before { + content: "\e518"; } + +.fa-diagram-project::before { + content: "\f542"; } + +.fa-project-diagram::before { + content: "\f542"; } + +.fa-copy::before { + content: "\f0c5"; } + +.fa-volume-xmark::before { + content: "\f6a9"; } + +.fa-volume-mute::before { + content: "\f6a9"; } + +.fa-volume-times::before { + content: "\f6a9"; } + +.fa-hand-sparkles::before { + content: "\e05d"; } + +.fa-grip::before { + content: "\f58d"; } + +.fa-grip-horizontal::before { + content: "\f58d"; } + +.fa-share-from-square::before { + content: "\f14d"; } + +.fa-share-square::before { + content: "\f14d"; } + +.fa-child-combatant::before { + content: "\e4e0"; } + +.fa-child-rifle::before { + content: "\e4e0"; } + +.fa-gun::before { + content: "\e19b"; } + +.fa-square-phone::before { + content: "\f098"; } + +.fa-phone-square::before { + content: "\f098"; } + +.fa-plus::before { + content: "\2b"; } + +.fa-add::before { + content: "\2b"; } + +.fa-expand::before { + content: "\f065"; } + +.fa-computer::before { + content: "\e4e5"; } + +.fa-xmark::before { + content: "\f00d"; } + +.fa-close::before { + content: "\f00d"; } + +.fa-multiply::before { + content: "\f00d"; } + +.fa-remove::before { + content: "\f00d"; } + +.fa-times::before { + content: "\f00d"; } + +.fa-arrows-up-down-left-right::before { + content: "\f047"; } + +.fa-arrows::before { + content: "\f047"; } + +.fa-chalkboard-user::before { + content: "\f51c"; } + +.fa-chalkboard-teacher::before { + content: "\f51c"; } + +.fa-peso-sign::before { + content: "\e222"; } + +.fa-building-shield::before { + content: "\e4d8"; } + +.fa-baby::before { + content: "\f77c"; } + +.fa-users-line::before { + content: "\e592"; } + +.fa-quote-left::before { + content: "\f10d"; } + +.fa-quote-left-alt::before { + content: "\f10d"; } + +.fa-tractor::before { + content: "\f722"; } + +.fa-trash-arrow-up::before { + content: "\f829"; } + +.fa-trash-restore::before { + content: "\f829"; } + +.fa-arrow-down-up-lock::before { + content: "\e4b0"; } + +.fa-lines-leaning::before { + content: "\e51e"; } + +.fa-ruler-combined::before { + content: "\f546"; } + +.fa-copyright::before { + content: "\f1f9"; } + +.fa-equals::before { + content: "\3d"; } + +.fa-blender::before { + content: "\f517"; } + +.fa-teeth::before { + content: "\f62e"; } + +.fa-shekel-sign::before { + content: "\f20b"; } + +.fa-ils::before { + content: "\f20b"; } + +.fa-shekel::before { + content: "\f20b"; } + +.fa-sheqel::before { + content: "\f20b"; } + +.fa-sheqel-sign::before { + content: "\f20b"; } + +.fa-map::before { + content: "\f279"; } + +.fa-rocket::before { + content: "\f135"; } + +.fa-photo-film::before { + content: "\f87c"; } + +.fa-photo-video::before { + content: "\f87c"; } + +.fa-folder-minus::before { + content: "\f65d"; } + +.fa-store::before { + content: "\f54e"; } + +.fa-arrow-trend-up::before { + content: "\e098"; } + +.fa-plug-circle-minus::before { + content: "\e55e"; } + +.fa-sign-hanging::before { + content: "\f4d9"; } + +.fa-sign::before { + content: "\f4d9"; } + +.fa-bezier-curve::before { + content: "\f55b"; } + +.fa-bell-slash::before { + content: "\f1f6"; } + +.fa-tablet::before { + content: "\f3fb"; } + +.fa-tablet-android::before { + content: "\f3fb"; } + +.fa-school-flag::before { + content: "\e56e"; } + +.fa-fill::before { + content: "\f575"; } + +.fa-angle-up::before { + content: "\f106"; } + +.fa-drumstick-bite::before { + content: "\f6d7"; } + +.fa-holly-berry::before { + content: "\f7aa"; } + +.fa-chevron-left::before { + content: "\f053"; } + +.fa-bacteria::before { + content: "\e059"; } + +.fa-hand-lizard::before { + content: "\f258"; } + +.fa-notdef::before { + content: "\e1fe"; } + +.fa-disease::before { + content: "\f7fa"; } + +.fa-briefcase-medical::before { + content: "\f469"; } + +.fa-genderless::before { + content: "\f22d"; } + +.fa-chevron-right::before { + content: "\f054"; } + +.fa-retweet::before { + content: "\f079"; } + +.fa-car-rear::before { + content: "\f5de"; } + +.fa-car-alt::before { + content: "\f5de"; } + +.fa-pump-soap::before { + content: "\e06b"; } + +.fa-video-slash::before { + content: "\f4e2"; } + +.fa-battery-quarter::before { + content: "\f243"; } + +.fa-battery-2::before { + content: "\f243"; } + +.fa-radio::before { + content: "\f8d7"; } + +.fa-baby-carriage::before { + content: "\f77d"; } + +.fa-carriage-baby::before { + content: "\f77d"; } + +.fa-traffic-light::before { + content: "\f637"; } + +.fa-thermometer::before { + content: "\f491"; } + +.fa-vr-cardboard::before { + content: "\f729"; } + +.fa-hand-middle-finger::before { + content: "\f806"; } + +.fa-percent::before { + content: "\25"; } + +.fa-percentage::before { + content: "\25"; } + +.fa-truck-moving::before { + content: "\f4df"; } + +.fa-glass-water-droplet::before { + content: "\e4f5"; } + +.fa-display::before { + content: "\e163"; } + +.fa-face-smile::before { + content: "\f118"; } + +.fa-smile::before { + content: "\f118"; } + +.fa-thumbtack::before { + content: "\f08d"; } + +.fa-thumb-tack::before { + content: "\f08d"; } + +.fa-trophy::before { + content: "\f091"; } + +.fa-person-praying::before { + content: "\f683"; } + +.fa-pray::before { + content: "\f683"; } + +.fa-hammer::before { + content: "\f6e3"; } + +.fa-hand-peace::before { + content: "\f25b"; } + +.fa-rotate::before { + content: "\f2f1"; } + +.fa-sync-alt::before { + content: "\f2f1"; } + +.fa-spinner::before { + content: "\f110"; } + +.fa-robot::before { + content: "\f544"; } + +.fa-peace::before { + content: "\f67c"; } + +.fa-gears::before { + content: "\f085"; } + +.fa-cogs::before { + content: "\f085"; } + +.fa-warehouse::before { + content: "\f494"; } + +.fa-arrow-up-right-dots::before { + content: "\e4b7"; } + +.fa-splotch::before { + content: "\f5bc"; } + +.fa-face-grin-hearts::before { + content: "\f584"; } + +.fa-grin-hearts::before { + content: "\f584"; } + +.fa-dice-four::before { + content: "\f524"; } + +.fa-sim-card::before { + content: "\f7c4"; } + +.fa-transgender::before { + content: "\f225"; } + +.fa-transgender-alt::before { + content: "\f225"; } + +.fa-mercury::before { + content: "\f223"; } + +.fa-arrow-turn-down::before { + content: "\f149"; } + +.fa-level-down::before { + content: "\f149"; } + +.fa-person-falling-burst::before { + content: "\e547"; } + +.fa-award::before { + content: "\f559"; } + +.fa-ticket-simple::before { + content: "\f3ff"; } + +.fa-ticket-alt::before { + content: "\f3ff"; } + +.fa-building::before { + content: "\f1ad"; } + +.fa-angles-left::before { + content: "\f100"; } + +.fa-angle-double-left::before { + content: "\f100"; } + +.fa-qrcode::before { + content: "\f029"; } + +.fa-clock-rotate-left::before { + content: "\f1da"; } + +.fa-history::before { + content: "\f1da"; } + +.fa-face-grin-beam-sweat::before { + content: "\f583"; } + +.fa-grin-beam-sweat::before { + content: "\f583"; } + +.fa-file-export::before { + content: "\f56e"; } + +.fa-arrow-right-from-file::before { + content: "\f56e"; } + +.fa-shield::before { + content: "\f132"; } + +.fa-shield-blank::before { + content: "\f132"; } + +.fa-arrow-up-short-wide::before { + content: "\f885"; } + +.fa-sort-amount-up-alt::before { + content: "\f885"; } + +.fa-house-medical::before { + content: "\e3b2"; } + +.fa-golf-ball-tee::before { + content: "\f450"; } + +.fa-golf-ball::before { + content: "\f450"; } + +.fa-circle-chevron-left::before { + content: "\f137"; } + +.fa-chevron-circle-left::before { + content: "\f137"; } + +.fa-house-chimney-window::before { + content: "\e00d"; } + +.fa-pen-nib::before { + content: "\f5ad"; } + +.fa-tent-arrow-turn-left::before { + content: "\e580"; } + +.fa-tents::before { + content: "\e582"; } + +.fa-wand-magic::before { + content: "\f0d0"; } + +.fa-magic::before { + content: "\f0d0"; } + +.fa-dog::before { + content: "\f6d3"; } + +.fa-carrot::before { + content: "\f787"; } + +.fa-moon::before { + content: "\f186"; } + +.fa-wine-glass-empty::before { + content: "\f5ce"; } + +.fa-wine-glass-alt::before { + content: "\f5ce"; } + +.fa-cheese::before { + content: "\f7ef"; } + +.fa-yin-yang::before { + content: "\f6ad"; } + +.fa-music::before { + content: "\f001"; } + +.fa-code-commit::before { + content: "\f386"; } + +.fa-temperature-low::before { + content: "\f76b"; } + +.fa-person-biking::before { + content: "\f84a"; } + +.fa-biking::before { + content: "\f84a"; } + +.fa-broom::before { + content: "\f51a"; } + +.fa-shield-heart::before { + content: "\e574"; } + +.fa-gopuram::before { + content: "\f664"; } + +.fa-earth-oceania::before { + content: "\e47b"; } + +.fa-globe-oceania::before { + content: "\e47b"; } + +.fa-square-xmark::before { + content: "\f2d3"; } + +.fa-times-square::before { + content: "\f2d3"; } + +.fa-xmark-square::before { + content: "\f2d3"; } + +.fa-hashtag::before { + content: "\23"; } + +.fa-up-right-and-down-left-from-center::before { + content: "\f424"; } + +.fa-expand-alt::before { + content: "\f424"; } + +.fa-oil-can::before { + content: "\f613"; } + +.fa-t::before { + content: "\54"; } + +.fa-hippo::before { + content: "\f6ed"; } + +.fa-chart-column::before { + content: "\e0e3"; } + +.fa-infinity::before { + content: "\f534"; } + +.fa-vial-circle-check::before { + content: "\e596"; } + +.fa-person-arrow-down-to-line::before { + content: "\e538"; } + +.fa-voicemail::before { + content: "\f897"; } + +.fa-fan::before { + content: "\f863"; } + +.fa-person-walking-luggage::before { + content: "\e554"; } + +.fa-up-down::before { + content: "\f338"; } + +.fa-arrows-alt-v::before { + content: "\f338"; } + +.fa-cloud-moon-rain::before { + content: "\f73c"; } + +.fa-calendar::before { + content: "\f133"; } + +.fa-trailer::before { + content: "\e041"; } + +.fa-bahai::before { + content: "\f666"; } + +.fa-haykal::before { + content: "\f666"; } + +.fa-sd-card::before { + content: "\f7c2"; } + +.fa-dragon::before { + content: "\f6d5"; } + +.fa-shoe-prints::before { + content: "\f54b"; } + +.fa-circle-plus::before { + content: "\f055"; } + +.fa-plus-circle::before { + content: "\f055"; } + +.fa-face-grin-tongue-wink::before { + content: "\f58b"; } + +.fa-grin-tongue-wink::before { + content: "\f58b"; } + +.fa-hand-holding::before { + content: "\f4bd"; } + +.fa-plug-circle-exclamation::before { + content: "\e55d"; } + +.fa-link-slash::before { + content: "\f127"; } + +.fa-chain-broken::before { + content: "\f127"; } + +.fa-chain-slash::before { + content: "\f127"; } + +.fa-unlink::before { + content: "\f127"; } + +.fa-clone::before { + content: "\f24d"; } + +.fa-person-walking-arrow-loop-left::before { + content: "\e551"; } + +.fa-arrow-up-z-a::before { + content: "\f882"; } + +.fa-sort-alpha-up-alt::before { + content: "\f882"; } + +.fa-fire-flame-curved::before { + content: "\f7e4"; } + +.fa-fire-alt::before { + content: "\f7e4"; } + +.fa-tornado::before { + content: "\f76f"; } + +.fa-file-circle-plus::before { + content: "\e494"; } + +.fa-book-quran::before { + content: "\f687"; } + +.fa-quran::before { + content: "\f687"; } + +.fa-anchor::before { + content: "\f13d"; } + +.fa-border-all::before { + content: "\f84c"; } + +.fa-face-angry::before { + content: "\f556"; } + +.fa-angry::before { + content: "\f556"; } + +.fa-cookie-bite::before { + content: "\f564"; } + +.fa-arrow-trend-down::before { + content: "\e097"; } + +.fa-rss::before { + content: "\f09e"; } + +.fa-feed::before { + content: "\f09e"; } + +.fa-draw-polygon::before { + content: "\f5ee"; } + +.fa-scale-balanced::before { + content: "\f24e"; } + +.fa-balance-scale::before { + content: "\f24e"; } + +.fa-gauge-simple-high::before { + content: "\f62a"; } + +.fa-tachometer::before { + content: "\f62a"; } + +.fa-tachometer-fast::before { + content: "\f62a"; } + +.fa-shower::before { + content: "\f2cc"; } + +.fa-desktop::before { + content: "\f390"; } + +.fa-desktop-alt::before { + content: "\f390"; } + +.fa-m::before { + content: "\4d"; } + +.fa-table-list::before { + content: "\f00b"; } + +.fa-th-list::before { + content: "\f00b"; } + +.fa-comment-sms::before { + content: "\f7cd"; } + +.fa-sms::before { + content: "\f7cd"; } + +.fa-book::before { + content: "\f02d"; } + +.fa-user-plus::before { + content: "\f234"; } + +.fa-check::before { + content: "\f00c"; } + +.fa-battery-three-quarters::before { + content: "\f241"; } + +.fa-battery-4::before { + content: "\f241"; } + +.fa-house-circle-check::before { + content: "\e509"; } + +.fa-angle-left::before { + content: "\f104"; } + +.fa-diagram-successor::before { + content: "\e47a"; } + +.fa-truck-arrow-right::before { + content: "\e58b"; } + +.fa-arrows-split-up-and-left::before { + content: "\e4bc"; } + +.fa-hand-fist::before { + content: "\f6de"; } + +.fa-fist-raised::before { + content: "\f6de"; } + +.fa-cloud-moon::before { + content: "\f6c3"; } + +.fa-briefcase::before { + content: "\f0b1"; } + +.fa-person-falling::before { + content: "\e546"; } + +.fa-image-portrait::before { + content: "\f3e0"; } + +.fa-portrait::before { + content: "\f3e0"; } + +.fa-user-tag::before { + content: "\f507"; } + +.fa-rug::before { + content: "\e569"; } + +.fa-earth-europe::before { + content: "\f7a2"; } + +.fa-globe-europe::before { + content: "\f7a2"; } + +.fa-cart-flatbed-suitcase::before { + content: "\f59d"; } + +.fa-luggage-cart::before { + content: "\f59d"; } + +.fa-rectangle-xmark::before { + content: "\f410"; } + +.fa-rectangle-times::before { + content: "\f410"; } + +.fa-times-rectangle::before { + content: "\f410"; } + +.fa-window-close::before { + content: "\f410"; } + +.fa-baht-sign::before { + content: "\e0ac"; } + +.fa-book-open::before { + content: "\f518"; } + +.fa-book-journal-whills::before { + content: "\f66a"; } + +.fa-journal-whills::before { + content: "\f66a"; } + +.fa-handcuffs::before { + content: "\e4f8"; } + +.fa-triangle-exclamation::before { + content: "\f071"; } + +.fa-exclamation-triangle::before { + content: "\f071"; } + +.fa-warning::before { + content: "\f071"; } + +.fa-database::before { + content: "\f1c0"; } + +.fa-share::before { + content: "\f064"; } + +.fa-mail-forward::before { + content: "\f064"; } + +.fa-bottle-droplet::before { + content: "\e4c4"; } + +.fa-mask-face::before { + content: "\e1d7"; } + +.fa-hill-rockslide::before { + content: "\e508"; } + +.fa-right-left::before { + content: "\f362"; } + +.fa-exchange-alt::before { + content: "\f362"; } + +.fa-paper-plane::before { + content: "\f1d8"; } + +.fa-road-circle-exclamation::before { + content: "\e565"; } + +.fa-dungeon::before { + content: "\f6d9"; } + +.fa-align-right::before { + content: "\f038"; } + +.fa-money-bill-1-wave::before { + content: "\f53b"; } + +.fa-money-bill-wave-alt::before { + content: "\f53b"; } + +.fa-life-ring::before { + content: "\f1cd"; } + +.fa-hands::before { + content: "\f2a7"; } + +.fa-sign-language::before { + content: "\f2a7"; } + +.fa-signing::before { + content: "\f2a7"; } + +.fa-calendar-day::before { + content: "\f783"; } + +.fa-water-ladder::before { + content: "\f5c5"; } + +.fa-ladder-water::before { + content: "\f5c5"; } + +.fa-swimming-pool::before { + content: "\f5c5"; } + +.fa-arrows-up-down::before { + content: "\f07d"; } + +.fa-arrows-v::before { + content: "\f07d"; } + +.fa-face-grimace::before { + content: "\f57f"; } + +.fa-grimace::before { + content: "\f57f"; } + +.fa-wheelchair-move::before { + content: "\e2ce"; } + +.fa-wheelchair-alt::before { + content: "\e2ce"; } + +.fa-turn-down::before { + content: "\f3be"; } + +.fa-level-down-alt::before { + content: "\f3be"; } + +.fa-person-walking-arrow-right::before { + content: "\e552"; } + +.fa-square-envelope::before { + content: "\f199"; } + +.fa-envelope-square::before { + content: "\f199"; } + +.fa-dice::before { + content: "\f522"; } + +.fa-bowling-ball::before { + content: "\f436"; } + +.fa-brain::before { + content: "\f5dc"; } + +.fa-bandage::before { + content: "\f462"; } + +.fa-band-aid::before { + content: "\f462"; } + +.fa-calendar-minus::before { + content: "\f272"; } + +.fa-circle-xmark::before { + content: "\f057"; } + +.fa-times-circle::before { + content: "\f057"; } + +.fa-xmark-circle::before { + content: "\f057"; } + +.fa-gifts::before { + content: "\f79c"; } + +.fa-hotel::before { + content: "\f594"; } + +.fa-earth-asia::before { + content: "\f57e"; } + +.fa-globe-asia::before { + content: "\f57e"; } + +.fa-id-card-clip::before { + content: "\f47f"; } + +.fa-id-card-alt::before { + content: "\f47f"; } + +.fa-magnifying-glass-plus::before { + content: "\f00e"; } + +.fa-search-plus::before { + content: "\f00e"; } + +.fa-thumbs-up::before { + content: "\f164"; } + +.fa-user-clock::before { + content: "\f4fd"; } + +.fa-hand-dots::before { + content: "\f461"; } + +.fa-allergies::before { + content: "\f461"; } + +.fa-file-invoice::before { + content: "\f570"; } + +.fa-window-minimize::before { + content: "\f2d1"; } + +.fa-mug-saucer::before { + content: "\f0f4"; } + +.fa-coffee::before { + content: "\f0f4"; } + +.fa-brush::before { + content: "\f55d"; } + +.fa-mask::before { + content: "\f6fa"; } + +.fa-magnifying-glass-minus::before { + content: "\f010"; } + +.fa-search-minus::before { + content: "\f010"; } + +.fa-ruler-vertical::before { + content: "\f548"; } + +.fa-user-large::before { + content: "\f406"; } + +.fa-user-alt::before { + content: "\f406"; } + +.fa-train-tram::before { + content: "\e5b4"; } + +.fa-user-nurse::before { + content: "\f82f"; } + +.fa-syringe::before { + content: "\f48e"; } + +.fa-cloud-sun::before { + content: "\f6c4"; } + +.fa-stopwatch-20::before { + content: "\e06f"; } + +.fa-square-full::before { + content: "\f45c"; } + +.fa-magnet::before { + content: "\f076"; } + +.fa-jar::before { + content: "\e516"; } + +.fa-note-sticky::before { + content: "\f249"; } + +.fa-sticky-note::before { + content: "\f249"; } + +.fa-bug-slash::before { + content: "\e490"; } + +.fa-arrow-up-from-water-pump::before { + content: "\e4b6"; } + +.fa-bone::before { + content: "\f5d7"; } + +.fa-user-injured::before { + content: "\f728"; } + +.fa-face-sad-tear::before { + content: "\f5b4"; } + +.fa-sad-tear::before { + content: "\f5b4"; } + +.fa-plane::before { + content: "\f072"; } + +.fa-tent-arrows-down::before { + content: "\e581"; } + +.fa-exclamation::before { + content: "\21"; } + +.fa-arrows-spin::before { + content: "\e4bb"; } + +.fa-print::before { + content: "\f02f"; } + +.fa-turkish-lira-sign::before { + content: "\e2bb"; } + +.fa-try::before { + content: "\e2bb"; } + +.fa-turkish-lira::before { + content: "\e2bb"; } + +.fa-dollar-sign::before { + content: "\24"; } + +.fa-dollar::before { + content: "\24"; } + +.fa-usd::before { + content: "\24"; } + +.fa-x::before { + content: "\58"; } + +.fa-magnifying-glass-dollar::before { + content: "\f688"; } + +.fa-search-dollar::before { + content: "\f688"; } + +.fa-users-gear::before { + content: "\f509"; } + +.fa-users-cog::before { + content: "\f509"; } + +.fa-person-military-pointing::before { + content: "\e54a"; } + +.fa-building-columns::before { + content: "\f19c"; } + +.fa-bank::before { + content: "\f19c"; } + +.fa-institution::before { + content: "\f19c"; } + +.fa-museum::before { + content: "\f19c"; } + +.fa-university::before { + content: "\f19c"; } + +.fa-umbrella::before { + content: "\f0e9"; } + +.fa-trowel::before { + content: "\e589"; } + +.fa-d::before { + content: "\44"; } + +.fa-stapler::before { + content: "\e5af"; } + +.fa-masks-theater::before { + content: "\f630"; } + +.fa-theater-masks::before { + content: "\f630"; } + +.fa-kip-sign::before { + content: "\e1c4"; } + +.fa-hand-point-left::before { + content: "\f0a5"; } + +.fa-handshake-simple::before { + content: "\f4c6"; } + +.fa-handshake-alt::before { + content: "\f4c6"; } + +.fa-jet-fighter::before { + content: "\f0fb"; } + +.fa-fighter-jet::before { + content: "\f0fb"; } + +.fa-square-share-nodes::before { + content: "\f1e1"; } + +.fa-share-alt-square::before { + content: "\f1e1"; } + +.fa-barcode::before { + content: "\f02a"; } + +.fa-plus-minus::before { + content: "\e43c"; } + +.fa-video::before { + content: "\f03d"; } + +.fa-video-camera::before { + content: "\f03d"; } + +.fa-graduation-cap::before { + content: "\f19d"; } + +.fa-mortar-board::before { + content: "\f19d"; } + +.fa-hand-holding-medical::before { + content: "\e05c"; } + +.fa-person-circle-check::before { + content: "\e53e"; } + +.fa-turn-up::before { + content: "\f3bf"; } + +.fa-level-up-alt::before { + content: "\f3bf"; } + +.sr-only, +.fa-sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } + +.sr-only-focusable:not(:focus), +.fa-sr-only-focusable:not(:focus) { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } +:root, :host { + --fa-style-family-brands: 'Font Awesome 6 Brands'; + --fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; } + +@font-face { + font-family: 'Font Awesome 6 Brands'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +.fab, +.fa-brands { + font-weight: 400; } + +.fa-monero:before { + content: "\f3d0"; } + +.fa-hooli:before { + content: "\f427"; } + +.fa-yelp:before { + content: "\f1e9"; } + +.fa-cc-visa:before { + content: "\f1f0"; } + +.fa-lastfm:before { + content: "\f202"; } + +.fa-shopware:before { + content: "\f5b5"; } + +.fa-creative-commons-nc:before { + content: "\f4e8"; } + +.fa-aws:before { + content: "\f375"; } + +.fa-redhat:before { + content: "\f7bc"; } + +.fa-yoast:before { + content: "\f2b1"; } + +.fa-cloudflare:before { + content: "\e07d"; } + +.fa-ups:before { + content: "\f7e0"; } + +.fa-pixiv:before { + content: "\e640"; } + +.fa-wpexplorer:before { + content: "\f2de"; } + +.fa-dyalog:before { + content: "\f399"; } + +.fa-bity:before { + content: "\f37a"; } + +.fa-stackpath:before { + content: "\f842"; } + +.fa-buysellads:before { + content: "\f20d"; } + +.fa-first-order:before { + content: "\f2b0"; } + +.fa-modx:before { + content: "\f285"; } + +.fa-guilded:before { + content: "\e07e"; } + +.fa-vnv:before { + content: "\f40b"; } + +.fa-square-js:before { + content: "\f3b9"; } + +.fa-js-square:before { + content: "\f3b9"; } + +.fa-microsoft:before { + content: "\f3ca"; } + +.fa-qq:before { + content: "\f1d6"; } + +.fa-orcid:before { + content: "\f8d2"; } + +.fa-java:before { + content: "\f4e4"; } + +.fa-invision:before { + content: "\f7b0"; } + +.fa-creative-commons-pd-alt:before { + content: "\f4ed"; } + +.fa-centercode:before { + content: "\f380"; } + +.fa-glide-g:before { + content: "\f2a6"; } + +.fa-drupal:before { + content: "\f1a9"; } + +.fa-jxl:before { + content: "\e67b"; } + +.fa-hire-a-helper:before { + content: "\f3b0"; } + +.fa-creative-commons-by:before { + content: "\f4e7"; } + +.fa-unity:before { + content: "\e049"; } + +.fa-whmcs:before { + content: "\f40d"; } + +.fa-rocketchat:before { + content: "\f3e8"; } + +.fa-vk:before { + content: "\f189"; } + +.fa-untappd:before { + content: "\f405"; } + +.fa-mailchimp:before { + content: "\f59e"; } + +.fa-css3-alt:before { + content: "\f38b"; } + +.fa-square-reddit:before { + content: "\f1a2"; } + +.fa-reddit-square:before { + content: "\f1a2"; } + +.fa-vimeo-v:before { + content: "\f27d"; } + +.fa-contao:before { + content: "\f26d"; } + +.fa-square-font-awesome:before { + content: "\e5ad"; } + +.fa-deskpro:before { + content: "\f38f"; } + +.fa-brave:before { + content: "\e63c"; } + +.fa-sistrix:before { + content: "\f3ee"; } + +.fa-square-instagram:before { + content: "\e055"; } + +.fa-instagram-square:before { + content: "\e055"; } + +.fa-battle-net:before { + content: "\f835"; } + +.fa-the-red-yeti:before { + content: "\f69d"; } + +.fa-square-hacker-news:before { + content: "\f3af"; } + +.fa-hacker-news-square:before { + content: "\f3af"; } + +.fa-edge:before { + content: "\f282"; } + +.fa-threads:before { + content: "\e618"; } + +.fa-napster:before { + content: "\f3d2"; } + +.fa-square-snapchat:before { + content: "\f2ad"; } + +.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa-google-plus-g:before { + content: "\f0d5"; } + +.fa-artstation:before { + content: "\f77a"; } + +.fa-markdown:before { + content: "\f60f"; } + +.fa-sourcetree:before { + content: "\f7d3"; } + +.fa-google-plus:before { + content: "\f2b3"; } + +.fa-diaspora:before { + content: "\f791"; } + +.fa-foursquare:before { + content: "\f180"; } + +.fa-stack-overflow:before { + content: "\f16c"; } + +.fa-github-alt:before { + content: "\f113"; } + +.fa-phoenix-squadron:before { + content: "\f511"; } + +.fa-pagelines:before { + content: "\f18c"; } + +.fa-algolia:before { + content: "\f36c"; } + +.fa-red-river:before { + content: "\f3e3"; } + +.fa-creative-commons-sa:before { + content: "\f4ef"; } + +.fa-safari:before { + content: "\f267"; } + +.fa-google:before { + content: "\f1a0"; } + +.fa-square-font-awesome-stroke:before { + content: "\f35c"; } + +.fa-font-awesome-alt:before { + content: "\f35c"; } + +.fa-atlassian:before { + content: "\f77b"; } + +.fa-linkedin-in:before { + content: "\f0e1"; } + +.fa-digital-ocean:before { + content: "\f391"; } + +.fa-nimblr:before { + content: "\f5a8"; } + +.fa-chromecast:before { + content: "\f838"; } + +.fa-evernote:before { + content: "\f839"; } + +.fa-hacker-news:before { + content: "\f1d4"; } + +.fa-creative-commons-sampling:before { + content: "\f4f0"; } + +.fa-adversal:before { + content: "\f36a"; } + +.fa-creative-commons:before { + content: "\f25e"; } + +.fa-watchman-monitoring:before { + content: "\e087"; } + +.fa-fonticons:before { + content: "\f280"; } + +.fa-weixin:before { + content: "\f1d7"; } + +.fa-shirtsinbulk:before { + content: "\f214"; } + +.fa-codepen:before { + content: "\f1cb"; } + +.fa-git-alt:before { + content: "\f841"; } + +.fa-lyft:before { + content: "\f3c3"; } + +.fa-rev:before { + content: "\f5b2"; } + +.fa-windows:before { + content: "\f17a"; } + +.fa-wizards-of-the-coast:before { + content: "\f730"; } + +.fa-square-viadeo:before { + content: "\f2aa"; } + +.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa-meetup:before { + content: "\f2e0"; } + +.fa-centos:before { + content: "\f789"; } + +.fa-adn:before { + content: "\f170"; } + +.fa-cloudsmith:before { + content: "\f384"; } + +.fa-opensuse:before { + content: "\e62b"; } + +.fa-pied-piper-alt:before { + content: "\f1a8"; } + +.fa-square-dribbble:before { + content: "\f397"; } + +.fa-dribbble-square:before { + content: "\f397"; } + +.fa-codiepie:before { + content: "\f284"; } + +.fa-node:before { + content: "\f419"; } + +.fa-mix:before { + content: "\f3cb"; } + +.fa-steam:before { + content: "\f1b6"; } + +.fa-cc-apple-pay:before { + content: "\f416"; } + +.fa-scribd:before { + content: "\f28a"; } + +.fa-debian:before { + content: "\e60b"; } + +.fa-openid:before { + content: "\f19b"; } + +.fa-instalod:before { + content: "\e081"; } + +.fa-expeditedssl:before { + content: "\f23e"; } + +.fa-sellcast:before { + content: "\f2da"; } + +.fa-square-twitter:before { + content: "\f081"; } + +.fa-twitter-square:before { + content: "\f081"; } + +.fa-r-project:before { + content: "\f4f7"; } + +.fa-delicious:before { + content: "\f1a5"; } + +.fa-freebsd:before { + content: "\f3a4"; } + +.fa-vuejs:before { + content: "\f41f"; } + +.fa-accusoft:before { + content: "\f369"; } + +.fa-ioxhost:before { + content: "\f208"; } + +.fa-fonticons-fi:before { + content: "\f3a2"; } + +.fa-app-store:before { + content: "\f36f"; } + +.fa-cc-mastercard:before { + content: "\f1f1"; } + +.fa-itunes-note:before { + content: "\f3b5"; } + +.fa-golang:before { + content: "\e40f"; } + +.fa-kickstarter:before { + content: "\f3bb"; } + +.fa-square-kickstarter:before { + content: "\f3bb"; } + +.fa-grav:before { + content: "\f2d6"; } + +.fa-weibo:before { + content: "\f18a"; } + +.fa-uncharted:before { + content: "\e084"; } + +.fa-firstdraft:before { + content: "\f3a1"; } + +.fa-square-youtube:before { + content: "\f431"; } + +.fa-youtube-square:before { + content: "\f431"; } + +.fa-wikipedia-w:before { + content: "\f266"; } + +.fa-wpressr:before { + content: "\f3e4"; } + +.fa-rendact:before { + content: "\f3e4"; } + +.fa-angellist:before { + content: "\f209"; } + +.fa-galactic-republic:before { + content: "\f50c"; } + +.fa-nfc-directional:before { + content: "\e530"; } + +.fa-skype:before { + content: "\f17e"; } + +.fa-joget:before { + content: "\f3b7"; } + +.fa-fedora:before { + content: "\f798"; } + +.fa-stripe-s:before { + content: "\f42a"; } + +.fa-meta:before { + content: "\e49b"; } + +.fa-laravel:before { + content: "\f3bd"; } + +.fa-hotjar:before { + content: "\f3b1"; } + +.fa-bluetooth-b:before { + content: "\f294"; } + +.fa-square-letterboxd:before { + content: "\e62e"; } + +.fa-sticker-mule:before { + content: "\f3f7"; } + +.fa-creative-commons-zero:before { + content: "\f4f3"; } + +.fa-hips:before { + content: "\f452"; } + +.fa-behance:before { + content: "\f1b4"; } + +.fa-reddit:before { + content: "\f1a1"; } + +.fa-discord:before { + content: "\f392"; } + +.fa-chrome:before { + content: "\f268"; } + +.fa-app-store-ios:before { + content: "\f370"; } + +.fa-cc-discover:before { + content: "\f1f2"; } + +.fa-wpbeginner:before { + content: "\f297"; } + +.fa-confluence:before { + content: "\f78d"; } + +.fa-shoelace:before { + content: "\e60c"; } + +.fa-mdb:before { + content: "\f8ca"; } + +.fa-dochub:before { + content: "\f394"; } + +.fa-accessible-icon:before { + content: "\f368"; } + +.fa-ebay:before { + content: "\f4f4"; } + +.fa-amazon:before { + content: "\f270"; } + +.fa-unsplash:before { + content: "\e07c"; } + +.fa-yarn:before { + content: "\f7e3"; } + +.fa-square-steam:before { + content: "\f1b7"; } + +.fa-steam-square:before { + content: "\f1b7"; } + +.fa-500px:before { + content: "\f26e"; } + +.fa-square-vimeo:before { + content: "\f194"; } + +.fa-vimeo-square:before { + content: "\f194"; } + +.fa-asymmetrik:before { + content: "\f372"; } + +.fa-font-awesome:before { + content: "\f2b4"; } + +.fa-font-awesome-flag:before { + content: "\f2b4"; } + +.fa-font-awesome-logo-full:before { + content: "\f2b4"; } + +.fa-gratipay:before { + content: "\f184"; } + +.fa-apple:before { + content: "\f179"; } + +.fa-hive:before { + content: "\e07f"; } + +.fa-gitkraken:before { + content: "\f3a6"; } + +.fa-keybase:before { + content: "\f4f5"; } + +.fa-apple-pay:before { + content: "\f415"; } + +.fa-padlet:before { + content: "\e4a0"; } + +.fa-amazon-pay:before { + content: "\f42c"; } + +.fa-square-github:before { + content: "\f092"; } + +.fa-github-square:before { + content: "\f092"; } + +.fa-stumbleupon:before { + content: "\f1a4"; } + +.fa-fedex:before { + content: "\f797"; } + +.fa-phoenix-framework:before { + content: "\f3dc"; } + +.fa-shopify:before { + content: "\e057"; } + +.fa-neos:before { + content: "\f612"; } + +.fa-square-threads:before { + content: "\e619"; } + +.fa-hackerrank:before { + content: "\f5f7"; } + +.fa-researchgate:before { + content: "\f4f8"; } + +.fa-swift:before { + content: "\f8e1"; } + +.fa-angular:before { + content: "\f420"; } + +.fa-speakap:before { + content: "\f3f3"; } + +.fa-angrycreative:before { + content: "\f36e"; } + +.fa-y-combinator:before { + content: "\f23b"; } + +.fa-empire:before { + content: "\f1d1"; } + +.fa-envira:before { + content: "\f299"; } + +.fa-google-scholar:before { + content: "\e63b"; } + +.fa-square-gitlab:before { + content: "\e5ae"; } + +.fa-gitlab-square:before { + content: "\e5ae"; } + +.fa-studiovinari:before { + content: "\f3f8"; } + +.fa-pied-piper:before { + content: "\f2ae"; } + +.fa-wordpress:before { + content: "\f19a"; } + +.fa-product-hunt:before { + content: "\f288"; } + +.fa-firefox:before { + content: "\f269"; } + +.fa-linode:before { + content: "\f2b8"; } + +.fa-goodreads:before { + content: "\f3a8"; } + +.fa-square-odnoklassniki:before { + content: "\f264"; } + +.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa-jsfiddle:before { + content: "\f1cc"; } + +.fa-sith:before { + content: "\f512"; } + +.fa-themeisle:before { + content: "\f2b2"; } + +.fa-page4:before { + content: "\f3d7"; } + +.fa-hashnode:before { + content: "\e499"; } + +.fa-react:before { + content: "\f41b"; } + +.fa-cc-paypal:before { + content: "\f1f4"; } + +.fa-squarespace:before { + content: "\f5be"; } + +.fa-cc-stripe:before { + content: "\f1f5"; } + +.fa-creative-commons-share:before { + content: "\f4f2"; } + +.fa-bitcoin:before { + content: "\f379"; } + +.fa-keycdn:before { + content: "\f3ba"; } + +.fa-opera:before { + content: "\f26a"; } + +.fa-itch-io:before { + content: "\f83a"; } + +.fa-umbraco:before { + content: "\f8e8"; } + +.fa-galactic-senate:before { + content: "\f50d"; } + +.fa-ubuntu:before { + content: "\f7df"; } + +.fa-draft2digital:before { + content: "\f396"; } + +.fa-stripe:before { + content: "\f429"; } + +.fa-houzz:before { + content: "\f27c"; } + +.fa-gg:before { + content: "\f260"; } + +.fa-dhl:before { + content: "\f790"; } + +.fa-square-pinterest:before { + content: "\f0d3"; } + +.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa-xing:before { + content: "\f168"; } + +.fa-blackberry:before { + content: "\f37b"; } + +.fa-creative-commons-pd:before { + content: "\f4ec"; } + +.fa-playstation:before { + content: "\f3df"; } + +.fa-quinscape:before { + content: "\f459"; } + +.fa-less:before { + content: "\f41d"; } + +.fa-blogger-b:before { + content: "\f37d"; } + +.fa-opencart:before { + content: "\f23d"; } + +.fa-vine:before { + content: "\f1ca"; } + +.fa-signal-messenger:before { + content: "\e663"; } + +.fa-paypal:before { + content: "\f1ed"; } + +.fa-gitlab:before { + content: "\f296"; } + +.fa-typo3:before { + content: "\f42b"; } + +.fa-reddit-alien:before { + content: "\f281"; } + +.fa-yahoo:before { + content: "\f19e"; } + +.fa-dailymotion:before { + content: "\e052"; } + +.fa-affiliatetheme:before { + content: "\f36b"; } + +.fa-pied-piper-pp:before { + content: "\f1a7"; } + +.fa-bootstrap:before { + content: "\f836"; } + +.fa-odnoklassniki:before { + content: "\f263"; } + +.fa-nfc-symbol:before { + content: "\e531"; } + +.fa-mintbit:before { + content: "\e62f"; } + +.fa-ethereum:before { + content: "\f42e"; } + +.fa-speaker-deck:before { + content: "\f83c"; } + +.fa-creative-commons-nc-eu:before { + content: "\f4e9"; } + +.fa-patreon:before { + content: "\f3d9"; } + +.fa-avianex:before { + content: "\f374"; } + +.fa-ello:before { + content: "\f5f1"; } + +.fa-gofore:before { + content: "\f3a7"; } + +.fa-bimobject:before { + content: "\f378"; } + +.fa-brave-reverse:before { + content: "\e63d"; } + +.fa-facebook-f:before { + content: "\f39e"; } + +.fa-square-google-plus:before { + content: "\f0d4"; } + +.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa-web-awesome:before { + content: "\e682"; } + +.fa-mandalorian:before { + content: "\f50f"; } + +.fa-first-order-alt:before { + content: "\f50a"; } + +.fa-osi:before { + content: "\f41a"; } + +.fa-google-wallet:before { + content: "\f1ee"; } + +.fa-d-and-d-beyond:before { + content: "\f6ca"; } + +.fa-periscope:before { + content: "\f3da"; } + +.fa-fulcrum:before { + content: "\f50b"; } + +.fa-cloudscale:before { + content: "\f383"; } + +.fa-forumbee:before { + content: "\f211"; } + +.fa-mizuni:before { + content: "\f3cc"; } + +.fa-schlix:before { + content: "\f3ea"; } + +.fa-square-xing:before { + content: "\f169"; } + +.fa-xing-square:before { + content: "\f169"; } + +.fa-bandcamp:before { + content: "\f2d5"; } + +.fa-wpforms:before { + content: "\f298"; } + +.fa-cloudversify:before { + content: "\f385"; } + +.fa-usps:before { + content: "\f7e1"; } + +.fa-megaport:before { + content: "\f5a3"; } + +.fa-magento:before { + content: "\f3c4"; } + +.fa-spotify:before { + content: "\f1bc"; } + +.fa-optin-monster:before { + content: "\f23c"; } + +.fa-fly:before { + content: "\f417"; } + +.fa-aviato:before { + content: "\f421"; } + +.fa-itunes:before { + content: "\f3b4"; } + +.fa-cuttlefish:before { + content: "\f38c"; } + +.fa-blogger:before { + content: "\f37c"; } + +.fa-flickr:before { + content: "\f16e"; } + +.fa-viber:before { + content: "\f409"; } + +.fa-soundcloud:before { + content: "\f1be"; } + +.fa-digg:before { + content: "\f1a6"; } + +.fa-tencent-weibo:before { + content: "\f1d5"; } + +.fa-letterboxd:before { + content: "\e62d"; } + +.fa-symfony:before { + content: "\f83d"; } + +.fa-maxcdn:before { + content: "\f136"; } + +.fa-etsy:before { + content: "\f2d7"; } + +.fa-facebook-messenger:before { + content: "\f39f"; } + +.fa-audible:before { + content: "\f373"; } + +.fa-think-peaks:before { + content: "\f731"; } + +.fa-bilibili:before { + content: "\e3d9"; } + +.fa-erlang:before { + content: "\f39d"; } + +.fa-x-twitter:before { + content: "\e61b"; } + +.fa-cotton-bureau:before { + content: "\f89e"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-42-group:before { + content: "\e080"; } + +.fa-innosoft:before { + content: "\e080"; } + +.fa-stack-exchange:before { + content: "\f18d"; } + +.fa-elementor:before { + content: "\f430"; } + +.fa-square-pied-piper:before { + content: "\e01e"; } + +.fa-pied-piper-square:before { + content: "\e01e"; } + +.fa-creative-commons-nd:before { + content: "\f4eb"; } + +.fa-palfed:before { + content: "\f3d8"; } + +.fa-superpowers:before { + content: "\f2dd"; } + +.fa-resolving:before { + content: "\f3e7"; } + +.fa-xbox:before { + content: "\f412"; } + +.fa-square-web-awesome-stroke:before { + content: "\e684"; } + +.fa-searchengin:before { + content: "\f3eb"; } + +.fa-tiktok:before { + content: "\e07b"; } + +.fa-square-facebook:before { + content: "\f082"; } + +.fa-facebook-square:before { + content: "\f082"; } + +.fa-renren:before { + content: "\f18b"; } + +.fa-linux:before { + content: "\f17c"; } + +.fa-glide:before { + content: "\f2a5"; } + +.fa-linkedin:before { + content: "\f08c"; } + +.fa-hubspot:before { + content: "\f3b2"; } + +.fa-deploydog:before { + content: "\f38e"; } + +.fa-twitch:before { + content: "\f1e8"; } + +.fa-ravelry:before { + content: "\f2d9"; } + +.fa-mixer:before { + content: "\e056"; } + +.fa-square-lastfm:before { + content: "\f203"; } + +.fa-lastfm-square:before { + content: "\f203"; } + +.fa-vimeo:before { + content: "\f40a"; } + +.fa-mendeley:before { + content: "\f7b3"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-figma:before { + content: "\f799"; } + +.fa-creative-commons-remix:before { + content: "\f4ee"; } + +.fa-cc-amazon-pay:before { + content: "\f42d"; } + +.fa-dropbox:before { + content: "\f16b"; } + +.fa-instagram:before { + content: "\f16d"; } + +.fa-cmplid:before { + content: "\e360"; } + +.fa-upwork:before { + content: "\e641"; } + +.fa-facebook:before { + content: "\f09a"; } + +.fa-gripfire:before { + content: "\f3ac"; } + +.fa-jedi-order:before { + content: "\f50e"; } + +.fa-uikit:before { + content: "\f403"; } + +.fa-fort-awesome-alt:before { + content: "\f3a3"; } + +.fa-phabricator:before { + content: "\f3db"; } + +.fa-ussunnah:before { + content: "\f407"; } + +.fa-earlybirds:before { + content: "\f39a"; } + +.fa-trade-federation:before { + content: "\f513"; } + +.fa-autoprefixer:before { + content: "\f41c"; } + +.fa-whatsapp:before { + content: "\f232"; } + +.fa-square-upwork:before { + content: "\e67c"; } + +.fa-slideshare:before { + content: "\f1e7"; } + +.fa-google-play:before { + content: "\f3ab"; } + +.fa-viadeo:before { + content: "\f2a9"; } + +.fa-line:before { + content: "\f3c0"; } + +.fa-google-drive:before { + content: "\f3aa"; } + +.fa-servicestack:before { + content: "\f3ec"; } + +.fa-simplybuilt:before { + content: "\f215"; } + +.fa-bitbucket:before { + content: "\f171"; } + +.fa-imdb:before { + content: "\f2d8"; } + +.fa-deezer:before { + content: "\e077"; } + +.fa-raspberry-pi:before { + content: "\f7bb"; } + +.fa-jira:before { + content: "\f7b1"; } + +.fa-docker:before { + content: "\f395"; } + +.fa-screenpal:before { + content: "\e570"; } + +.fa-bluetooth:before { + content: "\f293"; } + +.fa-gitter:before { + content: "\f426"; } + +.fa-d-and-d:before { + content: "\f38d"; } + +.fa-microblog:before { + content: "\e01a"; } + +.fa-cc-diners-club:before { + content: "\f24c"; } + +.fa-gg-circle:before { + content: "\f261"; } + +.fa-pied-piper-hat:before { + content: "\f4e5"; } + +.fa-kickstarter-k:before { + content: "\f3bc"; } + +.fa-yandex:before { + content: "\f413"; } + +.fa-readme:before { + content: "\f4d5"; } + +.fa-html5:before { + content: "\f13b"; } + +.fa-sellsy:before { + content: "\f213"; } + +.fa-square-web-awesome:before { + content: "\e683"; } + +.fa-sass:before { + content: "\f41e"; } + +.fa-wirsindhandwerk:before { + content: "\e2d0"; } + +.fa-wsh:before { + content: "\e2d0"; } + +.fa-buromobelexperte:before { + content: "\f37f"; } + +.fa-salesforce:before { + content: "\f83b"; } + +.fa-octopus-deploy:before { + content: "\e082"; } + +.fa-medapps:before { + content: "\f3c6"; } + +.fa-ns8:before { + content: "\f3d5"; } + +.fa-pinterest-p:before { + content: "\f231"; } + +.fa-apper:before { + content: "\f371"; } + +.fa-fort-awesome:before { + content: "\f286"; } + +.fa-waze:before { + content: "\f83f"; } + +.fa-bluesky:before { + content: "\e671"; } + +.fa-cc-jcb:before { + content: "\f24b"; } + +.fa-snapchat:before { + content: "\f2ab"; } + +.fa-snapchat-ghost:before { + content: "\f2ab"; } + +.fa-fantasy-flight-games:before { + content: "\f6dc"; } + +.fa-rust:before { + content: "\e07a"; } + +.fa-wix:before { + content: "\f5cf"; } + +.fa-square-behance:before { + content: "\f1b5"; } + +.fa-behance-square:before { + content: "\f1b5"; } + +.fa-supple:before { + content: "\f3f9"; } + +.fa-webflow:before { + content: "\e65c"; } + +.fa-rebel:before { + content: "\f1d0"; } + +.fa-css3:before { + content: "\f13c"; } + +.fa-staylinked:before { + content: "\f3f5"; } + +.fa-kaggle:before { + content: "\f5fa"; } + +.fa-space-awesome:before { + content: "\e5ac"; } + +.fa-deviantart:before { + content: "\f1bd"; } + +.fa-cpanel:before { + content: "\f388"; } + +.fa-goodreads-g:before { + content: "\f3a9"; } + +.fa-square-git:before { + content: "\f1d2"; } + +.fa-git-square:before { + content: "\f1d2"; } + +.fa-square-tumblr:before { + content: "\f174"; } + +.fa-tumblr-square:before { + content: "\f174"; } + +.fa-trello:before { + content: "\f181"; } + +.fa-creative-commons-nc-jp:before { + content: "\f4ea"; } + +.fa-get-pocket:before { + content: "\f265"; } + +.fa-perbyte:before { + content: "\e083"; } + +.fa-grunt:before { + content: "\f3ad"; } + +.fa-weebly:before { + content: "\f5cc"; } + +.fa-connectdevelop:before { + content: "\f20e"; } + +.fa-leanpub:before { + content: "\f212"; } + +.fa-black-tie:before { + content: "\f27e"; } + +.fa-themeco:before { + content: "\f5c6"; } + +.fa-python:before { + content: "\f3e2"; } + +.fa-android:before { + content: "\f17b"; } + +.fa-bots:before { + content: "\e340"; } + +.fa-free-code-camp:before { + content: "\f2c5"; } + +.fa-hornbill:before { + content: "\f592"; } + +.fa-js:before { + content: "\f3b8"; } + +.fa-ideal:before { + content: "\e013"; } + +.fa-git:before { + content: "\f1d3"; } + +.fa-dev:before { + content: "\f6cc"; } + +.fa-sketch:before { + content: "\f7c6"; } + +.fa-yandex-international:before { + content: "\f414"; } + +.fa-cc-amex:before { + content: "\f1f3"; } + +.fa-uber:before { + content: "\f402"; } + +.fa-github:before { + content: "\f09b"; } + +.fa-php:before { + content: "\f457"; } + +.fa-alipay:before { + content: "\f642"; } + +.fa-youtube:before { + content: "\f167"; } + +.fa-skyatlas:before { + content: "\f216"; } + +.fa-firefox-browser:before { + content: "\e007"; } + +.fa-replyd:before { + content: "\f3e6"; } + +.fa-suse:before { + content: "\f7d6"; } + +.fa-jenkins:before { + content: "\f3b6"; } + +.fa-twitter:before { + content: "\f099"; } + +.fa-rockrms:before { + content: "\f3e9"; } + +.fa-pinterest:before { + content: "\f0d2"; } + +.fa-buffer:before { + content: "\f837"; } + +.fa-npm:before { + content: "\f3d4"; } + +.fa-yammer:before { + content: "\f840"; } + +.fa-btc:before { + content: "\f15a"; } + +.fa-dribbble:before { + content: "\f17d"; } + +.fa-stumbleupon-circle:before { + content: "\f1a3"; } + +.fa-internet-explorer:before { + content: "\f26b"; } + +.fa-stubber:before { + content: "\e5c7"; } + +.fa-telegram:before { + content: "\f2c6"; } + +.fa-telegram-plane:before { + content: "\f2c6"; } + +.fa-old-republic:before { + content: "\f510"; } + +.fa-odysee:before { + content: "\e5c6"; } + +.fa-square-whatsapp:before { + content: "\f40c"; } + +.fa-whatsapp-square:before { + content: "\f40c"; } + +.fa-node-js:before { + content: "\f3d3"; } + +.fa-edge-legacy:before { + content: "\e078"; } + +.fa-slack:before { + content: "\f198"; } + +.fa-slack-hash:before { + content: "\f198"; } + +.fa-medrt:before { + content: "\f3c8"; } + +.fa-usb:before { + content: "\f287"; } + +.fa-tumblr:before { + content: "\f173"; } + +.fa-vaadin:before { + content: "\f408"; } + +.fa-quora:before { + content: "\f2c4"; } + +.fa-square-x-twitter:before { + content: "\e61a"; } + +.fa-reacteurope:before { + content: "\f75d"; } + +.fa-medium:before { + content: "\f23a"; } + +.fa-medium-m:before { + content: "\f23a"; } + +.fa-amilia:before { + content: "\f36d"; } + +.fa-mixcloud:before { + content: "\f289"; } + +.fa-flipboard:before { + content: "\f44d"; } + +.fa-viacoin:before { + content: "\f237"; } + +.fa-critical-role:before { + content: "\f6c9"; } + +.fa-sitrox:before { + content: "\e44a"; } + +.fa-discourse:before { + content: "\f393"; } + +.fa-joomla:before { + content: "\f1aa"; } + +.fa-mastodon:before { + content: "\f4f6"; } + +.fa-airbnb:before { + content: "\f834"; } + +.fa-wolf-pack-battalion:before { + content: "\f514"; } + +.fa-buy-n-large:before { + content: "\f8a6"; } + +.fa-gulp:before { + content: "\f3ae"; } + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1"; } + +.fa-strava:before { + content: "\f428"; } + +.fa-ember:before { + content: "\f423"; } + +.fa-canadian-maple-leaf:before { + content: "\f785"; } + +.fa-teamspeak:before { + content: "\f4f9"; } + +.fa-pushed:before { + content: "\f3e1"; } + +.fa-wordpress-simple:before { + content: "\f411"; } + +.fa-nutritionix:before { + content: "\f3d6"; } + +.fa-wodu:before { + content: "\e088"; } + +.fa-google-pay:before { + content: "\e079"; } + +.fa-intercom:before { + content: "\f7af"; } + +.fa-zhihu:before { + content: "\f63f"; } + +.fa-korvue:before { + content: "\f42f"; } + +.fa-pix:before { + content: "\e43a"; } + +.fa-steam-symbol:before { + content: "\f3f6"; } +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; } + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } + +.far, +.fa-regular { + font-weight: 400; } +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; } + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 900; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +.fas, +.fa-solid { + font-weight: 900; } +@font-face { + font-family: 'Font Awesome 5 Brands'; + font-display: block; + font-weight: 400; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +@font-face { + font-family: 'Font Awesome 5 Free'; + font-display: block; + font-weight: 900; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +@font-face { + font-family: 'Font Awesome 5 Free'; + font-display: block; + font-weight: 400; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype"); } diff --git a/deps/font-awesome-6.5.2/css/all.min.css b/deps/font-awesome-6.5.2/css/all.min.css new file mode 100644 index 0000000..269bcee --- /dev/null +++ b/deps/font-awesome-6.5.2/css/all.min.css @@ -0,0 +1,9 @@ +/*! + * Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-classic,.fa-regular,.fa-sharp,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-duration:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,0));transform:rotate(var(--fa-rotate-angle,0))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)} + +.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{content:"\33"}.fa-4:before{content:"\34"}.fa-5:before{content:"\35"}.fa-6:before{content:"\36"}.fa-7:before{content:"\37"}.fa-8:before{content:"\38"}.fa-9:before{content:"\39"}.fa-fill-drip:before{content:"\f576"}.fa-arrows-to-circle:before{content:"\e4bd"}.fa-chevron-circle-right:before,.fa-circle-chevron-right:before{content:"\f138"}.fa-at:before{content:"\40"}.fa-trash-alt:before,.fa-trash-can:before{content:"\f2ed"}.fa-text-height:before{content:"\f034"}.fa-user-times:before,.fa-user-xmark:before{content:"\f235"}.fa-stethoscope:before{content:"\f0f1"}.fa-comment-alt:before,.fa-message:before{content:"\f27a"}.fa-info:before{content:"\f129"}.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before{content:"\f422"}.fa-explosion:before{content:"\e4e9"}.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before{content:"\f15c"}.fa-wave-square:before{content:"\f83e"}.fa-ring:before{content:"\f70b"}.fa-building-un:before{content:"\e4d9"}.fa-dice-three:before{content:"\f527"}.fa-calendar-alt:before,.fa-calendar-days:before{content:"\f073"}.fa-anchor-circle-check:before{content:"\e4aa"}.fa-building-circle-arrow-right:before{content:"\e4d1"}.fa-volleyball-ball:before,.fa-volleyball:before{content:"\f45f"}.fa-arrows-up-to-line:before{content:"\e4c2"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-circle-minus:before,.fa-minus-circle:before{content:"\f056"}.fa-door-open:before{content:"\f52b"}.fa-right-from-bracket:before,.fa-sign-out-alt:before{content:"\f2f5"}.fa-atom:before{content:"\f5d2"}.fa-soap:before{content:"\e06e"}.fa-heart-music-camera-bolt:before,.fa-icons:before{content:"\f86d"}.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before{content:"\f539"}.fa-bridge-circle-check:before{content:"\e4c9"}.fa-pump-medical:before{content:"\e06a"}.fa-fingerprint:before{content:"\f577"}.fa-hand-point-right:before{content:"\f0a4"}.fa-magnifying-glass-location:before,.fa-search-location:before{content:"\f689"}.fa-forward-step:before,.fa-step-forward:before{content:"\f051"}.fa-face-smile-beam:before,.fa-smile-beam:before{content:"\f5b8"}.fa-flag-checkered:before{content:"\f11e"}.fa-football-ball:before,.fa-football:before{content:"\f44e"}.fa-school-circle-exclamation:before{content:"\e56c"}.fa-crop:before{content:"\f125"}.fa-angle-double-down:before,.fa-angles-down:before{content:"\f103"}.fa-users-rectangle:before{content:"\e594"}.fa-people-roof:before{content:"\e537"}.fa-people-line:before{content:"\e534"}.fa-beer-mug-empty:before,.fa-beer:before{content:"\f0fc"}.fa-diagram-predecessor:before{content:"\e477"}.fa-arrow-up-long:before,.fa-long-arrow-up:before{content:"\f176"}.fa-burn:before,.fa-fire-flame-simple:before{content:"\f46a"}.fa-male:before,.fa-person:before{content:"\f183"}.fa-laptop:before{content:"\f109"}.fa-file-csv:before{content:"\f6dd"}.fa-menorah:before{content:"\f676"}.fa-truck-plane:before{content:"\e58f"}.fa-record-vinyl:before{content:"\f8d9"}.fa-face-grin-stars:before,.fa-grin-stars:before{content:"\f587"}.fa-bong:before{content:"\f55c"}.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before{content:"\f67b"}.fa-arrow-down-up-across-line:before{content:"\e4af"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f2e5"}.fa-jar-wheat:before{content:"\e517"}.fa-envelopes-bulk:before,.fa-mail-bulk:before{content:"\f674"}.fa-file-circle-exclamation:before{content:"\e4eb"}.fa-circle-h:before,.fa-hospital-symbol:before{content:"\f47e"}.fa-pager:before{content:"\f815"}.fa-address-book:before,.fa-contact-book:before{content:"\f2b9"}.fa-strikethrough:before{content:"\f0cc"}.fa-k:before{content:"\4b"}.fa-landmark-flag:before{content:"\e51c"}.fa-pencil-alt:before,.fa-pencil:before{content:"\f303"}.fa-backward:before{content:"\f04a"}.fa-caret-right:before{content:"\f0da"}.fa-comments:before{content:"\f086"}.fa-file-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-code-pull-request:before{content:"\e13c"}.fa-clipboard-list:before{content:"\f46d"}.fa-truck-loading:before,.fa-truck-ramp-box:before{content:"\f4de"}.fa-user-check:before{content:"\f4fc"}.fa-vial-virus:before{content:"\e597"}.fa-sheet-plastic:before{content:"\e571"}.fa-blog:before{content:"\f781"}.fa-user-ninja:before{content:"\f504"}.fa-person-arrow-up-from-line:before{content:"\e539"}.fa-scroll-torah:before,.fa-torah:before{content:"\f6a0"}.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before{content:"\f458"}.fa-toggle-off:before{content:"\f204"}.fa-archive:before,.fa-box-archive:before{content:"\f187"}.fa-person-drowning:before{content:"\e545"}.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before{content:"\f58a"}.fa-spray-can:before{content:"\f5bd"}.fa-truck-monster:before{content:"\f63b"}.fa-w:before{content:"\57"}.fa-earth-africa:before,.fa-globe-africa:before{content:"\f57c"}.fa-rainbow:before{content:"\f75b"}.fa-circle-notch:before{content:"\f1ce"}.fa-tablet-alt:before,.fa-tablet-screen-button:before{content:"\f3fa"}.fa-paw:before{content:"\f1b0"}.fa-cloud:before{content:"\f0c2"}.fa-trowel-bricks:before{content:"\e58a"}.fa-face-flushed:before,.fa-flushed:before{content:"\f579"}.fa-hospital-user:before{content:"\f80d"}.fa-tent-arrow-left-right:before{content:"\e57f"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-binoculars:before{content:"\f1e5"}.fa-microphone-slash:before{content:"\f131"}.fa-box-tissue:before{content:"\e05b"}.fa-motorcycle:before{content:"\f21c"}.fa-bell-concierge:before,.fa-concierge-bell:before{content:"\f562"}.fa-pen-ruler:before,.fa-pencil-ruler:before{content:"\f5ae"}.fa-people-arrows-left-right:before,.fa-people-arrows:before{content:"\e068"}.fa-mars-and-venus-burst:before{content:"\e523"}.fa-caret-square-right:before,.fa-square-caret-right:before{content:"\f152"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-sun-plant-wilt:before{content:"\e57a"}.fa-toilets-portable:before{content:"\e584"}.fa-hockey-puck:before{content:"\f453"}.fa-table:before{content:"\f0ce"}.fa-magnifying-glass-arrow-right:before{content:"\e521"}.fa-digital-tachograph:before,.fa-tachograph-digital:before{content:"\f566"}.fa-users-slash:before{content:"\e073"}.fa-clover:before{content:"\e139"}.fa-mail-reply:before,.fa-reply:before{content:"\f3e5"}.fa-star-and-crescent:before{content:"\f699"}.fa-house-fire:before{content:"\e50c"}.fa-minus-square:before,.fa-square-minus:before{content:"\f146"}.fa-helicopter:before{content:"\f533"}.fa-compass:before{content:"\f14e"}.fa-caret-square-down:before,.fa-square-caret-down:before{content:"\f150"}.fa-file-circle-question:before{content:"\e4ef"}.fa-laptop-code:before{content:"\f5fc"}.fa-swatchbook:before{content:"\f5c3"}.fa-prescription-bottle:before{content:"\f485"}.fa-bars:before,.fa-navicon:before{content:"\f0c9"}.fa-people-group:before{content:"\e533"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-heart-broken:before,.fa-heart-crack:before{content:"\f7a9"}.fa-external-link-square-alt:before,.fa-square-up-right:before{content:"\f360"}.fa-face-kiss-beam:before,.fa-kiss-beam:before{content:"\f597"}.fa-film:before{content:"\f008"}.fa-ruler-horizontal:before{content:"\f547"}.fa-people-robbery:before{content:"\e536"}.fa-lightbulb:before{content:"\f0eb"}.fa-caret-left:before{content:"\f0d9"}.fa-circle-exclamation:before,.fa-exclamation-circle:before{content:"\f06a"}.fa-school-circle-xmark:before{content:"\e56d"}.fa-arrow-right-from-bracket:before,.fa-sign-out:before{content:"\f08b"}.fa-chevron-circle-down:before,.fa-circle-chevron-down:before{content:"\f13a"}.fa-unlock-alt:before,.fa-unlock-keyhole:before{content:"\f13e"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-headphones-alt:before,.fa-headphones-simple:before{content:"\f58f"}.fa-sitemap:before{content:"\f0e8"}.fa-circle-dollar-to-slot:before,.fa-donate:before{content:"\f4b9"}.fa-memory:before{content:"\f538"}.fa-road-spikes:before{content:"\e568"}.fa-fire-burner:before{content:"\e4f1"}.fa-flag:before{content:"\f024"}.fa-hanukiah:before{content:"\f6e6"}.fa-feather:before{content:"\f52d"}.fa-volume-down:before,.fa-volume-low:before{content:"\f027"}.fa-comment-slash:before{content:"\f4b3"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-compress:before{content:"\f066"}.fa-wheat-alt:before,.fa-wheat-awn:before{content:"\e2cd"}.fa-ankh:before{content:"\f644"}.fa-hands-holding-child:before{content:"\e4fa"}.fa-asterisk:before{content:"\2a"}.fa-check-square:before,.fa-square-check:before{content:"\f14a"}.fa-peseta-sign:before{content:"\e221"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-ghost:before{content:"\f6e2"}.fa-list-squares:before,.fa-list:before{content:"\f03a"}.fa-phone-square-alt:before,.fa-square-phone-flip:before{content:"\f87b"}.fa-cart-plus:before{content:"\f217"}.fa-gamepad:before{content:"\f11b"}.fa-circle-dot:before,.fa-dot-circle:before{content:"\f192"}.fa-dizzy:before,.fa-face-dizzy:before{content:"\f567"}.fa-egg:before{content:"\f7fb"}.fa-house-medical-circle-xmark:before{content:"\e513"}.fa-campground:before{content:"\f6bb"}.fa-folder-plus:before{content:"\f65e"}.fa-futbol-ball:before,.fa-futbol:before,.fa-soccer-ball:before{content:"\f1e3"}.fa-paint-brush:before,.fa-paintbrush:before{content:"\f1fc"}.fa-lock:before{content:"\f023"}.fa-gas-pump:before{content:"\f52f"}.fa-hot-tub-person:before,.fa-hot-tub:before{content:"\f593"}.fa-map-location:before,.fa-map-marked:before{content:"\f59f"}.fa-house-flood-water:before{content:"\e50e"}.fa-tree:before{content:"\f1bb"}.fa-bridge-lock:before{content:"\e4cc"}.fa-sack-dollar:before{content:"\f81d"}.fa-edit:before,.fa-pen-to-square:before{content:"\f044"}.fa-car-side:before{content:"\f5e4"}.fa-share-alt:before,.fa-share-nodes:before{content:"\f1e0"}.fa-heart-circle-minus:before{content:"\e4ff"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-microscope:before{content:"\f610"}.fa-sink:before{content:"\e06d"}.fa-bag-shopping:before,.fa-shopping-bag:before{content:"\f290"}.fa-arrow-down-z-a:before,.fa-sort-alpha-desc:before,.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-mitten:before{content:"\f7b5"}.fa-person-rays:before{content:"\e54d"}.fa-users:before{content:"\f0c0"}.fa-eye-slash:before{content:"\f070"}.fa-flask-vial:before{content:"\e4f3"}.fa-hand-paper:before,.fa-hand:before{content:"\f256"}.fa-om:before{content:"\f679"}.fa-worm:before{content:"\e599"}.fa-house-circle-xmark:before{content:"\e50b"}.fa-plug:before{content:"\f1e6"}.fa-chevron-up:before{content:"\f077"}.fa-hand-spock:before{content:"\f259"}.fa-stopwatch:before{content:"\f2f2"}.fa-face-kiss:before,.fa-kiss:before{content:"\f596"}.fa-bridge-circle-xmark:before{content:"\e4cb"}.fa-face-grin-tongue:before,.fa-grin-tongue:before{content:"\f589"}.fa-chess-bishop:before{content:"\f43a"}.fa-face-grin-wink:before,.fa-grin-wink:before{content:"\f58c"}.fa-deaf:before,.fa-deafness:before,.fa-ear-deaf:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-road-circle-check:before{content:"\e564"}.fa-dice-five:before{content:"\f523"}.fa-rss-square:before,.fa-square-rss:before{content:"\f143"}.fa-land-mine-on:before{content:"\e51b"}.fa-i-cursor:before{content:"\f246"}.fa-stamp:before{content:"\f5bf"}.fa-stairs:before{content:"\e289"}.fa-i:before{content:"\49"}.fa-hryvnia-sign:before,.fa-hryvnia:before{content:"\f6f2"}.fa-pills:before{content:"\f484"}.fa-face-grin-wide:before,.fa-grin-alt:before{content:"\f581"}.fa-tooth:before{content:"\f5c9"}.fa-v:before{content:"\56"}.fa-bangladeshi-taka-sign:before{content:"\e2e6"}.fa-bicycle:before{content:"\f206"}.fa-rod-asclepius:before,.fa-rod-snake:before,.fa-staff-aesculapius:before,.fa-staff-snake:before{content:"\e579"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-ambulance:before,.fa-truck-medical:before{content:"\f0f9"}.fa-wheat-awn-circle-exclamation:before{content:"\e598"}.fa-snowman:before{content:"\f7d0"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-road-barrier:before{content:"\e562"}.fa-school:before{content:"\f549"}.fa-igloo:before{content:"\f7ae"}.fa-joint:before{content:"\f595"}.fa-angle-right:before{content:"\f105"}.fa-horse:before{content:"\f6f0"}.fa-q:before{content:"\51"}.fa-g:before{content:"\47"}.fa-notes-medical:before{content:"\f481"}.fa-temperature-2:before,.fa-temperature-half:before,.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-dong-sign:before{content:"\e169"}.fa-capsules:before{content:"\f46b"}.fa-poo-bolt:before,.fa-poo-storm:before{content:"\f75a"}.fa-face-frown-open:before,.fa-frown-open:before{content:"\f57a"}.fa-hand-point-up:before{content:"\f0a6"}.fa-money-bill:before{content:"\f0d6"}.fa-bookmark:before{content:"\f02e"}.fa-align-justify:before{content:"\f039"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-helmet-un:before{content:"\e503"}.fa-bullseye:before{content:"\f140"}.fa-bacon:before{content:"\f7e5"}.fa-hand-point-down:before{content:"\f0a7"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-folder-blank:before,.fa-folder:before{content:"\f07b"}.fa-file-medical-alt:before,.fa-file-waveform:before{content:"\f478"}.fa-radiation:before{content:"\f7b9"}.fa-chart-simple:before{content:"\e473"}.fa-mars-stroke:before{content:"\f229"}.fa-vial:before{content:"\f492"}.fa-dashboard:before,.fa-gauge-med:before,.fa-gauge:before,.fa-tachometer-alt-average:before{content:"\f624"}.fa-magic-wand-sparkles:before,.fa-wand-magic-sparkles:before{content:"\e2ca"}.fa-e:before{content:"\45"}.fa-pen-alt:before,.fa-pen-clip:before{content:"\f305"}.fa-bridge-circle-exclamation:before{content:"\e4ca"}.fa-user:before{content:"\f007"}.fa-school-circle-check:before{content:"\e56b"}.fa-dumpster:before{content:"\f793"}.fa-shuttle-van:before,.fa-van-shuttle:before{content:"\f5b6"}.fa-building-user:before{content:"\e4da"}.fa-caret-square-left:before,.fa-square-caret-left:before{content:"\f191"}.fa-highlighter:before{content:"\f591"}.fa-key:before{content:"\f084"}.fa-bullhorn:before{content:"\f0a1"}.fa-globe:before{content:"\f0ac"}.fa-synagogue:before{content:"\f69b"}.fa-person-half-dress:before{content:"\e548"}.fa-road-bridge:before{content:"\e563"}.fa-location-arrow:before{content:"\f124"}.fa-c:before{content:"\43"}.fa-tablet-button:before{content:"\f10a"}.fa-building-lock:before{content:"\e4d6"}.fa-pizza-slice:before{content:"\f818"}.fa-money-bill-wave:before{content:"\f53a"}.fa-area-chart:before,.fa-chart-area:before{content:"\f1fe"}.fa-house-flag:before{content:"\e50d"}.fa-person-circle-minus:before{content:"\e540"}.fa-ban:before,.fa-cancel:before{content:"\f05e"}.fa-camera-rotate:before{content:"\e0d8"}.fa-air-freshener:before,.fa-spray-can-sparkles:before{content:"\f5d0"}.fa-star:before{content:"\f005"}.fa-repeat:before{content:"\f363"}.fa-cross:before{content:"\f654"}.fa-box:before{content:"\f466"}.fa-venus-mars:before{content:"\f228"}.fa-arrow-pointer:before,.fa-mouse-pointer:before{content:"\f245"}.fa-expand-arrows-alt:before,.fa-maximize:before{content:"\f31e"}.fa-charging-station:before{content:"\f5e7"}.fa-shapes:before,.fa-triangle-circle-square:before{content:"\f61f"}.fa-random:before,.fa-shuffle:before{content:"\f074"}.fa-person-running:before,.fa-running:before{content:"\f70c"}.fa-mobile-retro:before{content:"\e527"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-spider:before{content:"\f717"}.fa-hands-bound:before{content:"\e4f9"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-plane-circle-exclamation:before{content:"\e556"}.fa-x-ray:before{content:"\f497"}.fa-spell-check:before{content:"\f891"}.fa-slash:before{content:"\f715"}.fa-computer-mouse:before,.fa-mouse:before{content:"\f8cc"}.fa-arrow-right-to-bracket:before,.fa-sign-in:before{content:"\f090"}.fa-shop-slash:before,.fa-store-alt-slash:before{content:"\e070"}.fa-server:before{content:"\f233"}.fa-virus-covid-slash:before{content:"\e4a9"}.fa-shop-lock:before{content:"\e4a5"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-blender-phone:before{content:"\f6b6"}.fa-building-wheat:before{content:"\e4db"}.fa-person-breastfeeding:before{content:"\e53a"}.fa-right-to-bracket:before,.fa-sign-in-alt:before{content:"\f2f6"}.fa-venus:before{content:"\f221"}.fa-passport:before{content:"\f5ab"}.fa-heart-pulse:before,.fa-heartbeat:before{content:"\f21e"}.fa-people-carry-box:before,.fa-people-carry:before{content:"\f4ce"}.fa-temperature-high:before{content:"\f769"}.fa-microchip:before{content:"\f2db"}.fa-crown:before{content:"\f521"}.fa-weight-hanging:before{content:"\f5cd"}.fa-xmarks-lines:before{content:"\e59a"}.fa-file-prescription:before{content:"\f572"}.fa-weight-scale:before,.fa-weight:before{content:"\f496"}.fa-user-friends:before,.fa-user-group:before{content:"\f500"}.fa-arrow-up-a-z:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-chess-knight:before{content:"\f441"}.fa-face-laugh-squint:before,.fa-laugh-squint:before{content:"\f59b"}.fa-wheelchair:before{content:"\f193"}.fa-arrow-circle-up:before,.fa-circle-arrow-up:before{content:"\f0aa"}.fa-toggle-on:before{content:"\f205"}.fa-person-walking:before,.fa-walking:before{content:"\f554"}.fa-l:before{content:"\4c"}.fa-fire:before{content:"\f06d"}.fa-bed-pulse:before,.fa-procedures:before{content:"\f487"}.fa-shuttle-space:before,.fa-space-shuttle:before{content:"\f197"}.fa-face-laugh:before,.fa-laugh:before{content:"\f599"}.fa-folder-open:before{content:"\f07c"}.fa-heart-circle-plus:before{content:"\e500"}.fa-code-fork:before{content:"\e13b"}.fa-city:before{content:"\f64f"}.fa-microphone-alt:before,.fa-microphone-lines:before{content:"\f3c9"}.fa-pepper-hot:before{content:"\f816"}.fa-unlock:before{content:"\f09c"}.fa-colon-sign:before{content:"\e140"}.fa-headset:before{content:"\f590"}.fa-store-slash:before{content:"\e071"}.fa-road-circle-xmark:before{content:"\e566"}.fa-user-minus:before{content:"\f503"}.fa-mars-stroke-up:before,.fa-mars-stroke-v:before{content:"\f22a"}.fa-champagne-glasses:before,.fa-glass-cheers:before{content:"\f79f"}.fa-clipboard:before{content:"\f328"}.fa-house-circle-exclamation:before{content:"\e50a"}.fa-file-arrow-up:before,.fa-file-upload:before{content:"\f574"}.fa-wifi-3:before,.fa-wifi-strong:before,.fa-wifi:before{content:"\f1eb"}.fa-bath:before,.fa-bathtub:before{content:"\f2cd"}.fa-underline:before{content:"\f0cd"}.fa-user-edit:before,.fa-user-pen:before{content:"\f4ff"}.fa-signature:before{content:"\f5b7"}.fa-stroopwafel:before{content:"\f551"}.fa-bold:before{content:"\f032"}.fa-anchor-lock:before{content:"\e4ad"}.fa-building-ngo:before{content:"\e4d7"}.fa-manat-sign:before{content:"\e1d5"}.fa-not-equal:before{content:"\f53e"}.fa-border-style:before,.fa-border-top-left:before{content:"\f853"}.fa-map-location-dot:before,.fa-map-marked-alt:before{content:"\f5a0"}.fa-jedi:before{content:"\f669"}.fa-poll:before,.fa-square-poll-vertical:before{content:"\f681"}.fa-mug-hot:before{content:"\f7b6"}.fa-battery-car:before,.fa-car-battery:before{content:"\f5df"}.fa-gift:before{content:"\f06b"}.fa-dice-two:before{content:"\f528"}.fa-chess-queen:before{content:"\f445"}.fa-glasses:before{content:"\f530"}.fa-chess-board:before{content:"\f43c"}.fa-building-circle-check:before{content:"\e4d2"}.fa-person-chalkboard:before{content:"\e53d"}.fa-mars-stroke-h:before,.fa-mars-stroke-right:before{content:"\f22b"}.fa-hand-back-fist:before,.fa-hand-rock:before{content:"\f255"}.fa-caret-square-up:before,.fa-square-caret-up:before{content:"\f151"}.fa-cloud-showers-water:before{content:"\e4e4"}.fa-bar-chart:before,.fa-chart-bar:before{content:"\f080"}.fa-hands-bubbles:before,.fa-hands-wash:before{content:"\e05e"}.fa-less-than-equal:before{content:"\f537"}.fa-train:before{content:"\f238"}.fa-eye-low-vision:before,.fa-low-vision:before{content:"\f2a8"}.fa-crow:before{content:"\f520"}.fa-sailboat:before{content:"\e445"}.fa-window-restore:before{content:"\f2d2"}.fa-plus-square:before,.fa-square-plus:before{content:"\f0fe"}.fa-torii-gate:before{content:"\f6a1"}.fa-frog:before{content:"\f52e"}.fa-bucket:before{content:"\e4cf"}.fa-image:before{content:"\f03e"}.fa-microphone:before{content:"\f130"}.fa-cow:before{content:"\f6c8"}.fa-caret-up:before{content:"\f0d8"}.fa-screwdriver:before{content:"\f54a"}.fa-folder-closed:before{content:"\e185"}.fa-house-tsunami:before{content:"\e515"}.fa-square-nfi:before{content:"\e576"}.fa-arrow-up-from-ground-water:before{content:"\e4b5"}.fa-glass-martini-alt:before,.fa-martini-glass:before{content:"\f57b"}.fa-rotate-back:before,.fa-rotate-backward:before,.fa-rotate-left:before,.fa-undo-alt:before{content:"\f2ea"}.fa-columns:before,.fa-table-columns:before{content:"\f0db"}.fa-lemon:before{content:"\f094"}.fa-head-side-mask:before{content:"\e063"}.fa-handshake:before{content:"\f2b5"}.fa-gem:before{content:"\f3a5"}.fa-dolly-box:before,.fa-dolly:before{content:"\f472"}.fa-smoking:before{content:"\f48d"}.fa-compress-arrows-alt:before,.fa-minimize:before{content:"\f78c"}.fa-monument:before{content:"\f5a6"}.fa-snowplow:before{content:"\f7d2"}.fa-angle-double-right:before,.fa-angles-right:before{content:"\f101"}.fa-cannabis:before{content:"\f55f"}.fa-circle-play:before,.fa-play-circle:before{content:"\f144"}.fa-tablets:before{content:"\f490"}.fa-ethernet:before{content:"\f796"}.fa-eur:before,.fa-euro-sign:before,.fa-euro:before{content:"\f153"}.fa-chair:before{content:"\f6c0"}.fa-check-circle:before,.fa-circle-check:before{content:"\f058"}.fa-circle-stop:before,.fa-stop-circle:before{content:"\f28d"}.fa-compass-drafting:before,.fa-drafting-compass:before{content:"\f568"}.fa-plate-wheat:before{content:"\e55a"}.fa-icicles:before{content:"\f7ad"}.fa-person-shelter:before{content:"\e54f"}.fa-neuter:before{content:"\f22c"}.fa-id-badge:before{content:"\f2c1"}.fa-marker:before{content:"\f5a1"}.fa-face-laugh-beam:before,.fa-laugh-beam:before{content:"\f59a"}.fa-helicopter-symbol:before{content:"\e502"}.fa-universal-access:before{content:"\f29a"}.fa-chevron-circle-up:before,.fa-circle-chevron-up:before{content:"\f139"}.fa-lari-sign:before{content:"\e1c8"}.fa-volcano:before{content:"\f770"}.fa-person-walking-dashed-line-arrow-right:before{content:"\e553"}.fa-gbp:before,.fa-pound-sign:before,.fa-sterling-sign:before{content:"\f154"}.fa-viruses:before{content:"\e076"}.fa-square-person-confined:before{content:"\e577"}.fa-user-tie:before{content:"\f508"}.fa-arrow-down-long:before,.fa-long-arrow-down:before{content:"\f175"}.fa-tent-arrow-down-to-line:before{content:"\e57e"}.fa-certificate:before{content:"\f0a3"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-suitcase:before{content:"\f0f2"}.fa-person-skating:before,.fa-skating:before{content:"\f7c5"}.fa-filter-circle-dollar:before,.fa-funnel-dollar:before{content:"\f662"}.fa-camera-retro:before{content:"\f083"}.fa-arrow-circle-down:before,.fa-circle-arrow-down:before{content:"\f0ab"}.fa-arrow-right-to-file:before,.fa-file-import:before{content:"\f56f"}.fa-external-link-square:before,.fa-square-arrow-up-right:before{content:"\f14c"}.fa-box-open:before{content:"\f49e"}.fa-scroll:before{content:"\f70e"}.fa-spa:before{content:"\f5bb"}.fa-location-pin-lock:before{content:"\e51f"}.fa-pause:before{content:"\f04c"}.fa-hill-avalanche:before{content:"\e507"}.fa-temperature-0:before,.fa-temperature-empty:before,.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-bomb:before{content:"\f1e2"}.fa-registered:before{content:"\f25d"}.fa-address-card:before,.fa-contact-card:before,.fa-vcard:before{content:"\f2bb"}.fa-balance-scale-right:before,.fa-scale-unbalanced-flip:before{content:"\f516"}.fa-subscript:before{content:"\f12c"}.fa-diamond-turn-right:before,.fa-directions:before{content:"\f5eb"}.fa-burst:before{content:"\e4dc"}.fa-house-laptop:before,.fa-laptop-house:before{content:"\e066"}.fa-face-tired:before,.fa-tired:before{content:"\f5c8"}.fa-money-bills:before{content:"\e1f3"}.fa-smog:before{content:"\f75f"}.fa-crutch:before{content:"\f7f7"}.fa-cloud-arrow-up:before,.fa-cloud-upload-alt:before,.fa-cloud-upload:before{content:"\f0ee"}.fa-palette:before{content:"\f53f"}.fa-arrows-turn-right:before{content:"\e4c0"}.fa-vest:before{content:"\e085"}.fa-ferry:before{content:"\e4ea"}.fa-arrows-down-to-people:before{content:"\e4b9"}.fa-seedling:before,.fa-sprout:before{content:"\f4d8"}.fa-arrows-alt-h:before,.fa-left-right:before{content:"\f337"}.fa-boxes-packing:before{content:"\e4c7"}.fa-arrow-circle-left:before,.fa-circle-arrow-left:before{content:"\f0a8"}.fa-group-arrows-rotate:before{content:"\e4f6"}.fa-bowl-food:before{content:"\e4c6"}.fa-candy-cane:before{content:"\f786"}.fa-arrow-down-wide-short:before,.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-cloud-bolt:before,.fa-thunderstorm:before{content:"\f76c"}.fa-remove-format:before,.fa-text-slash:before{content:"\f87d"}.fa-face-smile-wink:before,.fa-smile-wink:before{content:"\f4da"}.fa-file-word:before{content:"\f1c2"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-arrows-h:before,.fa-arrows-left-right:before{content:"\f07e"}.fa-house-lock:before{content:"\e510"}.fa-cloud-arrow-down:before,.fa-cloud-download-alt:before,.fa-cloud-download:before{content:"\f0ed"}.fa-children:before{content:"\e4e1"}.fa-blackboard:before,.fa-chalkboard:before{content:"\f51b"}.fa-user-alt-slash:before,.fa-user-large-slash:before{content:"\f4fa"}.fa-envelope-open:before{content:"\f2b6"}.fa-handshake-alt-slash:before,.fa-handshake-simple-slash:before{content:"\e05f"}.fa-mattress-pillow:before{content:"\e525"}.fa-guarani-sign:before{content:"\e19a"}.fa-arrows-rotate:before,.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-fire-extinguisher:before{content:"\f134"}.fa-cruzeiro-sign:before{content:"\e152"}.fa-greater-than-equal:before{content:"\f532"}.fa-shield-alt:before,.fa-shield-halved:before{content:"\f3ed"}.fa-atlas:before,.fa-book-atlas:before{content:"\f558"}.fa-virus:before{content:"\e074"}.fa-envelope-circle-check:before{content:"\e4e8"}.fa-layer-group:before{content:"\f5fd"}.fa-arrows-to-dot:before{content:"\e4be"}.fa-archway:before{content:"\f557"}.fa-heart-circle-check:before{content:"\e4fd"}.fa-house-chimney-crack:before,.fa-house-damage:before{content:"\f6f1"}.fa-file-archive:before,.fa-file-zipper:before{content:"\f1c6"}.fa-square:before{content:"\f0c8"}.fa-glass-martini:before,.fa-martini-glass-empty:before{content:"\f000"}.fa-couch:before{content:"\f4b8"}.fa-cedi-sign:before{content:"\e0df"}.fa-italic:before{content:"\f033"}.fa-table-cells-column-lock:before{content:"\e678"}.fa-church:before{content:"\f51d"}.fa-comments-dollar:before{content:"\f653"}.fa-democrat:before{content:"\f747"}.fa-z:before{content:"\5a"}.fa-person-skiing:before,.fa-skiing:before{content:"\f7c9"}.fa-road-lock:before{content:"\e567"}.fa-a:before{content:"\41"}.fa-temperature-arrow-down:before,.fa-temperature-down:before{content:"\e03f"}.fa-feather-alt:before,.fa-feather-pointed:before{content:"\f56b"}.fa-p:before{content:"\50"}.fa-snowflake:before{content:"\f2dc"}.fa-newspaper:before{content:"\f1ea"}.fa-ad:before,.fa-rectangle-ad:before{content:"\f641"}.fa-arrow-circle-right:before,.fa-circle-arrow-right:before{content:"\f0a9"}.fa-filter-circle-xmark:before{content:"\e17b"}.fa-locust:before{content:"\e520"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-list-1-2:before,.fa-list-numeric:before,.fa-list-ol:before{content:"\f0cb"}.fa-person-dress-burst:before{content:"\e544"}.fa-money-check-alt:before,.fa-money-check-dollar:before{content:"\f53d"}.fa-vector-square:before{content:"\f5cb"}.fa-bread-slice:before{content:"\f7ec"}.fa-language:before{content:"\f1ab"}.fa-face-kiss-wink-heart:before,.fa-kiss-wink-heart:before{content:"\f598"}.fa-filter:before{content:"\f0b0"}.fa-question:before{content:"\3f"}.fa-file-signature:before{content:"\f573"}.fa-arrows-alt:before,.fa-up-down-left-right:before{content:"\f0b2"}.fa-house-chimney-user:before{content:"\e065"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-puzzle-piece:before{content:"\f12e"}.fa-money-check:before{content:"\f53c"}.fa-star-half-alt:before,.fa-star-half-stroke:before{content:"\f5c0"}.fa-code:before{content:"\f121"}.fa-glass-whiskey:before,.fa-whiskey-glass:before{content:"\f7a0"}.fa-building-circle-exclamation:before{content:"\e4d3"}.fa-magnifying-glass-chart:before{content:"\e522"}.fa-arrow-up-right-from-square:before,.fa-external-link:before{content:"\f08e"}.fa-cubes-stacked:before{content:"\e4e6"}.fa-krw:before,.fa-won-sign:before,.fa-won:before{content:"\f159"}.fa-virus-covid:before{content:"\e4a8"}.fa-austral-sign:before{content:"\e0a9"}.fa-f:before{content:"\46"}.fa-leaf:before{content:"\f06c"}.fa-road:before{content:"\f018"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-person-circle-plus:before{content:"\e541"}.fa-chart-pie:before,.fa-pie-chart:before{content:"\f200"}.fa-bolt-lightning:before{content:"\e0b7"}.fa-sack-xmark:before{content:"\e56a"}.fa-file-excel:before{content:"\f1c3"}.fa-file-contract:before{content:"\f56c"}.fa-fish-fins:before{content:"\e4f2"}.fa-building-flag:before{content:"\e4d5"}.fa-face-grin-beam:before,.fa-grin-beam:before{content:"\f582"}.fa-object-ungroup:before{content:"\f248"}.fa-poop:before{content:"\f619"}.fa-location-pin:before,.fa-map-marker:before{content:"\f041"}.fa-kaaba:before{content:"\f66b"}.fa-toilet-paper:before{content:"\f71e"}.fa-hard-hat:before,.fa-hat-hard:before,.fa-helmet-safety:before{content:"\f807"}.fa-eject:before{content:"\f052"}.fa-arrow-alt-circle-right:before,.fa-circle-right:before{content:"\f35a"}.fa-plane-circle-check:before{content:"\e555"}.fa-face-rolling-eyes:before,.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-object-group:before{content:"\f247"}.fa-chart-line:before,.fa-line-chart:before{content:"\f201"}.fa-mask-ventilator:before{content:"\e524"}.fa-arrow-right:before{content:"\f061"}.fa-map-signs:before,.fa-signs-post:before{content:"\f277"}.fa-cash-register:before{content:"\f788"}.fa-person-circle-question:before{content:"\e542"}.fa-h:before{content:"\48"}.fa-tarp:before{content:"\e57b"}.fa-screwdriver-wrench:before,.fa-tools:before{content:"\f7d9"}.fa-arrows-to-eye:before{content:"\e4bf"}.fa-plug-circle-bolt:before{content:"\e55b"}.fa-heart:before{content:"\f004"}.fa-mars-and-venus:before{content:"\f224"}.fa-home-user:before,.fa-house-user:before{content:"\e1b0"}.fa-dumpster-fire:before{content:"\f794"}.fa-house-crack:before{content:"\e3b1"}.fa-cocktail:before,.fa-martini-glass-citrus:before{content:"\f561"}.fa-face-surprise:before,.fa-surprise:before{content:"\f5c2"}.fa-bottle-water:before{content:"\e4c5"}.fa-circle-pause:before,.fa-pause-circle:before{content:"\f28b"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-apple-alt:before,.fa-apple-whole:before{content:"\f5d1"}.fa-kitchen-set:before{content:"\e51a"}.fa-r:before{content:"\52"}.fa-temperature-1:before,.fa-temperature-quarter:before,.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-cube:before{content:"\f1b2"}.fa-bitcoin-sign:before{content:"\e0b4"}.fa-shield-dog:before{content:"\e573"}.fa-solar-panel:before{content:"\f5ba"}.fa-lock-open:before{content:"\f3c1"}.fa-elevator:before{content:"\e16d"}.fa-money-bill-transfer:before{content:"\e528"}.fa-money-bill-trend-up:before{content:"\e529"}.fa-house-flood-water-circle-arrow-right:before{content:"\e50f"}.fa-poll-h:before,.fa-square-poll-horizontal:before{content:"\f682"}.fa-circle:before{content:"\f111"}.fa-backward-fast:before,.fa-fast-backward:before{content:"\f049"}.fa-recycle:before{content:"\f1b8"}.fa-user-astronaut:before{content:"\f4fb"}.fa-plane-slash:before{content:"\e069"}.fa-trademark:before{content:"\f25c"}.fa-basketball-ball:before,.fa-basketball:before{content:"\f434"}.fa-satellite-dish:before{content:"\f7c0"}.fa-arrow-alt-circle-up:before,.fa-circle-up:before{content:"\f35b"}.fa-mobile-alt:before,.fa-mobile-screen-button:before{content:"\f3cd"}.fa-volume-high:before,.fa-volume-up:before{content:"\f028"}.fa-users-rays:before{content:"\e593"}.fa-wallet:before{content:"\f555"}.fa-clipboard-check:before{content:"\f46c"}.fa-file-audio:before{content:"\f1c7"}.fa-burger:before,.fa-hamburger:before{content:"\f805"}.fa-wrench:before{content:"\f0ad"}.fa-bugs:before{content:"\e4d0"}.fa-rupee-sign:before,.fa-rupee:before{content:"\f156"}.fa-file-image:before{content:"\f1c5"}.fa-circle-question:before,.fa-question-circle:before{content:"\f059"}.fa-plane-departure:before{content:"\f5b0"}.fa-handshake-slash:before{content:"\e060"}.fa-book-bookmark:before{content:"\e0bb"}.fa-code-branch:before{content:"\f126"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-bridge:before{content:"\e4c8"}.fa-phone-alt:before,.fa-phone-flip:before{content:"\f879"}.fa-truck-front:before{content:"\e2b7"}.fa-cat:before{content:"\f6be"}.fa-anchor-circle-exclamation:before{content:"\e4ab"}.fa-truck-field:before{content:"\e58d"}.fa-route:before{content:"\f4d7"}.fa-clipboard-question:before{content:"\e4e3"}.fa-panorama:before{content:"\e209"}.fa-comment-medical:before{content:"\f7f5"}.fa-teeth-open:before{content:"\f62f"}.fa-file-circle-minus:before{content:"\e4ed"}.fa-tags:before{content:"\f02c"}.fa-wine-glass:before{content:"\f4e3"}.fa-fast-forward:before,.fa-forward-fast:before{content:"\f050"}.fa-face-meh-blank:before,.fa-meh-blank:before{content:"\f5a4"}.fa-parking:before,.fa-square-parking:before{content:"\f540"}.fa-house-signal:before{content:"\e012"}.fa-bars-progress:before,.fa-tasks-alt:before{content:"\f828"}.fa-faucet-drip:before{content:"\e006"}.fa-cart-flatbed:before,.fa-dolly-flatbed:before{content:"\f474"}.fa-ban-smoking:before,.fa-smoking-ban:before{content:"\f54d"}.fa-terminal:before{content:"\f120"}.fa-mobile-button:before{content:"\f10b"}.fa-house-medical-flag:before{content:"\e514"}.fa-basket-shopping:before,.fa-shopping-basket:before{content:"\f291"}.fa-tape:before{content:"\f4db"}.fa-bus-alt:before,.fa-bus-simple:before{content:"\f55e"}.fa-eye:before{content:"\f06e"}.fa-face-sad-cry:before,.fa-sad-cry:before{content:"\f5b3"}.fa-audio-description:before{content:"\f29e"}.fa-person-military-to-person:before{content:"\e54c"}.fa-file-shield:before{content:"\e4f0"}.fa-user-slash:before{content:"\f506"}.fa-pen:before{content:"\f304"}.fa-tower-observation:before{content:"\e586"}.fa-file-code:before{content:"\f1c9"}.fa-signal-5:before,.fa-signal-perfect:before,.fa-signal:before{content:"\f012"}.fa-bus:before{content:"\f207"}.fa-heart-circle-xmark:before{content:"\e501"}.fa-home-lg:before,.fa-house-chimney:before{content:"\e3af"}.fa-window-maximize:before{content:"\f2d0"}.fa-face-frown:before,.fa-frown:before{content:"\f119"}.fa-prescription:before{content:"\f5b1"}.fa-shop:before,.fa-store-alt:before{content:"\f54f"}.fa-floppy-disk:before,.fa-save:before{content:"\f0c7"}.fa-vihara:before{content:"\f6a7"}.fa-balance-scale-left:before,.fa-scale-unbalanced:before{content:"\f515"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-comment-dots:before,.fa-commenting:before{content:"\f4ad"}.fa-plant-wilt:before{content:"\e5aa"}.fa-diamond:before{content:"\f219"}.fa-face-grin-squint:before,.fa-grin-squint:before{content:"\f585"}.fa-hand-holding-dollar:before,.fa-hand-holding-usd:before{content:"\f4c0"}.fa-bacterium:before{content:"\e05a"}.fa-hand-pointer:before{content:"\f25a"}.fa-drum-steelpan:before{content:"\f56a"}.fa-hand-scissors:before{content:"\f257"}.fa-hands-praying:before,.fa-praying-hands:before{content:"\f684"}.fa-arrow-right-rotate:before,.fa-arrow-rotate-forward:before,.fa-arrow-rotate-right:before,.fa-redo:before{content:"\f01e"}.fa-biohazard:before{content:"\f780"}.fa-location-crosshairs:before,.fa-location:before{content:"\f601"}.fa-mars-double:before{content:"\f227"}.fa-child-dress:before{content:"\e59c"}.fa-users-between-lines:before{content:"\e591"}.fa-lungs-virus:before{content:"\e067"}.fa-face-grin-tears:before,.fa-grin-tears:before{content:"\f588"}.fa-phone:before{content:"\f095"}.fa-calendar-times:before,.fa-calendar-xmark:before{content:"\f273"}.fa-child-reaching:before{content:"\e59d"}.fa-head-side-virus:before{content:"\e064"}.fa-user-cog:before,.fa-user-gear:before{content:"\f4fe"}.fa-arrow-up-1-9:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-door-closed:before{content:"\f52a"}.fa-shield-virus:before{content:"\e06c"}.fa-dice-six:before{content:"\f526"}.fa-mosquito-net:before{content:"\e52c"}.fa-bridge-water:before{content:"\e4ce"}.fa-person-booth:before{content:"\f756"}.fa-text-width:before{content:"\f035"}.fa-hat-wizard:before{content:"\f6e8"}.fa-pen-fancy:before{content:"\f5ac"}.fa-digging:before,.fa-person-digging:before{content:"\f85e"}.fa-trash:before{content:"\f1f8"}.fa-gauge-simple-med:before,.fa-gauge-simple:before,.fa-tachometer-average:before{content:"\f629"}.fa-book-medical:before{content:"\f7e6"}.fa-poo:before{content:"\f2fe"}.fa-quote-right-alt:before,.fa-quote-right:before{content:"\f10e"}.fa-shirt:before,.fa-t-shirt:before,.fa-tshirt:before{content:"\f553"}.fa-cubes:before{content:"\f1b3"}.fa-divide:before{content:"\f529"}.fa-tenge-sign:before,.fa-tenge:before{content:"\f7d7"}.fa-headphones:before{content:"\f025"}.fa-hands-holding:before{content:"\f4c2"}.fa-hands-clapping:before{content:"\e1a8"}.fa-republican:before{content:"\f75e"}.fa-arrow-left:before{content:"\f060"}.fa-person-circle-xmark:before{content:"\e543"}.fa-ruler:before{content:"\f545"}.fa-align-left:before{content:"\f036"}.fa-dice-d6:before{content:"\f6d1"}.fa-restroom:before{content:"\f7bd"}.fa-j:before{content:"\4a"}.fa-users-viewfinder:before{content:"\e595"}.fa-file-video:before{content:"\f1c8"}.fa-external-link-alt:before,.fa-up-right-from-square:before{content:"\f35d"}.fa-table-cells:before,.fa-th:before{content:"\f00a"}.fa-file-pdf:before{content:"\f1c1"}.fa-bible:before,.fa-book-bible:before{content:"\f647"}.fa-o:before{content:"\4f"}.fa-medkit:before,.fa-suitcase-medical:before{content:"\f0fa"}.fa-user-secret:before{content:"\f21b"}.fa-otter:before{content:"\f700"}.fa-female:before,.fa-person-dress:before{content:"\f182"}.fa-comment-dollar:before{content:"\f651"}.fa-briefcase-clock:before,.fa-business-time:before{content:"\f64a"}.fa-table-cells-large:before,.fa-th-large:before{content:"\f009"}.fa-book-tanakh:before,.fa-tanakh:before{content:"\f827"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-clipboard-user:before{content:"\f7f3"}.fa-child:before{content:"\f1ae"}.fa-lira-sign:before{content:"\f195"}.fa-satellite:before{content:"\f7bf"}.fa-plane-lock:before{content:"\e558"}.fa-tag:before{content:"\f02b"}.fa-comment:before{content:"\f075"}.fa-birthday-cake:before,.fa-cake-candles:before,.fa-cake:before{content:"\f1fd"}.fa-envelope:before{content:"\f0e0"}.fa-angle-double-up:before,.fa-angles-up:before{content:"\f102"}.fa-paperclip:before{content:"\f0c6"}.fa-arrow-right-to-city:before{content:"\e4b3"}.fa-ribbon:before{content:"\f4d6"}.fa-lungs:before{content:"\f604"}.fa-arrow-up-9-1:before,.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-litecoin-sign:before{content:"\e1d3"}.fa-border-none:before{content:"\f850"}.fa-circle-nodes:before{content:"\e4e2"}.fa-parachute-box:before{content:"\f4cd"}.fa-indent:before{content:"\f03c"}.fa-truck-field-un:before{content:"\e58e"}.fa-hourglass-empty:before,.fa-hourglass:before{content:"\f254"}.fa-mountain:before{content:"\f6fc"}.fa-user-doctor:before,.fa-user-md:before{content:"\f0f0"}.fa-circle-info:before,.fa-info-circle:before{content:"\f05a"}.fa-cloud-meatball:before{content:"\f73b"}.fa-camera-alt:before,.fa-camera:before{content:"\f030"}.fa-square-virus:before{content:"\e578"}.fa-meteor:before{content:"\f753"}.fa-car-on:before{content:"\e4dd"}.fa-sleigh:before{content:"\f7cc"}.fa-arrow-down-1-9:before,.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-hand-holding-droplet:before,.fa-hand-holding-water:before{content:"\f4c1"}.fa-water:before{content:"\f773"}.fa-calendar-check:before{content:"\f274"}.fa-braille:before{content:"\f2a1"}.fa-prescription-bottle-alt:before,.fa-prescription-bottle-medical:before{content:"\f486"}.fa-landmark:before{content:"\f66f"}.fa-truck:before{content:"\f0d1"}.fa-crosshairs:before{content:"\f05b"}.fa-person-cane:before{content:"\e53c"}.fa-tent:before{content:"\e57d"}.fa-vest-patches:before{content:"\e086"}.fa-check-double:before{content:"\f560"}.fa-arrow-down-a-z:before,.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-money-bill-wheat:before{content:"\e52a"}.fa-cookie:before{content:"\f563"}.fa-arrow-left-rotate:before,.fa-arrow-rotate-back:before,.fa-arrow-rotate-backward:before,.fa-arrow-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-hard-drive:before,.fa-hdd:before{content:"\f0a0"}.fa-face-grin-squint-tears:before,.fa-grin-squint-tears:before{content:"\f586"}.fa-dumbbell:before{content:"\f44b"}.fa-list-alt:before,.fa-rectangle-list:before{content:"\f022"}.fa-tarp-droplet:before{content:"\e57c"}.fa-house-medical-circle-check:before{content:"\e511"}.fa-person-skiing-nordic:before,.fa-skiing-nordic:before{content:"\f7ca"}.fa-calendar-plus:before{content:"\f271"}.fa-plane-arrival:before{content:"\f5af"}.fa-arrow-alt-circle-left:before,.fa-circle-left:before{content:"\f359"}.fa-subway:before,.fa-train-subway:before{content:"\f239"}.fa-chart-gantt:before{content:"\e0e4"}.fa-indian-rupee-sign:before,.fa-indian-rupee:before,.fa-inr:before{content:"\e1bc"}.fa-crop-alt:before,.fa-crop-simple:before{content:"\f565"}.fa-money-bill-1:before,.fa-money-bill-alt:before{content:"\f3d1"}.fa-left-long:before,.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-dna:before{content:"\f471"}.fa-virus-slash:before{content:"\e075"}.fa-minus:before,.fa-subtract:before{content:"\f068"}.fa-chess:before{content:"\f439"}.fa-arrow-left-long:before,.fa-long-arrow-left:before{content:"\f177"}.fa-plug-circle-check:before{content:"\e55c"}.fa-street-view:before{content:"\f21d"}.fa-franc-sign:before{content:"\e18f"}.fa-volume-off:before{content:"\f026"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before,.fa-hands-american-sign-language-interpreting:before,.fa-hands-asl-interpreting:before{content:"\f2a3"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-droplet-slash:before,.fa-tint-slash:before{content:"\f5c7"}.fa-mosque:before{content:"\f678"}.fa-mosquito:before{content:"\e52b"}.fa-star-of-david:before{content:"\f69a"}.fa-person-military-rifle:before{content:"\e54b"}.fa-cart-shopping:before,.fa-shopping-cart:before{content:"\f07a"}.fa-vials:before{content:"\f493"}.fa-plug-circle-plus:before{content:"\e55f"}.fa-place-of-worship:before{content:"\f67f"}.fa-grip-vertical:before{content:"\f58e"}.fa-arrow-turn-up:before,.fa-level-up:before{content:"\f148"}.fa-u:before{content:"\55"}.fa-square-root-alt:before,.fa-square-root-variable:before{content:"\f698"}.fa-clock-four:before,.fa-clock:before{content:"\f017"}.fa-backward-step:before,.fa-step-backward:before{content:"\f048"}.fa-pallet:before{content:"\f482"}.fa-faucet:before{content:"\e005"}.fa-baseball-bat-ball:before{content:"\f432"}.fa-s:before{content:"\53"}.fa-timeline:before{content:"\e29c"}.fa-keyboard:before{content:"\f11c"}.fa-caret-down:before{content:"\f0d7"}.fa-clinic-medical:before,.fa-house-chimney-medical:before{content:"\f7f2"}.fa-temperature-3:before,.fa-temperature-three-quarters:before,.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-mobile-android-alt:before,.fa-mobile-screen:before{content:"\f3cf"}.fa-plane-up:before{content:"\e22d"}.fa-piggy-bank:before{content:"\f4d3"}.fa-battery-3:before,.fa-battery-half:before{content:"\f242"}.fa-mountain-city:before{content:"\e52e"}.fa-coins:before{content:"\f51e"}.fa-khanda:before{content:"\f66d"}.fa-sliders-h:before,.fa-sliders:before{content:"\f1de"}.fa-folder-tree:before{content:"\f802"}.fa-network-wired:before{content:"\f6ff"}.fa-map-pin:before{content:"\f276"}.fa-hamsa:before{content:"\f665"}.fa-cent-sign:before{content:"\e3f5"}.fa-flask:before{content:"\f0c3"}.fa-person-pregnant:before{content:"\e31e"}.fa-wand-sparkles:before{content:"\f72b"}.fa-ellipsis-v:before,.fa-ellipsis-vertical:before{content:"\f142"}.fa-ticket:before{content:"\f145"}.fa-power-off:before{content:"\f011"}.fa-long-arrow-alt-right:before,.fa-right-long:before{content:"\f30b"}.fa-flag-usa:before{content:"\f74d"}.fa-laptop-file:before{content:"\e51d"}.fa-teletype:before,.fa-tty:before{content:"\f1e4"}.fa-diagram-next:before{content:"\e476"}.fa-person-rifle:before{content:"\e54e"}.fa-house-medical-circle-exclamation:before{content:"\e512"}.fa-closed-captioning:before{content:"\f20a"}.fa-hiking:before,.fa-person-hiking:before{content:"\f6ec"}.fa-venus-double:before{content:"\f226"}.fa-images:before{content:"\f302"}.fa-calculator:before{content:"\f1ec"}.fa-people-pulling:before{content:"\e535"}.fa-n:before{content:"\4e"}.fa-cable-car:before,.fa-tram:before{content:"\f7da"}.fa-cloud-rain:before{content:"\f73d"}.fa-building-circle-xmark:before{content:"\e4d4"}.fa-ship:before{content:"\f21a"}.fa-arrows-down-to-line:before{content:"\e4b8"}.fa-download:before{content:"\f019"}.fa-face-grin:before,.fa-grin:before{content:"\f580"}.fa-backspace:before,.fa-delete-left:before{content:"\f55a"}.fa-eye-dropper-empty:before,.fa-eye-dropper:before,.fa-eyedropper:before{content:"\f1fb"}.fa-file-circle-check:before{content:"\e5a0"}.fa-forward:before{content:"\f04e"}.fa-mobile-android:before,.fa-mobile-phone:before,.fa-mobile:before{content:"\f3ce"}.fa-face-meh:before,.fa-meh:before{content:"\f11a"}.fa-align-center:before{content:"\f037"}.fa-book-dead:before,.fa-book-skull:before{content:"\f6b7"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-heart-circle-exclamation:before{content:"\e4fe"}.fa-home-alt:before,.fa-home-lg-alt:before,.fa-home:before,.fa-house:before{content:"\f015"}.fa-calendar-week:before{content:"\f784"}.fa-laptop-medical:before{content:"\f812"}.fa-b:before{content:"\42"}.fa-file-medical:before{content:"\f477"}.fa-dice-one:before{content:"\f525"}.fa-kiwi-bird:before{content:"\f535"}.fa-arrow-right-arrow-left:before,.fa-exchange:before{content:"\f0ec"}.fa-redo-alt:before,.fa-rotate-forward:before,.fa-rotate-right:before{content:"\f2f9"}.fa-cutlery:before,.fa-utensils:before{content:"\f2e7"}.fa-arrow-up-wide-short:before,.fa-sort-amount-up:before{content:"\f161"}.fa-mill-sign:before{content:"\e1ed"}.fa-bowl-rice:before{content:"\e2eb"}.fa-skull:before{content:"\f54c"}.fa-broadcast-tower:before,.fa-tower-broadcast:before{content:"\f519"}.fa-truck-pickup:before{content:"\f63c"}.fa-long-arrow-alt-up:before,.fa-up-long:before{content:"\f30c"}.fa-stop:before{content:"\f04d"}.fa-code-merge:before{content:"\f387"}.fa-upload:before{content:"\f093"}.fa-hurricane:before{content:"\f751"}.fa-mound:before{content:"\e52d"}.fa-toilet-portable:before{content:"\e583"}.fa-compact-disc:before{content:"\f51f"}.fa-file-arrow-down:before,.fa-file-download:before{content:"\f56d"}.fa-caravan:before{content:"\f8ff"}.fa-shield-cat:before{content:"\e572"}.fa-bolt:before,.fa-zap:before{content:"\f0e7"}.fa-glass-water:before{content:"\e4f4"}.fa-oil-well:before{content:"\e532"}.fa-vault:before{content:"\e2c5"}.fa-mars:before{content:"\f222"}.fa-toilet:before{content:"\f7d8"}.fa-plane-circle-xmark:before{content:"\e557"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen-sign:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble-sign:before,.fa-ruble:before{content:"\f158"}.fa-sun:before{content:"\f185"}.fa-guitar:before{content:"\f7a6"}.fa-face-laugh-wink:before,.fa-laugh-wink:before{content:"\f59c"}.fa-horse-head:before{content:"\f7ab"}.fa-bore-hole:before{content:"\e4c3"}.fa-industry:before{content:"\f275"}.fa-arrow-alt-circle-down:before,.fa-circle-down:before{content:"\f358"}.fa-arrows-turn-to-dots:before{content:"\e4c1"}.fa-florin-sign:before{content:"\e184"}.fa-arrow-down-short-wide:before,.fa-sort-amount-desc:before,.fa-sort-amount-down-alt:before{content:"\f884"}.fa-less-than:before{content:"\3c"}.fa-angle-down:before{content:"\f107"}.fa-car-tunnel:before{content:"\e4de"}.fa-head-side-cough:before{content:"\e061"}.fa-grip-lines:before{content:"\f7a4"}.fa-thumbs-down:before{content:"\f165"}.fa-user-lock:before{content:"\f502"}.fa-arrow-right-long:before,.fa-long-arrow-right:before{content:"\f178"}.fa-anchor-circle-xmark:before{content:"\e4ac"}.fa-ellipsis-h:before,.fa-ellipsis:before{content:"\f141"}.fa-chess-pawn:before{content:"\f443"}.fa-first-aid:before,.fa-kit-medical:before{content:"\f479"}.fa-person-through-window:before{content:"\e5a9"}.fa-toolbox:before{content:"\f552"}.fa-hands-holding-circle:before{content:"\e4fb"}.fa-bug:before{content:"\f188"}.fa-credit-card-alt:before,.fa-credit-card:before{content:"\f09d"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-hand-holding-hand:before{content:"\e4f7"}.fa-book-open-reader:before,.fa-book-reader:before{content:"\f5da"}.fa-mountain-sun:before{content:"\e52f"}.fa-arrows-left-right-to-line:before{content:"\e4ba"}.fa-dice-d20:before{content:"\f6cf"}.fa-truck-droplet:before{content:"\e58c"}.fa-file-circle-xmark:before{content:"\e5a1"}.fa-temperature-arrow-up:before,.fa-temperature-up:before{content:"\e040"}.fa-medal:before{content:"\f5a2"}.fa-bed:before{content:"\f236"}.fa-h-square:before,.fa-square-h:before{content:"\f0fd"}.fa-podcast:before{content:"\f2ce"}.fa-temperature-4:before,.fa-temperature-full:before,.fa-thermometer-4:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-bell:before{content:"\f0f3"}.fa-superscript:before{content:"\f12b"}.fa-plug-circle-xmark:before{content:"\e560"}.fa-star-of-life:before{content:"\f621"}.fa-phone-slash:before{content:"\f3dd"}.fa-paint-roller:before{content:"\f5aa"}.fa-hands-helping:before,.fa-handshake-angle:before{content:"\f4c4"}.fa-location-dot:before,.fa-map-marker-alt:before{content:"\f3c5"}.fa-file:before{content:"\f15b"}.fa-greater-than:before{content:"\3e"}.fa-person-swimming:before,.fa-swimmer:before{content:"\f5c4"}.fa-arrow-down:before{content:"\f063"}.fa-droplet:before,.fa-tint:before{content:"\f043"}.fa-eraser:before{content:"\f12d"}.fa-earth-america:before,.fa-earth-americas:before,.fa-earth:before,.fa-globe-americas:before{content:"\f57d"}.fa-person-burst:before{content:"\e53b"}.fa-dove:before{content:"\f4ba"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-socks:before{content:"\f696"}.fa-inbox:before{content:"\f01c"}.fa-section:before{content:"\e447"}.fa-gauge-high:before,.fa-tachometer-alt-fast:before,.fa-tachometer-alt:before{content:"\f625"}.fa-envelope-open-text:before{content:"\f658"}.fa-hospital-alt:before,.fa-hospital-wide:before,.fa-hospital:before{content:"\f0f8"}.fa-wine-bottle:before{content:"\f72f"}.fa-chess-rook:before{content:"\f447"}.fa-bars-staggered:before,.fa-reorder:before,.fa-stream:before{content:"\f550"}.fa-dharmachakra:before{content:"\f655"}.fa-hotdog:before{content:"\f80f"}.fa-blind:before,.fa-person-walking-with-cane:before{content:"\f29d"}.fa-drum:before{content:"\f569"}.fa-ice-cream:before{content:"\f810"}.fa-heart-circle-bolt:before{content:"\e4fc"}.fa-fax:before{content:"\f1ac"}.fa-paragraph:before{content:"\f1dd"}.fa-check-to-slot:before,.fa-vote-yea:before{content:"\f772"}.fa-star-half:before{content:"\f089"}.fa-boxes-alt:before,.fa-boxes-stacked:before,.fa-boxes:before{content:"\f468"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-assistive-listening-systems:before,.fa-ear-listen:before{content:"\f2a2"}.fa-tree-city:before{content:"\e587"}.fa-play:before{content:"\f04b"}.fa-font:before{content:"\f031"}.fa-table-cells-row-lock:before{content:"\e67a"}.fa-rupiah-sign:before{content:"\e23d"}.fa-magnifying-glass:before,.fa-search:before{content:"\f002"}.fa-ping-pong-paddle-ball:before,.fa-table-tennis-paddle-ball:before,.fa-table-tennis:before{content:"\f45d"}.fa-diagnoses:before,.fa-person-dots-from-line:before{content:"\f470"}.fa-trash-can-arrow-up:before,.fa-trash-restore-alt:before{content:"\f82a"}.fa-naira-sign:before{content:"\e1f6"}.fa-cart-arrow-down:before{content:"\f218"}.fa-walkie-talkie:before{content:"\f8ef"}.fa-file-edit:before,.fa-file-pen:before{content:"\f31c"}.fa-receipt:before{content:"\f543"}.fa-pen-square:before,.fa-pencil-square:before,.fa-square-pen:before{content:"\f14b"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-person-circle-exclamation:before{content:"\e53f"}.fa-chevron-down:before{content:"\f078"}.fa-battery-5:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-skull-crossbones:before{content:"\f714"}.fa-code-compare:before{content:"\e13a"}.fa-list-dots:before,.fa-list-ul:before{content:"\f0ca"}.fa-school-lock:before{content:"\e56f"}.fa-tower-cell:before{content:"\e585"}.fa-down-long:before,.fa-long-arrow-alt-down:before{content:"\f309"}.fa-ranking-star:before{content:"\e561"}.fa-chess-king:before{content:"\f43f"}.fa-person-harassing:before{content:"\e549"}.fa-brazilian-real-sign:before{content:"\e46c"}.fa-landmark-alt:before,.fa-landmark-dome:before{content:"\f752"}.fa-arrow-up:before{content:"\f062"}.fa-television:before,.fa-tv-alt:before,.fa-tv:before{content:"\f26c"}.fa-shrimp:before{content:"\e448"}.fa-list-check:before,.fa-tasks:before{content:"\f0ae"}.fa-jug-detergent:before{content:"\e519"}.fa-circle-user:before,.fa-user-circle:before{content:"\f2bd"}.fa-user-shield:before{content:"\f505"}.fa-wind:before{content:"\f72e"}.fa-car-burst:before,.fa-car-crash:before{content:"\f5e1"}.fa-y:before{content:"\59"}.fa-person-snowboarding:before,.fa-snowboarding:before{content:"\f7ce"}.fa-shipping-fast:before,.fa-truck-fast:before{content:"\f48b"}.fa-fish:before{content:"\f578"}.fa-user-graduate:before{content:"\f501"}.fa-adjust:before,.fa-circle-half-stroke:before{content:"\f042"}.fa-clapperboard:before{content:"\e131"}.fa-circle-radiation:before,.fa-radiation-alt:before{content:"\f7ba"}.fa-baseball-ball:before,.fa-baseball:before{content:"\f433"}.fa-jet-fighter-up:before{content:"\e518"}.fa-diagram-project:before,.fa-project-diagram:before{content:"\f542"}.fa-copy:before{content:"\f0c5"}.fa-volume-mute:before,.fa-volume-times:before,.fa-volume-xmark:before{content:"\f6a9"}.fa-hand-sparkles:before{content:"\e05d"}.fa-grip-horizontal:before,.fa-grip:before{content:"\f58d"}.fa-share-from-square:before,.fa-share-square:before{content:"\f14d"}.fa-child-combatant:before,.fa-child-rifle:before{content:"\e4e0"}.fa-gun:before{content:"\e19b"}.fa-phone-square:before,.fa-square-phone:before{content:"\f098"}.fa-add:before,.fa-plus:before{content:"\2b"}.fa-expand:before{content:"\f065"}.fa-computer:before{content:"\e4e5"}.fa-close:before,.fa-multiply:before,.fa-remove:before,.fa-times:before,.fa-xmark:before{content:"\f00d"}.fa-arrows-up-down-left-right:before,.fa-arrows:before{content:"\f047"}.fa-chalkboard-teacher:before,.fa-chalkboard-user:before{content:"\f51c"}.fa-peso-sign:before{content:"\e222"}.fa-building-shield:before{content:"\e4d8"}.fa-baby:before{content:"\f77c"}.fa-users-line:before{content:"\e592"}.fa-quote-left-alt:before,.fa-quote-left:before{content:"\f10d"}.fa-tractor:before{content:"\f722"}.fa-trash-arrow-up:before,.fa-trash-restore:before{content:"\f829"}.fa-arrow-down-up-lock:before{content:"\e4b0"}.fa-lines-leaning:before{content:"\e51e"}.fa-ruler-combined:before{content:"\f546"}.fa-copyright:before{content:"\f1f9"}.fa-equals:before{content:"\3d"}.fa-blender:before{content:"\f517"}.fa-teeth:before{content:"\f62e"}.fa-ils:before,.fa-shekel-sign:before,.fa-shekel:before,.fa-sheqel-sign:before,.fa-sheqel:before{content:"\f20b"}.fa-map:before{content:"\f279"}.fa-rocket:before{content:"\f135"}.fa-photo-film:before,.fa-photo-video:before{content:"\f87c"}.fa-folder-minus:before{content:"\f65d"}.fa-store:before{content:"\f54e"}.fa-arrow-trend-up:before{content:"\e098"}.fa-plug-circle-minus:before{content:"\e55e"}.fa-sign-hanging:before,.fa-sign:before{content:"\f4d9"}.fa-bezier-curve:before{content:"\f55b"}.fa-bell-slash:before{content:"\f1f6"}.fa-tablet-android:before,.fa-tablet:before{content:"\f3fb"}.fa-school-flag:before{content:"\e56e"}.fa-fill:before{content:"\f575"}.fa-angle-up:before{content:"\f106"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-holly-berry:before{content:"\f7aa"}.fa-chevron-left:before{content:"\f053"}.fa-bacteria:before{content:"\e059"}.fa-hand-lizard:before{content:"\f258"}.fa-notdef:before{content:"\e1fe"}.fa-disease:before{content:"\f7fa"}.fa-briefcase-medical:before{content:"\f469"}.fa-genderless:before{content:"\f22d"}.fa-chevron-right:before{content:"\f054"}.fa-retweet:before{content:"\f079"}.fa-car-alt:before,.fa-car-rear:before{content:"\f5de"}.fa-pump-soap:before{content:"\e06b"}.fa-video-slash:before{content:"\f4e2"}.fa-battery-2:before,.fa-battery-quarter:before{content:"\f243"}.fa-radio:before{content:"\f8d7"}.fa-baby-carriage:before,.fa-carriage-baby:before{content:"\f77d"}.fa-traffic-light:before{content:"\f637"}.fa-thermometer:before{content:"\f491"}.fa-vr-cardboard:before{content:"\f729"}.fa-hand-middle-finger:before{content:"\f806"}.fa-percent:before,.fa-percentage:before{content:"\25"}.fa-truck-moving:before{content:"\f4df"}.fa-glass-water-droplet:before{content:"\e4f5"}.fa-display:before{content:"\e163"}.fa-face-smile:before,.fa-smile:before{content:"\f118"}.fa-thumb-tack:before,.fa-thumbtack:before{content:"\f08d"}.fa-trophy:before{content:"\f091"}.fa-person-praying:before,.fa-pray:before{content:"\f683"}.fa-hammer:before{content:"\f6e3"}.fa-hand-peace:before{content:"\f25b"}.fa-rotate:before,.fa-sync-alt:before{content:"\f2f1"}.fa-spinner:before{content:"\f110"}.fa-robot:before{content:"\f544"}.fa-peace:before{content:"\f67c"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-warehouse:before{content:"\f494"}.fa-arrow-up-right-dots:before{content:"\e4b7"}.fa-splotch:before{content:"\f5bc"}.fa-face-grin-hearts:before,.fa-grin-hearts:before{content:"\f584"}.fa-dice-four:before{content:"\f524"}.fa-sim-card:before{content:"\f7c4"}.fa-transgender-alt:before,.fa-transgender:before{content:"\f225"}.fa-mercury:before{content:"\f223"}.fa-arrow-turn-down:before,.fa-level-down:before{content:"\f149"}.fa-person-falling-burst:before{content:"\e547"}.fa-award:before{content:"\f559"}.fa-ticket-alt:before,.fa-ticket-simple:before{content:"\f3ff"}.fa-building:before{content:"\f1ad"}.fa-angle-double-left:before,.fa-angles-left:before{content:"\f100"}.fa-qrcode:before{content:"\f029"}.fa-clock-rotate-left:before,.fa-history:before{content:"\f1da"}.fa-face-grin-beam-sweat:before,.fa-grin-beam-sweat:before{content:"\f583"}.fa-arrow-right-from-file:before,.fa-file-export:before{content:"\f56e"}.fa-shield-blank:before,.fa-shield:before{content:"\f132"}.fa-arrow-up-short-wide:before,.fa-sort-amount-up-alt:before{content:"\f885"}.fa-house-medical:before{content:"\e3b2"}.fa-golf-ball-tee:before,.fa-golf-ball:before{content:"\f450"}.fa-chevron-circle-left:before,.fa-circle-chevron-left:before{content:"\f137"}.fa-house-chimney-window:before{content:"\e00d"}.fa-pen-nib:before{content:"\f5ad"}.fa-tent-arrow-turn-left:before{content:"\e580"}.fa-tents:before{content:"\e582"}.fa-magic:before,.fa-wand-magic:before{content:"\f0d0"}.fa-dog:before{content:"\f6d3"}.fa-carrot:before{content:"\f787"}.fa-moon:before{content:"\f186"}.fa-wine-glass-alt:before,.fa-wine-glass-empty:before{content:"\f5ce"}.fa-cheese:before{content:"\f7ef"}.fa-yin-yang:before{content:"\f6ad"}.fa-music:before{content:"\f001"}.fa-code-commit:before{content:"\f386"}.fa-temperature-low:before{content:"\f76b"}.fa-biking:before,.fa-person-biking:before{content:"\f84a"}.fa-broom:before{content:"\f51a"}.fa-shield-heart:before{content:"\e574"}.fa-gopuram:before{content:"\f664"}.fa-earth-oceania:before,.fa-globe-oceania:before{content:"\e47b"}.fa-square-xmark:before,.fa-times-square:before,.fa-xmark-square:before{content:"\f2d3"}.fa-hashtag:before{content:"\23"}.fa-expand-alt:before,.fa-up-right-and-down-left-from-center:before{content:"\f424"}.fa-oil-can:before{content:"\f613"}.fa-t:before{content:"\54"}.fa-hippo:before{content:"\f6ed"}.fa-chart-column:before{content:"\e0e3"}.fa-infinity:before{content:"\f534"}.fa-vial-circle-check:before{content:"\e596"}.fa-person-arrow-down-to-line:before{content:"\e538"}.fa-voicemail:before{content:"\f897"}.fa-fan:before{content:"\f863"}.fa-person-walking-luggage:before{content:"\e554"}.fa-arrows-alt-v:before,.fa-up-down:before{content:"\f338"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-calendar:before{content:"\f133"}.fa-trailer:before{content:"\e041"}.fa-bahai:before,.fa-haykal:before{content:"\f666"}.fa-sd-card:before{content:"\f7c2"}.fa-dragon:before{content:"\f6d5"}.fa-shoe-prints:before{content:"\f54b"}.fa-circle-plus:before,.fa-plus-circle:before{content:"\f055"}.fa-face-grin-tongue-wink:before,.fa-grin-tongue-wink:before{content:"\f58b"}.fa-hand-holding:before{content:"\f4bd"}.fa-plug-circle-exclamation:before{content:"\e55d"}.fa-chain-broken:before,.fa-chain-slash:before,.fa-link-slash:before,.fa-unlink:before{content:"\f127"}.fa-clone:before{content:"\f24d"}.fa-person-walking-arrow-loop-left:before{content:"\e551"}.fa-arrow-up-z-a:before,.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-fire-alt:before,.fa-fire-flame-curved:before{content:"\f7e4"}.fa-tornado:before{content:"\f76f"}.fa-file-circle-plus:before{content:"\e494"}.fa-book-quran:before,.fa-quran:before{content:"\f687"}.fa-anchor:before{content:"\f13d"}.fa-border-all:before{content:"\f84c"}.fa-angry:before,.fa-face-angry:before{content:"\f556"}.fa-cookie-bite:before{content:"\f564"}.fa-arrow-trend-down:before{content:"\e097"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-draw-polygon:before{content:"\f5ee"}.fa-balance-scale:before,.fa-scale-balanced:before{content:"\f24e"}.fa-gauge-simple-high:before,.fa-tachometer-fast:before,.fa-tachometer:before{content:"\f62a"}.fa-shower:before{content:"\f2cc"}.fa-desktop-alt:before,.fa-desktop:before{content:"\f390"}.fa-m:before{content:"\4d"}.fa-table-list:before,.fa-th-list:before{content:"\f00b"}.fa-comment-sms:before,.fa-sms:before{content:"\f7cd"}.fa-book:before{content:"\f02d"}.fa-user-plus:before{content:"\f234"}.fa-check:before{content:"\f00c"}.fa-battery-4:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-house-circle-check:before{content:"\e509"}.fa-angle-left:before{content:"\f104"}.fa-diagram-successor:before{content:"\e47a"}.fa-truck-arrow-right:before{content:"\e58b"}.fa-arrows-split-up-and-left:before{content:"\e4bc"}.fa-fist-raised:before,.fa-hand-fist:before{content:"\f6de"}.fa-cloud-moon:before{content:"\f6c3"}.fa-briefcase:before{content:"\f0b1"}.fa-person-falling:before{content:"\e546"}.fa-image-portrait:before,.fa-portrait:before{content:"\f3e0"}.fa-user-tag:before{content:"\f507"}.fa-rug:before{content:"\e569"}.fa-earth-europe:before,.fa-globe-europe:before{content:"\f7a2"}.fa-cart-flatbed-suitcase:before,.fa-luggage-cart:before{content:"\f59d"}.fa-rectangle-times:before,.fa-rectangle-xmark:before,.fa-times-rectangle:before,.fa-window-close:before{content:"\f410"}.fa-baht-sign:before{content:"\e0ac"}.fa-book-open:before{content:"\f518"}.fa-book-journal-whills:before,.fa-journal-whills:before{content:"\f66a"}.fa-handcuffs:before{content:"\e4f8"}.fa-exclamation-triangle:before,.fa-triangle-exclamation:before,.fa-warning:before{content:"\f071"}.fa-database:before{content:"\f1c0"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-bottle-droplet:before{content:"\e4c4"}.fa-mask-face:before{content:"\e1d7"}.fa-hill-rockslide:before{content:"\e508"}.fa-exchange-alt:before,.fa-right-left:before{content:"\f362"}.fa-paper-plane:before{content:"\f1d8"}.fa-road-circle-exclamation:before{content:"\e565"}.fa-dungeon:before{content:"\f6d9"}.fa-align-right:before{content:"\f038"}.fa-money-bill-1-wave:before,.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-life-ring:before{content:"\f1cd"}.fa-hands:before,.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-calendar-day:before{content:"\f783"}.fa-ladder-water:before,.fa-swimming-pool:before,.fa-water-ladder:before{content:"\f5c5"}.fa-arrows-up-down:before,.fa-arrows-v:before{content:"\f07d"}.fa-face-grimace:before,.fa-grimace:before{content:"\f57f"}.fa-wheelchair-alt:before,.fa-wheelchair-move:before{content:"\e2ce"}.fa-level-down-alt:before,.fa-turn-down:before{content:"\f3be"}.fa-person-walking-arrow-right:before{content:"\e552"}.fa-envelope-square:before,.fa-square-envelope:before{content:"\f199"}.fa-dice:before{content:"\f522"}.fa-bowling-ball:before{content:"\f436"}.fa-brain:before{content:"\f5dc"}.fa-band-aid:before,.fa-bandage:before{content:"\f462"}.fa-calendar-minus:before{content:"\f272"}.fa-circle-xmark:before,.fa-times-circle:before,.fa-xmark-circle:before{content:"\f057"}.fa-gifts:before{content:"\f79c"}.fa-hotel:before{content:"\f594"}.fa-earth-asia:before,.fa-globe-asia:before{content:"\f57e"}.fa-id-card-alt:before,.fa-id-card-clip:before{content:"\f47f"}.fa-magnifying-glass-plus:before,.fa-search-plus:before{content:"\f00e"}.fa-thumbs-up:before{content:"\f164"}.fa-user-clock:before{content:"\f4fd"}.fa-allergies:before,.fa-hand-dots:before{content:"\f461"}.fa-file-invoice:before{content:"\f570"}.fa-window-minimize:before{content:"\f2d1"}.fa-coffee:before,.fa-mug-saucer:before{content:"\f0f4"}.fa-brush:before{content:"\f55d"}.fa-mask:before{content:"\f6fa"}.fa-magnifying-glass-minus:before,.fa-search-minus:before{content:"\f010"}.fa-ruler-vertical:before{content:"\f548"}.fa-user-alt:before,.fa-user-large:before{content:"\f406"}.fa-train-tram:before{content:"\e5b4"}.fa-user-nurse:before{content:"\f82f"}.fa-syringe:before{content:"\f48e"}.fa-cloud-sun:before{content:"\f6c4"}.fa-stopwatch-20:before{content:"\e06f"}.fa-square-full:before{content:"\f45c"}.fa-magnet:before{content:"\f076"}.fa-jar:before{content:"\e516"}.fa-note-sticky:before,.fa-sticky-note:before{content:"\f249"}.fa-bug-slash:before{content:"\e490"}.fa-arrow-up-from-water-pump:before{content:"\e4b6"}.fa-bone:before{content:"\f5d7"}.fa-user-injured:before{content:"\f728"}.fa-face-sad-tear:before,.fa-sad-tear:before{content:"\f5b4"}.fa-plane:before{content:"\f072"}.fa-tent-arrows-down:before{content:"\e581"}.fa-exclamation:before{content:"\21"}.fa-arrows-spin:before{content:"\e4bb"}.fa-print:before{content:"\f02f"}.fa-try:before,.fa-turkish-lira-sign:before,.fa-turkish-lira:before{content:"\e2bb"}.fa-dollar-sign:before,.fa-dollar:before,.fa-usd:before{content:"\24"}.fa-x:before{content:"\58"}.fa-magnifying-glass-dollar:before,.fa-search-dollar:before{content:"\f688"}.fa-users-cog:before,.fa-users-gear:before{content:"\f509"}.fa-person-military-pointing:before{content:"\e54a"}.fa-bank:before,.fa-building-columns:before,.fa-institution:before,.fa-museum:before,.fa-university:before{content:"\f19c"}.fa-umbrella:before{content:"\f0e9"}.fa-trowel:before{content:"\e589"}.fa-d:before{content:"\44"}.fa-stapler:before{content:"\e5af"}.fa-masks-theater:before,.fa-theater-masks:before{content:"\f630"}.fa-kip-sign:before{content:"\e1c4"}.fa-hand-point-left:before{content:"\f0a5"}.fa-handshake-alt:before,.fa-handshake-simple:before{content:"\f4c6"}.fa-fighter-jet:before,.fa-jet-fighter:before{content:"\f0fb"}.fa-share-alt-square:before,.fa-square-share-nodes:before{content:"\f1e1"}.fa-barcode:before{content:"\f02a"}.fa-plus-minus:before{content:"\e43c"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-person-circle-check:before{content:"\e53e"}.fa-level-up-alt:before,.fa-turn-up:before{content:"\f3bf"} +.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host,:root{--fa-style-family-brands:"Font Awesome 6 Brands";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }.fa-brands,.fab{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-pixiv:before{content:"\e640"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-js-square:before,.fa-square-js:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-jxl:before{content:"\e67b"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-reddit-square:before,.fa-square-reddit:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-brave:before{content:"\e63c"}.fa-sistrix:before{content:"\f3ee"}.fa-instagram-square:before,.fa-square-instagram:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-hacker-news-square:before,.fa-square-hacker-news:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-threads:before{content:"\e618"}.fa-napster:before{content:"\f3d2"}.fa-snapchat-square:before,.fa-square-snapchat:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before,.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-opensuse:before{content:"\e62b"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-dribbble-square:before,.fa-square-dribbble:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-debian:before{content:"\e60b"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before,.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{content:"\f208"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-app-store:before{content:"\f36f"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-itunes-note:before{content:"\f3b5"}.fa-golang:before{content:"\e40f"}.fa-kickstarter:before,.fa-square-kickstarter:before{content:"\f3bb"}.fa-grav:before{content:"\f2d6"}.fa-weibo:before{content:"\f18a"}.fa-uncharted:before{content:"\e084"}.fa-firstdraft:before{content:"\f3a1"}.fa-square-youtube:before,.fa-youtube-square:before{content:"\f431"}.fa-wikipedia-w:before{content:"\f266"}.fa-rendact:before,.fa-wpressr:before{content:"\f3e4"}.fa-angellist:before{content:"\f209"}.fa-galactic-republic:before{content:"\f50c"}.fa-nfc-directional:before{content:"\e530"}.fa-skype:before{content:"\f17e"}.fa-joget:before{content:"\f3b7"}.fa-fedora:before{content:"\f798"}.fa-stripe-s:before{content:"\f42a"}.fa-meta:before{content:"\e49b"}.fa-laravel:before{content:"\f3bd"}.fa-hotjar:before{content:"\f3b1"}.fa-bluetooth-b:before{content:"\f294"}.fa-square-letterboxd:before{content:"\e62e"}.fa-sticker-mule:before{content:"\f3f7"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-hips:before{content:"\f452"}.fa-behance:before{content:"\f1b4"}.fa-reddit:before{content:"\f1a1"}.fa-discord:before{content:"\f392"}.fa-chrome:before{content:"\f268"}.fa-app-store-ios:before{content:"\f370"}.fa-cc-discover:before{content:"\f1f2"}.fa-wpbeginner:before{content:"\f297"}.fa-confluence:before{content:"\f78d"}.fa-shoelace:before{content:"\e60c"}.fa-mdb:before{content:"\f8ca"}.fa-dochub:before{content:"\f394"}.fa-accessible-icon:before{content:"\f368"}.fa-ebay:before{content:"\f4f4"}.fa-amazon:before{content:"\f270"}.fa-unsplash:before{content:"\e07c"}.fa-yarn:before{content:"\f7e3"}.fa-square-steam:before,.fa-steam-square:before{content:"\f1b7"}.fa-500px:before{content:"\f26e"}.fa-square-vimeo:before,.fa-vimeo-square:before{content:"\f194"}.fa-asymmetrik:before{content:"\f372"}.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before{content:"\f2b4"}.fa-gratipay:before{content:"\f184"}.fa-apple:before{content:"\f179"}.fa-hive:before{content:"\e07f"}.fa-gitkraken:before{content:"\f3a6"}.fa-keybase:before{content:"\f4f5"}.fa-apple-pay:before{content:"\f415"}.fa-padlet:before{content:"\e4a0"}.fa-amazon-pay:before{content:"\f42c"}.fa-github-square:before,.fa-square-github:before{content:"\f092"}.fa-stumbleupon:before{content:"\f1a4"}.fa-fedex:before{content:"\f797"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-shopify:before{content:"\e057"}.fa-neos:before{content:"\f612"}.fa-square-threads:before{content:"\e619"}.fa-hackerrank:before{content:"\f5f7"}.fa-researchgate:before{content:"\f4f8"}.fa-swift:before{content:"\f8e1"}.fa-angular:before{content:"\f420"}.fa-speakap:before{content:"\f3f3"}.fa-angrycreative:before{content:"\f36e"}.fa-y-combinator:before{content:"\f23b"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-google-scholar:before{content:"\e63b"}.fa-gitlab-square:before,.fa-square-gitlab:before{content:"\e5ae"}.fa-studiovinari:before{content:"\f3f8"}.fa-pied-piper:before{content:"\f2ae"}.fa-wordpress:before{content:"\f19a"}.fa-product-hunt:before{content:"\f288"}.fa-firefox:before{content:"\f269"}.fa-linode:before{content:"\f2b8"}.fa-goodreads:before{content:"\f3a8"}.fa-odnoklassniki-square:before,.fa-square-odnoklassniki:before{content:"\f264"}.fa-jsfiddle:before{content:"\f1cc"}.fa-sith:before{content:"\f512"}.fa-themeisle:before{content:"\f2b2"}.fa-page4:before{content:"\f3d7"}.fa-hashnode:before{content:"\e499"}.fa-react:before{content:"\f41b"}.fa-cc-paypal:before{content:"\f1f4"}.fa-squarespace:before{content:"\f5be"}.fa-cc-stripe:before{content:"\f1f5"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-bitcoin:before{content:"\f379"}.fa-keycdn:before{content:"\f3ba"}.fa-opera:before{content:"\f26a"}.fa-itch-io:before{content:"\f83a"}.fa-umbraco:before{content:"\f8e8"}.fa-galactic-senate:before{content:"\f50d"}.fa-ubuntu:before{content:"\f7df"}.fa-draft2digital:before{content:"\f396"}.fa-stripe:before{content:"\f429"}.fa-houzz:before{content:"\f27c"}.fa-gg:before{content:"\f260"}.fa-dhl:before{content:"\f790"}.fa-pinterest-square:before,.fa-square-pinterest:before{content:"\f0d3"}.fa-xing:before{content:"\f168"}.fa-blackberry:before{content:"\f37b"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-playstation:before{content:"\f3df"}.fa-quinscape:before{content:"\f459"}.fa-less:before{content:"\f41d"}.fa-blogger-b:before{content:"\f37d"}.fa-opencart:before{content:"\f23d"}.fa-vine:before{content:"\f1ca"}.fa-signal-messenger:before{content:"\e663"}.fa-paypal:before{content:"\f1ed"}.fa-gitlab:before{content:"\f296"}.fa-typo3:before{content:"\f42b"}.fa-reddit-alien:before{content:"\f281"}.fa-yahoo:before{content:"\f19e"}.fa-dailymotion:before{content:"\e052"}.fa-affiliatetheme:before{content:"\f36b"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-bootstrap:before{content:"\f836"}.fa-odnoklassniki:before{content:"\f263"}.fa-nfc-symbol:before{content:"\e531"}.fa-mintbit:before{content:"\e62f"}.fa-ethereum:before{content:"\f42e"}.fa-speaker-deck:before{content:"\f83c"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-patreon:before{content:"\f3d9"}.fa-avianex:before{content:"\f374"}.fa-ello:before{content:"\f5f1"}.fa-gofore:before{content:"\f3a7"}.fa-bimobject:before{content:"\f378"}.fa-brave-reverse:before{content:"\e63d"}.fa-facebook-f:before{content:"\f39e"}.fa-google-plus-square:before,.fa-square-google-plus:before{content:"\f0d4"}.fa-web-awesome:before{content:"\e682"}.fa-mandalorian:before{content:"\f50f"}.fa-first-order-alt:before{content:"\f50a"}.fa-osi:before{content:"\f41a"}.fa-google-wallet:before{content:"\f1ee"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-periscope:before{content:"\f3da"}.fa-fulcrum:before{content:"\f50b"}.fa-cloudscale:before{content:"\f383"}.fa-forumbee:before{content:"\f211"}.fa-mizuni:before{content:"\f3cc"}.fa-schlix:before{content:"\f3ea"}.fa-square-xing:before,.fa-xing-square:before{content:"\f169"}.fa-bandcamp:before{content:"\f2d5"}.fa-wpforms:before{content:"\f298"}.fa-cloudversify:before{content:"\f385"}.fa-usps:before{content:"\f7e1"}.fa-megaport:before{content:"\f5a3"}.fa-magento:before{content:"\f3c4"}.fa-spotify:before{content:"\f1bc"}.fa-optin-monster:before{content:"\f23c"}.fa-fly:before{content:"\f417"}.fa-aviato:before{content:"\f421"}.fa-itunes:before{content:"\f3b4"}.fa-cuttlefish:before{content:"\f38c"}.fa-blogger:before{content:"\f37c"}.fa-flickr:before{content:"\f16e"}.fa-viber:before{content:"\f409"}.fa-soundcloud:before{content:"\f1be"}.fa-digg:before{content:"\f1a6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-letterboxd:before{content:"\e62d"}.fa-symfony:before{content:"\f83d"}.fa-maxcdn:before{content:"\f136"}.fa-etsy:before{content:"\f2d7"}.fa-facebook-messenger:before{content:"\f39f"}.fa-audible:before{content:"\f373"}.fa-think-peaks:before{content:"\f731"}.fa-bilibili:before{content:"\e3d9"}.fa-erlang:before{content:"\f39d"}.fa-x-twitter:before{content:"\e61b"}.fa-cotton-bureau:before{content:"\f89e"}.fa-dashcube:before{content:"\f210"}.fa-42-group:before,.fa-innosoft:before{content:"\e080"}.fa-stack-exchange:before{content:"\f18d"}.fa-elementor:before{content:"\f430"}.fa-pied-piper-square:before,.fa-square-pied-piper:before{content:"\e01e"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-palfed:before{content:"\f3d8"}.fa-superpowers:before{content:"\f2dd"}.fa-resolving:before{content:"\f3e7"}.fa-xbox:before{content:"\f412"}.fa-square-web-awesome-stroke:before{content:"\e684"}.fa-searchengin:before{content:"\f3eb"}.fa-tiktok:before{content:"\e07b"}.fa-facebook-square:before,.fa-square-facebook:before{content:"\f082"}.fa-renren:before{content:"\f18b"}.fa-linux:before{content:"\f17c"}.fa-glide:before{content:"\f2a5"}.fa-linkedin:before{content:"\f08c"}.fa-hubspot:before{content:"\f3b2"}.fa-deploydog:before{content:"\f38e"}.fa-twitch:before{content:"\f1e8"}.fa-ravelry:before{content:"\f2d9"}.fa-mixer:before{content:"\e056"}.fa-lastfm-square:before,.fa-square-lastfm:before{content:"\f203"}.fa-vimeo:before{content:"\f40a"}.fa-mendeley:before{content:"\f7b3"}.fa-uniregistry:before{content:"\f404"}.fa-figma:before{content:"\f799"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-dropbox:before{content:"\f16b"}.fa-instagram:before{content:"\f16d"}.fa-cmplid:before{content:"\e360"}.fa-upwork:before{content:"\e641"}.fa-facebook:before{content:"\f09a"}.fa-gripfire:before{content:"\f3ac"}.fa-jedi-order:before{content:"\f50e"}.fa-uikit:before{content:"\f403"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-phabricator:before{content:"\f3db"}.fa-ussunnah:before{content:"\f407"}.fa-earlybirds:before{content:"\f39a"}.fa-trade-federation:before{content:"\f513"}.fa-autoprefixer:before{content:"\f41c"}.fa-whatsapp:before{content:"\f232"}.fa-square-upwork:before{content:"\e67c"}.fa-slideshare:before{content:"\f1e7"}.fa-google-play:before{content:"\f3ab"}.fa-viadeo:before{content:"\f2a9"}.fa-line:before{content:"\f3c0"}.fa-google-drive:before{content:"\f3aa"}.fa-servicestack:before{content:"\f3ec"}.fa-simplybuilt:before{content:"\f215"}.fa-bitbucket:before{content:"\f171"}.fa-imdb:before{content:"\f2d8"}.fa-deezer:before{content:"\e077"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-jira:before{content:"\f7b1"}.fa-docker:before{content:"\f395"}.fa-screenpal:before{content:"\e570"}.fa-bluetooth:before{content:"\f293"}.fa-gitter:before{content:"\f426"}.fa-d-and-d:before{content:"\f38d"}.fa-microblog:before{content:"\e01a"}.fa-cc-diners-club:before{content:"\f24c"}.fa-gg-circle:before{content:"\f261"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-yandex:before{content:"\f413"}.fa-readme:before{content:"\f4d5"}.fa-html5:before{content:"\f13b"}.fa-sellsy:before{content:"\f213"}.fa-square-web-awesome:before{content:"\e683"}.fa-sass:before{content:"\f41e"}.fa-wirsindhandwerk:before,.fa-wsh:before{content:"\e2d0"}.fa-buromobelexperte:before{content:"\f37f"}.fa-salesforce:before{content:"\f83b"}.fa-octopus-deploy:before{content:"\e082"}.fa-medapps:before{content:"\f3c6"}.fa-ns8:before{content:"\f3d5"}.fa-pinterest-p:before{content:"\f231"}.fa-apper:before{content:"\f371"}.fa-fort-awesome:before{content:"\f286"}.fa-waze:before{content:"\f83f"}.fa-bluesky:before{content:"\e671"}.fa-cc-jcb:before{content:"\f24b"}.fa-snapchat-ghost:before,.fa-snapchat:before{content:"\f2ab"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-rust:before{content:"\e07a"}.fa-wix:before{content:"\f5cf"}.fa-behance-square:before,.fa-square-behance:before{content:"\f1b5"}.fa-supple:before{content:"\f3f9"}.fa-webflow:before{content:"\e65c"}.fa-rebel:before{content:"\f1d0"}.fa-css3:before{content:"\f13c"}.fa-staylinked:before{content:"\f3f5"}.fa-kaggle:before{content:"\f5fa"}.fa-space-awesome:before{content:"\e5ac"}.fa-deviantart:before{content:"\f1bd"}.fa-cpanel:before{content:"\f388"}.fa-goodreads-g:before{content:"\f3a9"}.fa-git-square:before,.fa-square-git:before{content:"\f1d2"}.fa-square-tumblr:before,.fa-tumblr-square:before{content:"\f174"}.fa-trello:before{content:"\f181"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-get-pocket:before{content:"\f265"}.fa-perbyte:before{content:"\e083"}.fa-grunt:before{content:"\f3ad"}.fa-weebly:before{content:"\f5cc"}.fa-connectdevelop:before{content:"\f20e"}.fa-leanpub:before{content:"\f212"}.fa-black-tie:before{content:"\f27e"}.fa-themeco:before{content:"\f5c6"}.fa-python:before{content:"\f3e2"}.fa-android:before{content:"\f17b"}.fa-bots:before{content:"\e340"}.fa-free-code-camp:before{content:"\f2c5"}.fa-hornbill:before{content:"\f592"}.fa-js:before{content:"\f3b8"}.fa-ideal:before{content:"\e013"}.fa-git:before{content:"\f1d3"}.fa-dev:before{content:"\f6cc"}.fa-sketch:before{content:"\f7c6"}.fa-yandex-international:before{content:"\f414"}.fa-cc-amex:before{content:"\f1f3"}.fa-uber:before{content:"\f402"}.fa-github:before{content:"\f09b"}.fa-php:before{content:"\f457"}.fa-alipay:before{content:"\f642"}.fa-youtube:before{content:"\f167"}.fa-skyatlas:before{content:"\f216"}.fa-firefox-browser:before{content:"\e007"}.fa-replyd:before{content:"\f3e6"}.fa-suse:before{content:"\f7d6"}.fa-jenkins:before{content:"\f3b6"}.fa-twitter:before{content:"\f099"}.fa-rockrms:before{content:"\f3e9"}.fa-pinterest:before{content:"\f0d2"}.fa-buffer:before{content:"\f837"}.fa-npm:before{content:"\f3d4"}.fa-yammer:before{content:"\f840"}.fa-btc:before{content:"\f15a"}.fa-dribbble:before{content:"\f17d"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-internet-explorer:before{content:"\f26b"}.fa-stubber:before{content:"\e5c7"}.fa-telegram-plane:before,.fa-telegram:before{content:"\f2c6"}.fa-old-republic:before{content:"\f510"}.fa-odysee:before{content:"\e5c6"}.fa-square-whatsapp:before,.fa-whatsapp-square:before{content:"\f40c"}.fa-node-js:before{content:"\f3d3"}.fa-edge-legacy:before{content:"\e078"}.fa-slack-hash:before,.fa-slack:before{content:"\f198"}.fa-medrt:before{content:"\f3c8"}.fa-usb:before{content:"\f287"}.fa-tumblr:before{content:"\f173"}.fa-vaadin:before{content:"\f408"}.fa-quora:before{content:"\f2c4"}.fa-square-x-twitter:before{content:"\e61a"}.fa-reacteurope:before{content:"\f75d"}.fa-medium-m:before,.fa-medium:before{content:"\f23a"}.fa-amilia:before{content:"\f36d"}.fa-mixcloud:before{content:"\f289"}.fa-flipboard:before{content:"\f44d"}.fa-viacoin:before{content:"\f237"}.fa-critical-role:before{content:"\f6c9"}.fa-sitrox:before{content:"\e44a"}.fa-discourse:before{content:"\f393"}.fa-joomla:before{content:"\f1aa"}.fa-mastodon:before{content:"\f4f6"}.fa-airbnb:before{content:"\f834"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-buy-n-large:before{content:"\f8a6"}.fa-gulp:before{content:"\f3ae"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-strava:before{content:"\f428"}.fa-ember:before{content:"\f423"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-teamspeak:before{content:"\f4f9"}.fa-pushed:before{content:"\f3e1"}.fa-wordpress-simple:before{content:"\f411"}.fa-nutritionix:before{content:"\f3d6"}.fa-wodu:before{content:"\e088"}.fa-google-pay:before{content:"\e079"}.fa-intercom:before{content:"\f7af"}.fa-zhihu:before{content:"\f63f"}.fa-korvue:before{content:"\f42f"}.fa-pix:before{content:"\e43a"}.fa-steam-symbol:before{content:"\f3f6"}:host,:root{--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }.fa-regular,.far{font-weight:400}:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }.fa-solid,.fas{font-weight:900}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }@font-face{font-family:"FontAwesome";font-display:block;src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }@font-face{font-family:"FontAwesome";font-display:block;src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }@font-face{font-family:"FontAwesome";font-display:block;src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }@font-face{font-family:"FontAwesome";font-display:block;src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype"); } \ No newline at end of file diff --git a/deps/font-awesome-6.5.2/css/v4-shims.css b/deps/font-awesome-6.5.2/css/v4-shims.css new file mode 100644 index 0000000..ea60ea4 --- /dev/null +++ b/deps/font-awesome-6.5.2/css/v4-shims.css @@ -0,0 +1,2194 @@ +/*! + * Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +.fa.fa-glass:before { + content: "\f000"; } + +.fa.fa-envelope-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-envelope-o:before { + content: "\f0e0"; } + +.fa.fa-star-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-star-o:before { + content: "\f005"; } + +.fa.fa-remove:before { + content: "\f00d"; } + +.fa.fa-close:before { + content: "\f00d"; } + +.fa.fa-gear:before { + content: "\f013"; } + +.fa.fa-trash-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-trash-o:before { + content: "\f2ed"; } + +.fa.fa-home:before { + content: "\f015"; } + +.fa.fa-file-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-o:before { + content: "\f15b"; } + +.fa.fa-clock-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-clock-o:before { + content: "\f017"; } + +.fa.fa-arrow-circle-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-down:before { + content: "\f358"; } + +.fa.fa-arrow-circle-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-up:before { + content: "\f35b"; } + +.fa.fa-play-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-play-circle-o:before { + content: "\f144"; } + +.fa.fa-repeat:before { + content: "\f01e"; } + +.fa.fa-rotate-right:before { + content: "\f01e"; } + +.fa.fa-refresh:before { + content: "\f021"; } + +.fa.fa-list-alt { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-list-alt:before { + content: "\f022"; } + +.fa.fa-dedent:before { + content: "\f03b"; } + +.fa.fa-video-camera:before { + content: "\f03d"; } + +.fa.fa-picture-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-picture-o:before { + content: "\f03e"; } + +.fa.fa-photo { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-photo:before { + content: "\f03e"; } + +.fa.fa-image { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-image:before { + content: "\f03e"; } + +.fa.fa-map-marker:before { + content: "\f3c5"; } + +.fa.fa-pencil-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-pencil-square-o:before { + content: "\f044"; } + +.fa.fa-edit { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-edit:before { + content: "\f044"; } + +.fa.fa-share-square-o:before { + content: "\f14d"; } + +.fa.fa-check-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-check-square-o:before { + content: "\f14a"; } + +.fa.fa-arrows:before { + content: "\f0b2"; } + +.fa.fa-times-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-times-circle-o:before { + content: "\f057"; } + +.fa.fa-check-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-check-circle-o:before { + content: "\f058"; } + +.fa.fa-mail-forward:before { + content: "\f064"; } + +.fa.fa-expand:before { + content: "\f424"; } + +.fa.fa-compress:before { + content: "\f422"; } + +.fa.fa-eye { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-eye-slash { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-warning:before { + content: "\f071"; } + +.fa.fa-calendar:before { + content: "\f073"; } + +.fa.fa-arrows-v:before { + content: "\f338"; } + +.fa.fa-arrows-h:before { + content: "\f337"; } + +.fa.fa-bar-chart:before { + content: "\e0e3"; } + +.fa.fa-bar-chart-o:before { + content: "\e0e3"; } + +.fa.fa-twitter-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-twitter-square:before { + content: "\f081"; } + +.fa.fa-facebook-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-facebook-square:before { + content: "\f082"; } + +.fa.fa-gears:before { + content: "\f085"; } + +.fa.fa-thumbs-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-thumbs-o-up:before { + content: "\f164"; } + +.fa.fa-thumbs-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-thumbs-o-down:before { + content: "\f165"; } + +.fa.fa-heart-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-heart-o:before { + content: "\f004"; } + +.fa.fa-sign-out:before { + content: "\f2f5"; } + +.fa.fa-linkedin-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-linkedin-square:before { + content: "\f08c"; } + +.fa.fa-thumb-tack:before { + content: "\f08d"; } + +.fa.fa-external-link:before { + content: "\f35d"; } + +.fa.fa-sign-in:before { + content: "\f2f6"; } + +.fa.fa-github-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-github-square:before { + content: "\f092"; } + +.fa.fa-lemon-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-lemon-o:before { + content: "\f094"; } + +.fa.fa-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-square-o:before { + content: "\f0c8"; } + +.fa.fa-bookmark-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-bookmark-o:before { + content: "\f02e"; } + +.fa.fa-twitter { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-facebook { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-facebook:before { + content: "\f39e"; } + +.fa.fa-facebook-f { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-facebook-f:before { + content: "\f39e"; } + +.fa.fa-github { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-credit-card { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-feed:before { + content: "\f09e"; } + +.fa.fa-hdd-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hdd-o:before { + content: "\f0a0"; } + +.fa.fa-hand-o-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-o-right:before { + content: "\f0a4"; } + +.fa.fa-hand-o-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-o-left:before { + content: "\f0a5"; } + +.fa.fa-hand-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-o-up:before { + content: "\f0a6"; } + +.fa.fa-hand-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-o-down:before { + content: "\f0a7"; } + +.fa.fa-globe:before { + content: "\f57d"; } + +.fa.fa-tasks:before { + content: "\f828"; } + +.fa.fa-arrows-alt:before { + content: "\f31e"; } + +.fa.fa-group:before { + content: "\f0c0"; } + +.fa.fa-chain:before { + content: "\f0c1"; } + +.fa.fa-cut:before { + content: "\f0c4"; } + +.fa.fa-files-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-files-o:before { + content: "\f0c5"; } + +.fa.fa-floppy-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-floppy-o:before { + content: "\f0c7"; } + +.fa.fa-save { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-save:before { + content: "\f0c7"; } + +.fa.fa-navicon:before { + content: "\f0c9"; } + +.fa.fa-reorder:before { + content: "\f0c9"; } + +.fa.fa-magic:before { + content: "\e2ca"; } + +.fa.fa-pinterest { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-pinterest-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa.fa-google-plus-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa.fa-google-plus { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google-plus:before { + content: "\f0d5"; } + +.fa.fa-money:before { + content: "\f3d1"; } + +.fa.fa-unsorted:before { + content: "\f0dc"; } + +.fa.fa-sort-desc:before { + content: "\f0dd"; } + +.fa.fa-sort-asc:before { + content: "\f0de"; } + +.fa.fa-linkedin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-linkedin:before { + content: "\f0e1"; } + +.fa.fa-rotate-left:before { + content: "\f0e2"; } + +.fa.fa-legal:before { + content: "\f0e3"; } + +.fa.fa-tachometer:before { + content: "\f625"; } + +.fa.fa-dashboard:before { + content: "\f625"; } + +.fa.fa-comment-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-comment-o:before { + content: "\f075"; } + +.fa.fa-comments-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-comments-o:before { + content: "\f086"; } + +.fa.fa-flash:before { + content: "\f0e7"; } + +.fa.fa-clipboard:before { + content: "\f0ea"; } + +.fa.fa-lightbulb-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-lightbulb-o:before { + content: "\f0eb"; } + +.fa.fa-exchange:before { + content: "\f362"; } + +.fa.fa-cloud-download:before { + content: "\f0ed"; } + +.fa.fa-cloud-upload:before { + content: "\f0ee"; } + +.fa.fa-bell-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-bell-o:before { + content: "\f0f3"; } + +.fa.fa-cutlery:before { + content: "\f2e7"; } + +.fa.fa-file-text-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-text-o:before { + content: "\f15c"; } + +.fa.fa-building-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-building-o:before { + content: "\f1ad"; } + +.fa.fa-hospital-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hospital-o:before { + content: "\f0f8"; } + +.fa.fa-tablet:before { + content: "\f3fa"; } + +.fa.fa-mobile:before { + content: "\f3cd"; } + +.fa.fa-mobile-phone:before { + content: "\f3cd"; } + +.fa.fa-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-circle-o:before { + content: "\f111"; } + +.fa.fa-mail-reply:before { + content: "\f3e5"; } + +.fa.fa-github-alt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-folder-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-folder-o:before { + content: "\f07b"; } + +.fa.fa-folder-open-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-folder-open-o:before { + content: "\f07c"; } + +.fa.fa-smile-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-smile-o:before { + content: "\f118"; } + +.fa.fa-frown-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-frown-o:before { + content: "\f119"; } + +.fa.fa-meh-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-meh-o:before { + content: "\f11a"; } + +.fa.fa-keyboard-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-keyboard-o:before { + content: "\f11c"; } + +.fa.fa-flag-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-flag-o:before { + content: "\f024"; } + +.fa.fa-mail-reply-all:before { + content: "\f122"; } + +.fa.fa-star-half-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-star-half-o:before { + content: "\f5c0"; } + +.fa.fa-star-half-empty { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-star-half-empty:before { + content: "\f5c0"; } + +.fa.fa-star-half-full { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-star-half-full:before { + content: "\f5c0"; } + +.fa.fa-code-fork:before { + content: "\f126"; } + +.fa.fa-chain-broken:before { + content: "\f127"; } + +.fa.fa-unlink:before { + content: "\f127"; } + +.fa.fa-calendar-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-calendar-o:before { + content: "\f133"; } + +.fa.fa-maxcdn { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-html5 { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-css3 { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-unlock-alt:before { + content: "\f09c"; } + +.fa.fa-minus-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-minus-square-o:before { + content: "\f146"; } + +.fa.fa-level-up:before { + content: "\f3bf"; } + +.fa.fa-level-down:before { + content: "\f3be"; } + +.fa.fa-pencil-square:before { + content: "\f14b"; } + +.fa.fa-external-link-square:before { + content: "\f360"; } + +.fa.fa-compass { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-down:before { + content: "\f150"; } + +.fa.fa-toggle-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-toggle-down:before { + content: "\f150"; } + +.fa.fa-caret-square-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-up:before { + content: "\f151"; } + +.fa.fa-toggle-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-toggle-up:before { + content: "\f151"; } + +.fa.fa-caret-square-o-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-right:before { + content: "\f152"; } + +.fa.fa-toggle-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-toggle-right:before { + content: "\f152"; } + +.fa.fa-eur:before { + content: "\f153"; } + +.fa.fa-euro:before { + content: "\f153"; } + +.fa.fa-gbp:before { + content: "\f154"; } + +.fa.fa-usd:before { + content: "\24"; } + +.fa.fa-dollar:before { + content: "\24"; } + +.fa.fa-inr:before { + content: "\e1bc"; } + +.fa.fa-rupee:before { + content: "\e1bc"; } + +.fa.fa-jpy:before { + content: "\f157"; } + +.fa.fa-cny:before { + content: "\f157"; } + +.fa.fa-rmb:before { + content: "\f157"; } + +.fa.fa-yen:before { + content: "\f157"; } + +.fa.fa-rub:before { + content: "\f158"; } + +.fa.fa-ruble:before { + content: "\f158"; } + +.fa.fa-rouble:before { + content: "\f158"; } + +.fa.fa-krw:before { + content: "\f159"; } + +.fa.fa-won:before { + content: "\f159"; } + +.fa.fa-btc { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bitcoin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bitcoin:before { + content: "\f15a"; } + +.fa.fa-file-text:before { + content: "\f15c"; } + +.fa.fa-sort-alpha-asc:before { + content: "\f15d"; } + +.fa.fa-sort-alpha-desc:before { + content: "\f881"; } + +.fa.fa-sort-amount-asc:before { + content: "\f884"; } + +.fa.fa-sort-amount-desc:before { + content: "\f160"; } + +.fa.fa-sort-numeric-asc:before { + content: "\f162"; } + +.fa.fa-sort-numeric-desc:before { + content: "\f886"; } + +.fa.fa-youtube-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-youtube-square:before { + content: "\f431"; } + +.fa.fa-youtube { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-xing { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-xing-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-xing-square:before { + content: "\f169"; } + +.fa.fa-youtube-play { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-youtube-play:before { + content: "\f167"; } + +.fa.fa-dropbox { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-stack-overflow { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-instagram { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-flickr { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-adn { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket-square:before { + content: "\f171"; } + +.fa.fa-tumblr { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-tumblr-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-tumblr-square:before { + content: "\f174"; } + +.fa.fa-long-arrow-down:before { + content: "\f309"; } + +.fa.fa-long-arrow-up:before { + content: "\f30c"; } + +.fa.fa-long-arrow-left:before { + content: "\f30a"; } + +.fa.fa-long-arrow-right:before { + content: "\f30b"; } + +.fa.fa-apple { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-windows { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-android { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-linux { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-dribbble { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-skype { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-foursquare { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-trello { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-gratipay { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-gittip { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-gittip:before { + content: "\f184"; } + +.fa.fa-sun-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-sun-o:before { + content: "\f185"; } + +.fa.fa-moon-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-moon-o:before { + content: "\f186"; } + +.fa.fa-vk { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-weibo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-renren { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-pagelines { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-stack-exchange { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-right:before { + content: "\f35a"; } + +.fa.fa-arrow-circle-o-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-left:before { + content: "\f359"; } + +.fa.fa-caret-square-o-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-left:before { + content: "\f191"; } + +.fa.fa-toggle-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-toggle-left:before { + content: "\f191"; } + +.fa.fa-dot-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-dot-circle-o:before { + content: "\f192"; } + +.fa.fa-vimeo-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-vimeo-square:before { + content: "\f194"; } + +.fa.fa-try:before { + content: "\e2bb"; } + +.fa.fa-turkish-lira:before { + content: "\e2bb"; } + +.fa.fa-plus-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-plus-square-o:before { + content: "\f0fe"; } + +.fa.fa-slack { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wordpress { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-openid { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-institution:before { + content: "\f19c"; } + +.fa.fa-bank:before { + content: "\f19c"; } + +.fa.fa-mortar-board:before { + content: "\f19d"; } + +.fa.fa-yahoo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-reddit { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-reddit-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-reddit-square:before { + content: "\f1a2"; } + +.fa.fa-stumbleupon-circle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-stumbleupon { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-delicious { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-digg { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper-pp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper-alt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-drupal { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-joomla { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-behance { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-behance-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-behance-square:before { + content: "\f1b5"; } + +.fa.fa-steam { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-steam-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-steam-square:before { + content: "\f1b7"; } + +.fa.fa-automobile:before { + content: "\f1b9"; } + +.fa.fa-cab:before { + content: "\f1ba"; } + +.fa.fa-spotify { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-deviantart { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-soundcloud { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-file-pdf-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-pdf-o:before { + content: "\f1c1"; } + +.fa.fa-file-word-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-word-o:before { + content: "\f1c2"; } + +.fa.fa-file-excel-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-excel-o:before { + content: "\f1c3"; } + +.fa.fa-file-powerpoint-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-powerpoint-o:before { + content: "\f1c4"; } + +.fa.fa-file-image-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-image-o:before { + content: "\f1c5"; } + +.fa.fa-file-photo-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-photo-o:before { + content: "\f1c5"; } + +.fa.fa-file-picture-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-picture-o:before { + content: "\f1c5"; } + +.fa.fa-file-archive-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-archive-o:before { + content: "\f1c6"; } + +.fa.fa-file-zip-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-zip-o:before { + content: "\f1c6"; } + +.fa.fa-file-audio-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-audio-o:before { + content: "\f1c7"; } + +.fa.fa-file-sound-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-sound-o:before { + content: "\f1c7"; } + +.fa.fa-file-video-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-video-o:before { + content: "\f1c8"; } + +.fa.fa-file-movie-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-movie-o:before { + content: "\f1c8"; } + +.fa.fa-file-code-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-file-code-o:before { + content: "\f1c9"; } + +.fa.fa-vine { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-codepen { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-jsfiddle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-life-bouy:before { + content: "\f1cd"; } + +.fa.fa-life-buoy:before { + content: "\f1cd"; } + +.fa.fa-life-saver:before { + content: "\f1cd"; } + +.fa.fa-support:before { + content: "\f1cd"; } + +.fa.fa-circle-o-notch:before { + content: "\f1ce"; } + +.fa.fa-rebel { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-ra { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-ra:before { + content: "\f1d0"; } + +.fa.fa-resistance { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-resistance:before { + content: "\f1d0"; } + +.fa.fa-empire { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-ge { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-ge:before { + content: "\f1d1"; } + +.fa.fa-git-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-git-square:before { + content: "\f1d2"; } + +.fa.fa-git { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-hacker-news { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator-square:before { + content: "\f1d4"; } + +.fa.fa-yc-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-yc-square:before { + content: "\f1d4"; } + +.fa.fa-tencent-weibo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-qq { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-weixin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wechat { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wechat:before { + content: "\f1d7"; } + +.fa.fa-send:before { + content: "\f1d8"; } + +.fa.fa-paper-plane-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-paper-plane-o:before { + content: "\f1d8"; } + +.fa.fa-send-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-send-o:before { + content: "\f1d8"; } + +.fa.fa-circle-thin { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-circle-thin:before { + content: "\f111"; } + +.fa.fa-header:before { + content: "\f1dc"; } + +.fa.fa-futbol-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-futbol-o:before { + content: "\f1e3"; } + +.fa.fa-soccer-ball-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-soccer-ball-o:before { + content: "\f1e3"; } + +.fa.fa-slideshare { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-twitch { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-yelp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-newspaper-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-newspaper-o:before { + content: "\f1ea"; } + +.fa.fa-paypal { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google-wallet { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-visa { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-mastercard { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-discover { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-amex { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-paypal { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-stripe { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bell-slash-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-bell-slash-o:before { + content: "\f1f6"; } + +.fa.fa-trash:before { + content: "\f2ed"; } + +.fa.fa-copyright { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-eyedropper:before { + content: "\f1fb"; } + +.fa.fa-area-chart:before { + content: "\f1fe"; } + +.fa.fa-pie-chart:before { + content: "\f200"; } + +.fa.fa-line-chart:before { + content: "\f201"; } + +.fa.fa-lastfm { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-lastfm-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-lastfm-square:before { + content: "\f203"; } + +.fa.fa-ioxhost { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-angellist { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-cc:before { + content: "\f20a"; } + +.fa.fa-ils:before { + content: "\f20b"; } + +.fa.fa-shekel:before { + content: "\f20b"; } + +.fa.fa-sheqel:before { + content: "\f20b"; } + +.fa.fa-buysellads { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-connectdevelop { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-dashcube { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-forumbee { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-leanpub { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-sellsy { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-shirtsinbulk { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-simplybuilt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-skyatlas { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-diamond { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-diamond:before { + content: "\f3a5"; } + +.fa.fa-transgender:before { + content: "\f224"; } + +.fa.fa-intersex:before { + content: "\f224"; } + +.fa.fa-transgender-alt:before { + content: "\f225"; } + +.fa.fa-facebook-official { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-facebook-official:before { + content: "\f09a"; } + +.fa.fa-pinterest-p { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-whatsapp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-hotel:before { + content: "\f236"; } + +.fa.fa-viacoin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-medium { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-yc { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-yc:before { + content: "\f23b"; } + +.fa.fa-optin-monster { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-opencart { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-expeditedssl { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-battery-4:before { + content: "\f240"; } + +.fa.fa-battery:before { + content: "\f240"; } + +.fa.fa-battery-3:before { + content: "\f241"; } + +.fa.fa-battery-2:before { + content: "\f242"; } + +.fa.fa-battery-1:before { + content: "\f243"; } + +.fa.fa-battery-0:before { + content: "\f244"; } + +.fa.fa-object-group { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-object-ungroup { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-sticky-note-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-sticky-note-o:before { + content: "\f249"; } + +.fa.fa-cc-jcb { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-cc-diners-club { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-clone { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hourglass-o:before { + content: "\f254"; } + +.fa.fa-hourglass-1:before { + content: "\f251"; } + +.fa.fa-hourglass-2:before { + content: "\f252"; } + +.fa.fa-hourglass-3:before { + content: "\f253"; } + +.fa.fa-hand-rock-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-rock-o:before { + content: "\f255"; } + +.fa.fa-hand-grab-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-grab-o:before { + content: "\f255"; } + +.fa.fa-hand-paper-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-paper-o:before { + content: "\f256"; } + +.fa.fa-hand-stop-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-stop-o:before { + content: "\f256"; } + +.fa.fa-hand-scissors-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-scissors-o:before { + content: "\f257"; } + +.fa.fa-hand-lizard-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-lizard-o:before { + content: "\f258"; } + +.fa.fa-hand-spock-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-spock-o:before { + content: "\f259"; } + +.fa.fa-hand-pointer-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-pointer-o:before { + content: "\f25a"; } + +.fa.fa-hand-peace-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-hand-peace-o:before { + content: "\f25b"; } + +.fa.fa-registered { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-creative-commons { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-gg { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-gg-circle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa.fa-get-pocket { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wikipedia-w { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-safari { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-chrome { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-firefox { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-opera { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-internet-explorer { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-television:before { + content: "\f26c"; } + +.fa.fa-contao { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-500px { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-amazon { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-calendar-plus-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-calendar-plus-o:before { + content: "\f271"; } + +.fa.fa-calendar-minus-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-calendar-minus-o:before { + content: "\f272"; } + +.fa.fa-calendar-times-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-calendar-times-o:before { + content: "\f273"; } + +.fa.fa-calendar-check-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-calendar-check-o:before { + content: "\f274"; } + +.fa.fa-map-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-map-o:before { + content: "\f279"; } + +.fa.fa-commenting:before { + content: "\f4ad"; } + +.fa.fa-commenting-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-commenting-o:before { + content: "\f4ad"; } + +.fa.fa-houzz { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-vimeo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-vimeo:before { + content: "\f27d"; } + +.fa.fa-black-tie { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-fonticons { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-reddit-alien { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-edge { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-credit-card-alt:before { + content: "\f09d"; } + +.fa.fa-codiepie { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-modx { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-fort-awesome { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-usb { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-product-hunt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-mixcloud { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-scribd { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-pause-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-pause-circle-o:before { + content: "\f28b"; } + +.fa.fa-stop-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-stop-circle-o:before { + content: "\f28d"; } + +.fa.fa-bluetooth { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-bluetooth-b { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-gitlab { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wpbeginner { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wpforms { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-envira { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wheelchair-alt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wheelchair-alt:before { + content: "\f368"; } + +.fa.fa-question-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-question-circle-o:before { + content: "\f059"; } + +.fa.fa-volume-control-phone:before { + content: "\f2a0"; } + +.fa.fa-asl-interpreting:before { + content: "\f2a3"; } + +.fa.fa-deafness:before { + content: "\f2a4"; } + +.fa.fa-hard-of-hearing:before { + content: "\f2a4"; } + +.fa.fa-glide { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-glide-g { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-signing:before { + content: "\f2a7"; } + +.fa.fa-viadeo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-viadeo-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa.fa-snapchat { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-ghost { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-ghost:before { + content: "\f2ab"; } + +.fa.fa-snapchat-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa.fa-pied-piper { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-first-order { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-yoast { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-themeisle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-official { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-official:before { + content: "\f2b3"; } + +.fa.fa-google-plus-circle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-circle:before { + content: "\f2b3"; } + +.fa.fa-font-awesome { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-fa { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-fa:before { + content: "\f2b4"; } + +.fa.fa-handshake-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-handshake-o:before { + content: "\f2b5"; } + +.fa.fa-envelope-open-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-envelope-open-o:before { + content: "\f2b6"; } + +.fa.fa-linode { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-address-book-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-address-book-o:before { + content: "\f2b9"; } + +.fa.fa-vcard:before { + content: "\f2bb"; } + +.fa.fa-address-card-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-address-card-o:before { + content: "\f2bb"; } + +.fa.fa-vcard-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-vcard-o:before { + content: "\f2bb"; } + +.fa.fa-user-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-user-circle-o:before { + content: "\f2bd"; } + +.fa.fa-user-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-user-o:before { + content: "\f007"; } + +.fa.fa-id-badge { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-drivers-license:before { + content: "\f2c2"; } + +.fa.fa-id-card-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-id-card-o:before { + content: "\f2c2"; } + +.fa.fa-drivers-license-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-drivers-license-o:before { + content: "\f2c2"; } + +.fa.fa-quora { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-free-code-camp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-telegram { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-thermometer-4:before { + content: "\f2c7"; } + +.fa.fa-thermometer:before { + content: "\f2c7"; } + +.fa.fa-thermometer-3:before { + content: "\f2c8"; } + +.fa.fa-thermometer-2:before { + content: "\f2c9"; } + +.fa.fa-thermometer-1:before { + content: "\f2ca"; } + +.fa.fa-thermometer-0:before { + content: "\f2cb"; } + +.fa.fa-bathtub:before { + content: "\f2cd"; } + +.fa.fa-s15:before { + content: "\f2cd"; } + +.fa.fa-window-maximize { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-window-restore { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-times-rectangle:before { + content: "\f410"; } + +.fa.fa-window-close-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-window-close-o:before { + content: "\f410"; } + +.fa.fa-times-rectangle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-times-rectangle-o:before { + content: "\f410"; } + +.fa.fa-bandcamp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-grav { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-etsy { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-imdb { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-ravelry { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-eercast { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-eercast:before { + content: "\f2da"; } + +.fa.fa-snowflake-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; } + +.fa.fa-snowflake-o:before { + content: "\f2dc"; } + +.fa.fa-superpowers { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-wpexplorer { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } + +.fa.fa-meetup { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; } diff --git a/deps/font-awesome-6.5.2/css/v4-shims.min.css b/deps/font-awesome-6.5.2/css/v4-shims.min.css new file mode 100644 index 0000000..09baf5f --- /dev/null +++ b/deps/font-awesome-6.5.2/css/v4-shims.min.css @@ -0,0 +1,6 @@ +/*! + * Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +.fa.fa-glass:before{content:"\f000"}.fa.fa-envelope-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-envelope-o:before{content:"\f0e0"}.fa.fa-star-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-star-o:before{content:"\f005"}.fa.fa-close:before,.fa.fa-remove:before{content:"\f00d"}.fa.fa-gear:before{content:"\f013"}.fa.fa-trash-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-trash-o:before{content:"\f2ed"}.fa.fa-home:before{content:"\f015"}.fa.fa-file-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-o:before{content:"\f15b"}.fa.fa-clock-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-clock-o:before{content:"\f017"}.fa.fa-arrow-circle-o-down{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-arrow-circle-o-down:before{content:"\f358"}.fa.fa-arrow-circle-o-up{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-arrow-circle-o-up:before{content:"\f35b"}.fa.fa-play-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-play-circle-o:before{content:"\f144"}.fa.fa-repeat:before,.fa.fa-rotate-right:before{content:"\f01e"}.fa.fa-refresh:before{content:"\f021"}.fa.fa-list-alt{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-list-alt:before{content:"\f022"}.fa.fa-dedent:before{content:"\f03b"}.fa.fa-video-camera:before{content:"\f03d"}.fa.fa-picture-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-picture-o:before{content:"\f03e"}.fa.fa-photo{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-photo:before{content:"\f03e"}.fa.fa-image{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-image:before{content:"\f03e"}.fa.fa-map-marker:before{content:"\f3c5"}.fa.fa-pencil-square-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-pencil-square-o:before{content:"\f044"}.fa.fa-edit{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-edit:before{content:"\f044"}.fa.fa-share-square-o:before{content:"\f14d"}.fa.fa-check-square-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-check-square-o:before{content:"\f14a"}.fa.fa-arrows:before{content:"\f0b2"}.fa.fa-times-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-times-circle-o:before{content:"\f057"}.fa.fa-check-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-check-circle-o:before{content:"\f058"}.fa.fa-mail-forward:before{content:"\f064"}.fa.fa-expand:before{content:"\f424"}.fa.fa-compress:before{content:"\f422"}.fa.fa-eye,.fa.fa-eye-slash{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-warning:before{content:"\f071"}.fa.fa-calendar:before{content:"\f073"}.fa.fa-arrows-v:before{content:"\f338"}.fa.fa-arrows-h:before{content:"\f337"}.fa.fa-bar-chart-o:before,.fa.fa-bar-chart:before{content:"\e0e3"}.fa.fa-twitter-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-twitter-square:before{content:"\f081"}.fa.fa-facebook-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-facebook-square:before{content:"\f082"}.fa.fa-gears:before{content:"\f085"}.fa.fa-thumbs-o-up{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-thumbs-o-up:before{content:"\f164"}.fa.fa-thumbs-o-down{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-thumbs-o-down:before{content:"\f165"}.fa.fa-heart-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-heart-o:before{content:"\f004"}.fa.fa-sign-out:before{content:"\f2f5"}.fa.fa-linkedin-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-linkedin-square:before{content:"\f08c"}.fa.fa-thumb-tack:before{content:"\f08d"}.fa.fa-external-link:before{content:"\f35d"}.fa.fa-sign-in:before{content:"\f2f6"}.fa.fa-github-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-github-square:before{content:"\f092"}.fa.fa-lemon-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-lemon-o:before{content:"\f094"}.fa.fa-square-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-square-o:before{content:"\f0c8"}.fa.fa-bookmark-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-bookmark-o:before{content:"\f02e"}.fa.fa-facebook,.fa.fa-twitter{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-facebook:before{content:"\f39e"}.fa.fa-facebook-f{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-facebook-f:before{content:"\f39e"}.fa.fa-github{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-credit-card{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-feed:before{content:"\f09e"}.fa.fa-hdd-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hdd-o:before{content:"\f0a0"}.fa.fa-hand-o-right{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-o-right:before{content:"\f0a4"}.fa.fa-hand-o-left{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-o-left:before{content:"\f0a5"}.fa.fa-hand-o-up{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-o-up:before{content:"\f0a6"}.fa.fa-hand-o-down{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-o-down:before{content:"\f0a7"}.fa.fa-globe:before{content:"\f57d"}.fa.fa-tasks:before{content:"\f828"}.fa.fa-arrows-alt:before{content:"\f31e"}.fa.fa-group:before{content:"\f0c0"}.fa.fa-chain:before{content:"\f0c1"}.fa.fa-cut:before{content:"\f0c4"}.fa.fa-files-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-files-o:before{content:"\f0c5"}.fa.fa-floppy-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-floppy-o:before{content:"\f0c7"}.fa.fa-save{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-save:before{content:"\f0c7"}.fa.fa-navicon:before,.fa.fa-reorder:before{content:"\f0c9"}.fa.fa-magic:before{content:"\e2ca"}.fa.fa-pinterest,.fa.fa-pinterest-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-pinterest-square:before{content:"\f0d3"}.fa.fa-google-plus-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-google-plus-square:before{content:"\f0d4"}.fa.fa-google-plus{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-google-plus:before{content:"\f0d5"}.fa.fa-money:before{content:"\f3d1"}.fa.fa-unsorted:before{content:"\f0dc"}.fa.fa-sort-desc:before{content:"\f0dd"}.fa.fa-sort-asc:before{content:"\f0de"}.fa.fa-linkedin{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-linkedin:before{content:"\f0e1"}.fa.fa-rotate-left:before{content:"\f0e2"}.fa.fa-legal:before{content:"\f0e3"}.fa.fa-dashboard:before,.fa.fa-tachometer:before{content:"\f625"}.fa.fa-comment-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-comment-o:before{content:"\f075"}.fa.fa-comments-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-comments-o:before{content:"\f086"}.fa.fa-flash:before{content:"\f0e7"}.fa.fa-clipboard:before{content:"\f0ea"}.fa.fa-lightbulb-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-lightbulb-o:before{content:"\f0eb"}.fa.fa-exchange:before{content:"\f362"}.fa.fa-cloud-download:before{content:"\f0ed"}.fa.fa-cloud-upload:before{content:"\f0ee"}.fa.fa-bell-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-bell-o:before{content:"\f0f3"}.fa.fa-cutlery:before{content:"\f2e7"}.fa.fa-file-text-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-text-o:before{content:"\f15c"}.fa.fa-building-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-building-o:before{content:"\f1ad"}.fa.fa-hospital-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hospital-o:before{content:"\f0f8"}.fa.fa-tablet:before{content:"\f3fa"}.fa.fa-mobile-phone:before,.fa.fa-mobile:before{content:"\f3cd"}.fa.fa-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-circle-o:before{content:"\f111"}.fa.fa-mail-reply:before{content:"\f3e5"}.fa.fa-github-alt{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-folder-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-folder-o:before{content:"\f07b"}.fa.fa-folder-open-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-folder-open-o:before{content:"\f07c"}.fa.fa-smile-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-smile-o:before{content:"\f118"}.fa.fa-frown-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-frown-o:before{content:"\f119"}.fa.fa-meh-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-meh-o:before{content:"\f11a"}.fa.fa-keyboard-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-keyboard-o:before{content:"\f11c"}.fa.fa-flag-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-flag-o:before{content:"\f024"}.fa.fa-mail-reply-all:before{content:"\f122"}.fa.fa-star-half-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-star-half-o:before{content:"\f5c0"}.fa.fa-star-half-empty{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-star-half-empty:before{content:"\f5c0"}.fa.fa-star-half-full{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-star-half-full:before{content:"\f5c0"}.fa.fa-code-fork:before{content:"\f126"}.fa.fa-chain-broken:before,.fa.fa-unlink:before{content:"\f127"}.fa.fa-calendar-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-calendar-o:before{content:"\f133"}.fa.fa-css3,.fa.fa-html5,.fa.fa-maxcdn{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-unlock-alt:before{content:"\f09c"}.fa.fa-minus-square-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-minus-square-o:before{content:"\f146"}.fa.fa-level-up:before{content:"\f3bf"}.fa.fa-level-down:before{content:"\f3be"}.fa.fa-pencil-square:before{content:"\f14b"}.fa.fa-external-link-square:before{content:"\f360"}.fa.fa-compass{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-caret-square-o-down{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-caret-square-o-down:before{content:"\f150"}.fa.fa-toggle-down{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-toggle-down:before{content:"\f150"}.fa.fa-caret-square-o-up{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-caret-square-o-up:before{content:"\f151"}.fa.fa-toggle-up{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-toggle-up:before{content:"\f151"}.fa.fa-caret-square-o-right{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-caret-square-o-right:before{content:"\f152"}.fa.fa-toggle-right{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-toggle-right:before{content:"\f152"}.fa.fa-eur:before,.fa.fa-euro:before{content:"\f153"}.fa.fa-gbp:before{content:"\f154"}.fa.fa-dollar:before,.fa.fa-usd:before{content:"\24"}.fa.fa-inr:before,.fa.fa-rupee:before{content:"\e1bc"}.fa.fa-cny:before,.fa.fa-jpy:before,.fa.fa-rmb:before,.fa.fa-yen:before{content:"\f157"}.fa.fa-rouble:before,.fa.fa-rub:before,.fa.fa-ruble:before{content:"\f158"}.fa.fa-krw:before,.fa.fa-won:before{content:"\f159"}.fa.fa-bitcoin,.fa.fa-btc{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-bitcoin:before{content:"\f15a"}.fa.fa-file-text:before{content:"\f15c"}.fa.fa-sort-alpha-asc:before{content:"\f15d"}.fa.fa-sort-alpha-desc:before{content:"\f881"}.fa.fa-sort-amount-asc:before{content:"\f884"}.fa.fa-sort-amount-desc:before{content:"\f160"}.fa.fa-sort-numeric-asc:before{content:"\f162"}.fa.fa-sort-numeric-desc:before{content:"\f886"}.fa.fa-youtube-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-youtube-square:before{content:"\f431"}.fa.fa-xing,.fa.fa-xing-square,.fa.fa-youtube{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-xing-square:before{content:"\f169"}.fa.fa-youtube-play{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-youtube-play:before{content:"\f167"}.fa.fa-adn,.fa.fa-bitbucket,.fa.fa-bitbucket-square,.fa.fa-dropbox,.fa.fa-flickr,.fa.fa-instagram,.fa.fa-stack-overflow{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-bitbucket-square:before{content:"\f171"}.fa.fa-tumblr,.fa.fa-tumblr-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-tumblr-square:before{content:"\f174"}.fa.fa-long-arrow-down:before{content:"\f309"}.fa.fa-long-arrow-up:before{content:"\f30c"}.fa.fa-long-arrow-left:before{content:"\f30a"}.fa.fa-long-arrow-right:before{content:"\f30b"}.fa.fa-android,.fa.fa-apple,.fa.fa-dribbble,.fa.fa-foursquare,.fa.fa-gittip,.fa.fa-gratipay,.fa.fa-linux,.fa.fa-skype,.fa.fa-trello,.fa.fa-windows{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-gittip:before{content:"\f184"}.fa.fa-sun-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-sun-o:before{content:"\f185"}.fa.fa-moon-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-moon-o:before{content:"\f186"}.fa.fa-pagelines,.fa.fa-renren,.fa.fa-stack-exchange,.fa.fa-vk,.fa.fa-weibo{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-arrow-circle-o-right{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-arrow-circle-o-right:before{content:"\f35a"}.fa.fa-arrow-circle-o-left{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-arrow-circle-o-left:before{content:"\f359"}.fa.fa-caret-square-o-left{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-caret-square-o-left:before{content:"\f191"}.fa.fa-toggle-left{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-toggle-left:before{content:"\f191"}.fa.fa-dot-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-dot-circle-o:before{content:"\f192"}.fa.fa-vimeo-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-vimeo-square:before{content:"\f194"}.fa.fa-try:before,.fa.fa-turkish-lira:before{content:"\e2bb"}.fa.fa-plus-square-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-plus-square-o:before{content:"\f0fe"}.fa.fa-openid,.fa.fa-slack,.fa.fa-wordpress{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-bank:before,.fa.fa-institution:before{content:"\f19c"}.fa.fa-mortar-board:before{content:"\f19d"}.fa.fa-google,.fa.fa-reddit,.fa.fa-reddit-square,.fa.fa-yahoo{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-reddit-square:before{content:"\f1a2"}.fa.fa-behance,.fa.fa-behance-square,.fa.fa-delicious,.fa.fa-digg,.fa.fa-drupal,.fa.fa-joomla,.fa.fa-pied-piper-alt,.fa.fa-pied-piper-pp,.fa.fa-stumbleupon,.fa.fa-stumbleupon-circle{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-behance-square:before{content:"\f1b5"}.fa.fa-steam,.fa.fa-steam-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-steam-square:before{content:"\f1b7"}.fa.fa-automobile:before{content:"\f1b9"}.fa.fa-cab:before{content:"\f1ba"}.fa.fa-deviantart,.fa.fa-soundcloud,.fa.fa-spotify{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-file-pdf-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-pdf-o:before{content:"\f1c1"}.fa.fa-file-word-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-word-o:before{content:"\f1c2"}.fa.fa-file-excel-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-excel-o:before{content:"\f1c3"}.fa.fa-file-powerpoint-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-powerpoint-o:before{content:"\f1c4"}.fa.fa-file-image-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-image-o:before{content:"\f1c5"}.fa.fa-file-photo-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-photo-o:before{content:"\f1c5"}.fa.fa-file-picture-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-picture-o:before{content:"\f1c5"}.fa.fa-file-archive-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-archive-o:before{content:"\f1c6"}.fa.fa-file-zip-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-zip-o:before{content:"\f1c6"}.fa.fa-file-audio-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-audio-o:before{content:"\f1c7"}.fa.fa-file-sound-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-sound-o:before{content:"\f1c7"}.fa.fa-file-video-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-video-o:before{content:"\f1c8"}.fa.fa-file-movie-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-movie-o:before{content:"\f1c8"}.fa.fa-file-code-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-file-code-o:before{content:"\f1c9"}.fa.fa-codepen,.fa.fa-jsfiddle,.fa.fa-vine{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-life-bouy:before,.fa.fa-life-buoy:before,.fa.fa-life-saver:before,.fa.fa-support:before{content:"\f1cd"}.fa.fa-circle-o-notch:before{content:"\f1ce"}.fa.fa-ra,.fa.fa-rebel{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-ra:before{content:"\f1d0"}.fa.fa-resistance{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-resistance:before{content:"\f1d0"}.fa.fa-empire,.fa.fa-ge{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-ge:before{content:"\f1d1"}.fa.fa-git-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-git-square:before{content:"\f1d2"}.fa.fa-git,.fa.fa-hacker-news,.fa.fa-y-combinator-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-y-combinator-square:before{content:"\f1d4"}.fa.fa-yc-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-yc-square:before{content:"\f1d4"}.fa.fa-qq,.fa.fa-tencent-weibo,.fa.fa-wechat,.fa.fa-weixin{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-wechat:before{content:"\f1d7"}.fa.fa-send:before{content:"\f1d8"}.fa.fa-paper-plane-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-paper-plane-o:before{content:"\f1d8"}.fa.fa-send-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-send-o:before{content:"\f1d8"}.fa.fa-circle-thin{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-circle-thin:before{content:"\f111"}.fa.fa-header:before{content:"\f1dc"}.fa.fa-futbol-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-futbol-o:before{content:"\f1e3"}.fa.fa-soccer-ball-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-soccer-ball-o:before{content:"\f1e3"}.fa.fa-slideshare,.fa.fa-twitch,.fa.fa-yelp{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-newspaper-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-newspaper-o:before{content:"\f1ea"}.fa.fa-cc-amex,.fa.fa-cc-discover,.fa.fa-cc-mastercard,.fa.fa-cc-paypal,.fa.fa-cc-stripe,.fa.fa-cc-visa,.fa.fa-google-wallet,.fa.fa-paypal{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-bell-slash-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-bell-slash-o:before{content:"\f1f6"}.fa.fa-trash:before{content:"\f2ed"}.fa.fa-copyright{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-eyedropper:before{content:"\f1fb"}.fa.fa-area-chart:before{content:"\f1fe"}.fa.fa-pie-chart:before{content:"\f200"}.fa.fa-line-chart:before{content:"\f201"}.fa.fa-lastfm,.fa.fa-lastfm-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-lastfm-square:before{content:"\f203"}.fa.fa-angellist,.fa.fa-ioxhost{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-cc{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-cc:before{content:"\f20a"}.fa.fa-ils:before,.fa.fa-shekel:before,.fa.fa-sheqel:before{content:"\f20b"}.fa.fa-buysellads,.fa.fa-connectdevelop,.fa.fa-dashcube,.fa.fa-forumbee,.fa.fa-leanpub,.fa.fa-sellsy,.fa.fa-shirtsinbulk,.fa.fa-simplybuilt,.fa.fa-skyatlas{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-diamond{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-diamond:before{content:"\f3a5"}.fa.fa-intersex:before,.fa.fa-transgender:before{content:"\f224"}.fa.fa-transgender-alt:before{content:"\f225"}.fa.fa-facebook-official{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-facebook-official:before{content:"\f09a"}.fa.fa-pinterest-p,.fa.fa-whatsapp{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-hotel:before{content:"\f236"}.fa.fa-medium,.fa.fa-viacoin,.fa.fa-y-combinator,.fa.fa-yc{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-yc:before{content:"\f23b"}.fa.fa-expeditedssl,.fa.fa-opencart,.fa.fa-optin-monster{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-battery-4:before,.fa.fa-battery:before{content:"\f240"}.fa.fa-battery-3:before{content:"\f241"}.fa.fa-battery-2:before{content:"\f242"}.fa.fa-battery-1:before{content:"\f243"}.fa.fa-battery-0:before{content:"\f244"}.fa.fa-object-group,.fa.fa-object-ungroup,.fa.fa-sticky-note-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-sticky-note-o:before{content:"\f249"}.fa.fa-cc-diners-club,.fa.fa-cc-jcb{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-clone{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hourglass-o:before{content:"\f254"}.fa.fa-hourglass-1:before{content:"\f251"}.fa.fa-hourglass-2:before{content:"\f252"}.fa.fa-hourglass-3:before{content:"\f253"}.fa.fa-hand-rock-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-rock-o:before{content:"\f255"}.fa.fa-hand-grab-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-grab-o:before{content:"\f255"}.fa.fa-hand-paper-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-paper-o:before{content:"\f256"}.fa.fa-hand-stop-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-stop-o:before{content:"\f256"}.fa.fa-hand-scissors-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-scissors-o:before{content:"\f257"}.fa.fa-hand-lizard-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-lizard-o:before{content:"\f258"}.fa.fa-hand-spock-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-spock-o:before{content:"\f259"}.fa.fa-hand-pointer-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-pointer-o:before{content:"\f25a"}.fa.fa-hand-peace-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-hand-peace-o:before{content:"\f25b"}.fa.fa-registered{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-creative-commons,.fa.fa-gg,.fa.fa-gg-circle,.fa.fa-odnoklassniki,.fa.fa-odnoklassniki-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-odnoklassniki-square:before{content:"\f264"}.fa.fa-chrome,.fa.fa-firefox,.fa.fa-get-pocket,.fa.fa-internet-explorer,.fa.fa-opera,.fa.fa-safari,.fa.fa-wikipedia-w{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-television:before{content:"\f26c"}.fa.fa-500px,.fa.fa-amazon,.fa.fa-contao{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-calendar-plus-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-calendar-plus-o:before{content:"\f271"}.fa.fa-calendar-minus-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-calendar-minus-o:before{content:"\f272"}.fa.fa-calendar-times-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-calendar-times-o:before{content:"\f273"}.fa.fa-calendar-check-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-calendar-check-o:before{content:"\f274"}.fa.fa-map-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-map-o:before{content:"\f279"}.fa.fa-commenting:before{content:"\f4ad"}.fa.fa-commenting-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-commenting-o:before{content:"\f4ad"}.fa.fa-houzz,.fa.fa-vimeo{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-vimeo:before{content:"\f27d"}.fa.fa-black-tie,.fa.fa-edge,.fa.fa-fonticons,.fa.fa-reddit-alien{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-credit-card-alt:before{content:"\f09d"}.fa.fa-codiepie,.fa.fa-fort-awesome,.fa.fa-mixcloud,.fa.fa-modx,.fa.fa-product-hunt,.fa.fa-scribd,.fa.fa-usb{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-pause-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-pause-circle-o:before{content:"\f28b"}.fa.fa-stop-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-stop-circle-o:before{content:"\f28d"}.fa.fa-bluetooth,.fa.fa-bluetooth-b,.fa.fa-envira,.fa.fa-gitlab,.fa.fa-wheelchair-alt,.fa.fa-wpbeginner,.fa.fa-wpforms{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-wheelchair-alt:before{content:"\f368"}.fa.fa-question-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-question-circle-o:before{content:"\f059"}.fa.fa-volume-control-phone:before{content:"\f2a0"}.fa.fa-asl-interpreting:before{content:"\f2a3"}.fa.fa-deafness:before,.fa.fa-hard-of-hearing:before{content:"\f2a4"}.fa.fa-glide,.fa.fa-glide-g{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-signing:before{content:"\f2a7"}.fa.fa-viadeo,.fa.fa-viadeo-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-viadeo-square:before{content:"\f2aa"}.fa.fa-snapchat,.fa.fa-snapchat-ghost{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-snapchat-ghost:before{content:"\f2ab"}.fa.fa-snapchat-square{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-snapchat-square:before{content:"\f2ad"}.fa.fa-first-order,.fa.fa-google-plus-official,.fa.fa-pied-piper,.fa.fa-themeisle,.fa.fa-yoast{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-google-plus-official:before{content:"\f2b3"}.fa.fa-google-plus-circle{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-google-plus-circle:before{content:"\f2b3"}.fa.fa-fa,.fa.fa-font-awesome{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-fa:before{content:"\f2b4"}.fa.fa-handshake-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-handshake-o:before{content:"\f2b5"}.fa.fa-envelope-open-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-envelope-open-o:before{content:"\f2b6"}.fa.fa-linode{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-address-book-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-address-book-o:before{content:"\f2b9"}.fa.fa-vcard:before{content:"\f2bb"}.fa.fa-address-card-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-address-card-o:before{content:"\f2bb"}.fa.fa-vcard-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-vcard-o:before{content:"\f2bb"}.fa.fa-user-circle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-user-circle-o:before{content:"\f2bd"}.fa.fa-user-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-user-o:before{content:"\f007"}.fa.fa-id-badge{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-drivers-license:before{content:"\f2c2"}.fa.fa-id-card-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-id-card-o:before{content:"\f2c2"}.fa.fa-drivers-license-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-drivers-license-o:before{content:"\f2c2"}.fa.fa-free-code-camp,.fa.fa-quora,.fa.fa-telegram{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-thermometer-4:before,.fa.fa-thermometer:before{content:"\f2c7"}.fa.fa-thermometer-3:before{content:"\f2c8"}.fa.fa-thermometer-2:before{content:"\f2c9"}.fa.fa-thermometer-1:before{content:"\f2ca"}.fa.fa-thermometer-0:before{content:"\f2cb"}.fa.fa-bathtub:before,.fa.fa-s15:before{content:"\f2cd"}.fa.fa-window-maximize,.fa.fa-window-restore{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-times-rectangle:before{content:"\f410"}.fa.fa-window-close-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-window-close-o:before{content:"\f410"}.fa.fa-times-rectangle-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-times-rectangle-o:before{content:"\f410"}.fa.fa-bandcamp,.fa.fa-eercast,.fa.fa-etsy,.fa.fa-grav,.fa.fa-imdb,.fa.fa-ravelry{font-family:"Font Awesome 6 Brands";font-weight:400}.fa.fa-eercast:before{content:"\f2da"}.fa.fa-snowflake-o{font-family:"Font Awesome 6 Free";font-weight:400}.fa.fa-snowflake-o:before{content:"\f2dc"}.fa.fa-meetup,.fa.fa-superpowers,.fa.fa-wpexplorer{font-family:"Font Awesome 6 Brands";font-weight:400} \ No newline at end of file diff --git a/deps/font-awesome-6.5.2/webfonts/fa-brands-400.ttf b/deps/font-awesome-6.5.2/webfonts/fa-brands-400.ttf new file mode 100644 index 0000000..1fbb1f7 Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-brands-400.ttf differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-brands-400.woff2 b/deps/font-awesome-6.5.2/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000..5d28021 Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-brands-400.woff2 differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-regular-400.ttf b/deps/font-awesome-6.5.2/webfonts/fa-regular-400.ttf new file mode 100644 index 0000000..549d68d Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-regular-400.ttf differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-regular-400.woff2 b/deps/font-awesome-6.5.2/webfonts/fa-regular-400.woff2 new file mode 100644 index 0000000..18400d7 Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-regular-400.woff2 differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-solid-900.ttf b/deps/font-awesome-6.5.2/webfonts/fa-solid-900.ttf new file mode 100644 index 0000000..bb2a869 Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-solid-900.ttf differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-solid-900.woff2 b/deps/font-awesome-6.5.2/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000..758dd4f Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-solid-900.woff2 differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf b/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf new file mode 100644 index 0000000..8c5864c Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf differ diff --git a/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2 b/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2 new file mode 100644 index 0000000..f94bec2 Binary files /dev/null and b/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2 differ diff --git a/deps/headroom-0.11.0/headroom.min.js b/deps/headroom-0.11.0/headroom.min.js new file mode 100644 index 0000000..433069f --- /dev/null +++ b/deps/headroom-0.11.0/headroom.min.js @@ -0,0 +1,7 @@ +/*! + * headroom.js v0.11.0 - Give your page some headroom. Hide your header until you need it + * Copyright (c) 2020 Nick Williams - http://wicky.nillia.ms/headroom.js + * License: MIT + */ + +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t=t||self).Headroom=n()}(this,function(){"use strict";function t(){return"undefined"!=typeof window}function d(t){return function(t){return t&&t.document&&function(t){return 9===t.nodeType}(t.document)}(t)?function(t){var n=t.document,o=n.body,s=n.documentElement;return{scrollHeight:function(){return Math.max(o.scrollHeight,s.scrollHeight,o.offsetHeight,s.offsetHeight,o.clientHeight,s.clientHeight)},height:function(){return t.innerHeight||s.clientHeight||o.clientHeight},scrollY:function(){return void 0!==t.pageYOffset?t.pageYOffset:(s||o.parentNode||o).scrollTop}}}(t):function(t){return{scrollHeight:function(){return Math.max(t.scrollHeight,t.offsetHeight,t.clientHeight)},height:function(){return Math.max(t.offsetHeight,t.clientHeight)},scrollY:function(){return t.scrollTop}}}(t)}function n(t,s,e){var n,o=function(){var n=!1;try{var t={get passive(){n=!0}};window.addEventListener("test",t,t),window.removeEventListener("test",t,t)}catch(t){n=!1}return n}(),i=!1,r=d(t),l=r.scrollY(),a={};function c(){var t=Math.round(r.scrollY()),n=r.height(),o=r.scrollHeight();a.scrollY=t,a.lastScrollY=l,a.direction=ls.tolerance[a.direction],e(a),l=t,i=!1}function h(){i||(i=!0,n=requestAnimationFrame(c))}var u=!!o&&{passive:!0,capture:!1};return t.addEventListener("scroll",h,u),c(),{destroy:function(){cancelAnimationFrame(n),t.removeEventListener("scroll",h,u)}}}function o(t,n){n=n||{},Object.assign(this,o.options,n),this.classes=Object.assign({},o.options.classes,n.classes),this.elem=t,this.tolerance=function(t){return t===Object(t)?t:{down:t,up:t}}(this.tolerance),this.initialised=!1,this.frozen=!1}return o.prototype={constructor:o,init:function(){return o.cutsTheMustard&&!this.initialised&&(this.addClass("initial"),this.initialised=!0,setTimeout(function(t){t.scrollTracker=n(t.scroller,{offset:t.offset,tolerance:t.tolerance},t.update.bind(t))},100,this)),this},destroy:function(){this.initialised=!1,Object.keys(this.classes).forEach(this.removeClass,this),this.scrollTracker.destroy()},unpin:function(){!this.hasClass("pinned")&&this.hasClass("unpinned")||(this.addClass("unpinned"),this.removeClass("pinned"),this.onUnpin&&this.onUnpin.call(this))},pin:function(){this.hasClass("unpinned")&&(this.addClass("pinned"),this.removeClass("unpinned"),this.onPin&&this.onPin.call(this))},freeze:function(){this.frozen=!0,this.addClass("frozen")},unfreeze:function(){this.frozen=!1,this.removeClass("frozen")},top:function(){this.hasClass("top")||(this.addClass("top"),this.removeClass("notTop"),this.onTop&&this.onTop.call(this))},notTop:function(){this.hasClass("notTop")||(this.addClass("notTop"),this.removeClass("top"),this.onNotTop&&this.onNotTop.call(this))},bottom:function(){this.hasClass("bottom")||(this.addClass("bottom"),this.removeClass("notBottom"),this.onBottom&&this.onBottom.call(this))},notBottom:function(){this.hasClass("notBottom")||(this.addClass("notBottom"),this.removeClass("bottom"),this.onNotBottom&&this.onNotBottom.call(this))},shouldUnpin:function(t){return"down"===t.direction&&!t.top&&t.toleranceExceeded},shouldPin:function(t){return"up"===t.direction&&t.toleranceExceeded||t.top},addClass:function(t){this.elem.classList.add.apply(this.elem.classList,this.classes[t].split(" "))},removeClass:function(t){this.elem.classList.remove.apply(this.elem.classList,this.classes[t].split(" "))},hasClass:function(t){return this.classes[t].split(" ").every(function(t){return this.classList.contains(t)},this.elem)},update:function(t){t.isOutOfBounds||!0!==this.frozen&&(t.top?this.top():this.notTop(),t.bottom?this.bottom():this.notBottom(),this.shouldUnpin(t)?this.unpin():this.shouldPin(t)&&this.pin())}},o.options={tolerance:{up:0,down:0},offset:0,scroller:t()?window:null,classes:{frozen:"headroom--frozen",pinned:"headroom--pinned",unpinned:"headroom--unpinned",top:"headroom--top",notTop:"headroom--not-top",bottom:"headroom--bottom",notBottom:"headroom--not-bottom",initial:"headroom"}},o.cutsTheMustard=!!(t()&&function(){}.bind&&"classList"in document.documentElement&&Object.assign&&Object.keys&&requestAnimationFrame),o}); \ No newline at end of file diff --git a/deps/headroom-0.11.0/jQuery.headroom.min.js b/deps/headroom-0.11.0/jQuery.headroom.min.js new file mode 100644 index 0000000..17f70c9 --- /dev/null +++ b/deps/headroom-0.11.0/jQuery.headroom.min.js @@ -0,0 +1,7 @@ +/*! + * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it + * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js + * License: MIT + */ + +!function(a){a&&(a.fn.headroom=function(b){return this.each(function(){var c=a(this),d=c.data("headroom"),e="object"==typeof b&&b;e=a.extend(!0,{},Headroom.options,e),d||(d=new Headroom(this,e),d.init(),c.data("headroom",d)),"string"==typeof b&&(d[b](),"destroy"===b&&c.removeData("headroom"))})},a("[data-headroom]").each(function(){var b=a(this);b.headroom(b.data())}))}(window.Zepto||window.jQuery); \ No newline at end of file diff --git a/deps/jquery-3.6.0/jquery-3.6.0.js b/deps/jquery-3.6.0/jquery-3.6.0.js new file mode 100644 index 0000000..fc6c299 --- /dev/null +++ b/deps/jquery-3.6.0/jquery-3.6.0.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + Skip to contents + + +
    +
    +
    + +

    SeuratIntegrate streamlines single-cell transcriptomics (scRNA-seq) data integration and batch effect correction. This R package effortlessly extends the Seurat workflow with 8 popular integration methods across R and Python, complemented by 11 robust scoring metrics to estimate their performance.

    +
    +
    +

    Integrations

    +
      +
    1. ComBat
      +
    2. +
    3. Harmony
    4. +
    5. MNN
    6. +
    7. BBKNN
    8. +
    9. scVI
    10. +
    11. scANVI
    12. +
    13. Scanorama
    14. +
    15. trVAE
    16. +
    +
    +
    +

    Scoring metrics

    +
      +
    1. ARI
      +
    2. +
    3. ASW
    4. +
    5. Batch ASW
    6. +
    7. Cell cycle conservation
    8. +
    9. Graph connectivity
    10. +
    11. PCA-density
    12. +
    13. PCA-regression
    14. +
    15. kBET
    16. +
    17. cell-type (c)LISI
    18. +
    19. batch (i)LISI
    20. +
    21. NMI
    22. +
    +
    +
    +
    +

    Installation +

    +

    Install SeuratIntegrate from github:

    +
    +install.packages(c("remotes", "BiocManager")) # if not installed
    +
    +remotes::install_github("cbib/Seurat-Integrate", repos = BiocManager::repositories()) 
    +

    To benefit from SeuratIntegrate’s full capabilities, we recommend installing the following packages:

    +
    +# fast distance computation
    +install.packages('distances')
    +
    +# required to test for k-nearest neighbour batch effects
    +remotes::install_github('theislab/kBET')
    +
    +# faster Local Inverse Simpson’s Index computation
    +remotes::install_github('immunogenomics/lisi')
    +
    +
    +

    Conda environments for Python methods +

    +

    To simplify the creation and management of conda environments, we suggest using UpdateEnvCache():

    +
    +# create environments:
    +UpdateEnvCache("bbknn")
    +UpdateEnvCache("scvi")
    +UpdateEnvCache("scanorama")
    +UpdateEnvCache("trvae")
    +

    Those environments will be saved and automatically used by the Python integration methods provided by SeuratIntegrate.

    +

    Alternatively, the cache can be updated with a pre-existing environment. This can be useful if you have to set up a conda environment yourself because a command above failed or a conda environment turned out to be non-functional.

    +
    +# save "my_bbknn_env" (for bbknn) to cache
    +UpdateEnvCache("bbknn", conda.env = "my_bbknn_env")
    +

    The cache remains persistent across sessions and its state can be displayed with:

    + +
    +A fully set CondaEnvManager
    A fully set CondaEnvManager +
    +
    +

    Further details are provided in the vignette("setup_and_tips").

    +
    +
    +

    Data integration +

    +

    To run integration algorithms, we have developed a function called DoIntegrate() that enables:

    +
      +
    • performing multiple integration methods in a single call
    • +
    • control over the data (raw, normalised or scaled) and the features to use as input
    • +
    • flexible customisation of parameters for each integration method
    • +
    +
    +seu <- DoIntegrate(seu,
    +       # ... integrations
    +         CombatIntegration(layers = "data"),
    +         HarmonyIntegration(orig = "pca", dims = 1:30),
    +         ScanoramaIntegration(ncores = 4L, layers = "data"),
    +         scVIIntegration(layers = "counts", features = Features(seu)),
    +       # ...
    +       use.hvg = TRUE,    # `VariableFeatures()`
    +       use.future = c(FALSE, FALSE, TRUE, TRUE)
    +)
    +

    Here, all integration methods will use the variable features as input, with the exception of scVIIntegration() which is set to use all features. CombatIntegration() will correct the normalised counts, while scVIIntegration() will train on raw counts.

    +

    use.future must be TRUE for Python methods, and FALSE for R methods.

    +

    Integration methods produce one or several outputs. Those can be of multiple types - either a new assay with corrected counts, a new dimension reduction with corrected cell embeddings, or a new graph with corrected edges. The type of output is important to consider, because it will require different post-processing steps until the result of the integration can be visualised on a UMAP:

    +
      +
    • Corrected counts: ScaleData() -> RunPCA() -> RunUMAP() +
    • +
    • Dimension reduction: RunUMAP() +
    • +
    • KNN graph: RunUMAP(umap.method = "umap-learn") +
    • +
    +
    +
    +

    Scoring +

    +

    SeuratIntegrate incorporates 11 scoring metrics: 6 quantify the degree of batch mixing (batch correction), while 5 assess the preservation of biological differences (bio-conservation) based on ground truth cell type labels.

    +

    Each score can be obtained using a function of the form Score[score_name](), or directly saved in the Seurat object using the AddScore[score_name]() counterpart:

    +
    +# save the score in a variable
    +rpca_score <- ScoreRegressPC(seu, reduction = "pca")
    +
    +# or save the score in the Seurat object
    +seu <- AddScoreRegressPC(seu, integration = "unintegrated", reduction = "pca")
    +

    The AddScore functions have an advantage over the Score functions. They allow to then scale the scores between zero and one and to standardize their direction (the closer to one, always the better), improving interpretability. Then, scores can be plotted to readily compare the different integrations:

    +
    +# scale
    +seu <- ScaleScores(seu)
    +
    +# plot
    +PlotScores(seu)
    +
    +
    +
    +
    + + +
    + + + +
    +
    + + + + + + + diff --git a/katex-auto.js b/katex-auto.js new file mode 100644 index 0000000..20651d9 --- /dev/null +++ b/katex-auto.js @@ -0,0 +1,14 @@ +// https://github.com/jgm/pandoc/blob/29fa97ab96b8e2d62d48326e1b949a71dc41f47a/src/Text/Pandoc/Writers/HTML.hs#L332-L345 +document.addEventListener("DOMContentLoaded", function () { + var mathElements = document.getElementsByClassName("math"); + var macros = []; + for (var i = 0; i < mathElements.length; i++) { + var texText = mathElements[i].firstChild; + if (mathElements[i].tagName == "SPAN") { + katex.render(texText.data, mathElements[i], { + displayMode: mathElements[i].classList.contains("display"), + throwOnError: false, + macros: macros, + fleqn: false + }); + }}}); diff --git a/lightswitch.js b/lightswitch.js new file mode 100644 index 0000000..9467125 --- /dev/null +++ b/lightswitch.js @@ -0,0 +1,85 @@ + +/*! + * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * Updates for {pkgdown} by the {bslib} authors, also licensed under CC-BY-3.0. + */ + +const getStoredTheme = () => localStorage.getItem('theme') +const setStoredTheme = theme => localStorage.setItem('theme', theme) + +const getPreferredTheme = () => { + const storedTheme = getStoredTheme() + if (storedTheme) { + return storedTheme + } + + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' +} + +const setTheme = theme => { + if (theme === 'auto') { + document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) + } else { + document.documentElement.setAttribute('data-bs-theme', theme) + } +} + +function bsSetupThemeToggle () { + 'use strict' + + const showActiveTheme = (theme, focus = false) => { + var activeLabel, activeIcon; + + document.querySelectorAll('[data-bs-theme-value]').forEach(element => { + const buttonTheme = element.getAttribute('data-bs-theme-value') + const isActive = buttonTheme == theme + + element.classList.toggle('active', isActive) + element.setAttribute('aria-pressed', isActive) + + if (isActive) { + activeLabel = element.textContent; + activeIcon = element.querySelector('span').classList.value; + } + }) + + const themeSwitcher = document.querySelector('#dropdown-lightswitch') + if (!themeSwitcher) { + return + } + + themeSwitcher.setAttribute('aria-label', activeLabel) + themeSwitcher.querySelector('span').classList.value = activeIcon; + + if (focus) { + themeSwitcher.focus() + } + } + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + const storedTheme = getStoredTheme() + if (storedTheme !== 'light' && storedTheme !== 'dark') { + setTheme(getPreferredTheme()) + } + }) + + window.addEventListener('DOMContentLoaded', () => { + showActiveTheme(getPreferredTheme()) + + document + .querySelectorAll('[data-bs-theme-value]') + .forEach(toggle => { + toggle.addEventListener('click', () => { + const theme = toggle.getAttribute('data-bs-theme-value') + setTheme(theme) + setStoredTheme(theme) + showActiveTheme(theme, true) + }) + }) + }) +} + +setTheme(getPreferredTheme()); +bsSetupThemeToggle(); diff --git a/link.svg b/link.svg new file mode 100644 index 0000000..88ad827 --- /dev/null +++ b/link.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..ed84ab2 Binary files /dev/null and b/logo.png differ diff --git a/pkgdown.js b/pkgdown.js new file mode 100644 index 0000000..1a99c65 --- /dev/null +++ b/pkgdown.js @@ -0,0 +1,162 @@ +/* http://gregfranko.com/blog/jquery-best-practices/ */ +(function($) { + $(function() { + + $('nav.navbar').headroom(); + + Toc.init({ + $nav: $("#toc"), + $scope: $("main h2, main h3, main h4, main h5, main h6") + }); + + if ($('#toc').length) { + $('body').scrollspy({ + target: '#toc', + offset: $("nav.navbar").outerHeight() + 1 + }); + } + + // Activate popovers + $('[data-bs-toggle="popover"]').popover({ + container: 'body', + html: true, + trigger: 'focus', + placement: "top", + sanitize: false, + }); + + $('[data-bs-toggle="tooltip"]').tooltip(); + + /* Clipboard --------------------------*/ + + function changeTooltipMessage(element, msg) { + var tooltipOriginalTitle=element.getAttribute('data-bs-original-title'); + element.setAttribute('data-bs-original-title', msg); + $(element).tooltip('show'); + element.setAttribute('data-bs-original-title', tooltipOriginalTitle); + } + + if(ClipboardJS.isSupported()) { + $(document).ready(function() { + var copyButton = ""; + + $("div.sourceCode").addClass("hasCopyButton"); + + // Insert copy buttons: + $(copyButton).prependTo(".hasCopyButton"); + + // Initialize tooltips: + $('.btn-copy-ex').tooltip({container: 'body'}); + + // Initialize clipboard: + var clipboard = new ClipboardJS('[data-clipboard-copy]', { + text: function(trigger) { + return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); + } + }); + + clipboard.on('success', function(e) { + changeTooltipMessage(e.trigger, 'Copied!'); + e.clearSelection(); + }); + + clipboard.on('error', function(e) { + changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); + }); + + }); + } + + /* Search marking --------------------------*/ + var url = new URL(window.location.href); + var toMark = url.searchParams.get("q"); + var mark = new Mark("main#main"); + if (toMark) { + mark.mark(toMark, { + accuracy: { + value: "complementary", + limiters: [",", ".", ":", "/"], + } + }); + } + + /* Search --------------------------*/ + /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ + // Initialise search index on focus + var fuse; + $("#search-input").focus(async function(e) { + if (fuse) { + return; + } + + $(e.target).addClass("loading"); + var response = await fetch($("#search-input").data("search-index")); + var data = await response.json(); + + var options = { + keys: ["what", "text", "code"], + ignoreLocation: true, + threshold: 0.1, + includeMatches: true, + includeScore: true, + }; + fuse = new Fuse(data, options); + + $(e.target).removeClass("loading"); + }); + + // Use algolia autocomplete + var options = { + autoselect: true, + debug: true, + hint: false, + minLength: 2, + }; + var q; +async function searchFuse(query, callback) { + await fuse; + + var items; + if (!fuse) { + items = []; + } else { + q = query; + var results = fuse.search(query, { limit: 20 }); + items = results + .filter((x) => x.score <= 0.75) + .map((x) => x.item); + if (items.length === 0) { + items = [{dir:"Sorry 😿",previous_headings:"",title:"No results found.",what:"No results found.",path:window.location.href}]; + } + } + callback(items); +} + $("#search-input").autocomplete(options, [ + { + name: "content", + source: searchFuse, + templates: { + suggestion: (s) => { + if (s.title == s.what) { + return `${s.dir} >
    ${s.title}
    `; + } else if (s.previous_headings == "") { + return `${s.dir} >
    ${s.title}
    > ${s.what}`; + } else { + return `${s.dir} >
    ${s.title}
    > ${s.previous_headings} > ${s.what}`; + } + }, + }, + }, + ]).on('autocomplete:selected', function(event, s) { + window.location.href = s.path + "?q=" + q + "#" + s.id; + }); + }); +})(window.jQuery || window.$) + +document.addEventListener('keydown', function(event) { + // Check if the pressed key is '/' + if (event.key === '/') { + event.preventDefault(); // Prevent any default action associated with the '/' key + document.getElementById('search-input').focus(); // Set focus to the search input + } +}); diff --git a/pkgdown.yml b/pkgdown.yml new file mode 100644 index 0000000..95157bc --- /dev/null +++ b/pkgdown.yml @@ -0,0 +1,13 @@ +pandoc: '3.2' +pkgdown: 2.1.1 +pkgdown_sha: ~ +articles: + introduction: introduction.html + memo_integration: memo_integration.html + memo_score: memo_score.html + setup_and_tips: setup_and_tips.html + SeuratIntegrate: SeuratIntegrate.html +last_built: 2025-01-14T23:01Z +urls: + reference: https://cbib.github.io/Seurat-Integrate/reference + article: https://cbib.github.io/Seurat-Integrate/articles diff --git a/reference/AddMiscIntegrations.html b/reference/AddMiscIntegrations.html new file mode 100644 index 0000000..e7f7191 --- /dev/null +++ b/reference/AddMiscIntegrations.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddMiscScores.html b/reference/AddMiscScores.html new file mode 100644 index 0000000..e7f7191 --- /dev/null +++ b/reference/AddMiscScores.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreARI.html b/reference/AddScoreARI.html new file mode 100644 index 0000000..a4b2425 --- /dev/null +++ b/reference/AddScoreARI.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreASW.html b/reference/AddScoreASW.html new file mode 100644 index 0000000..18e38da --- /dev/null +++ b/reference/AddScoreASW.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreASWBatch.html b/reference/AddScoreASWBatch.html new file mode 100644 index 0000000..18e38da --- /dev/null +++ b/reference/AddScoreASWBatch.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreConnectivity.html b/reference/AddScoreConnectivity.html new file mode 100644 index 0000000..ebb214b --- /dev/null +++ b/reference/AddScoreConnectivity.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreDensityPC.html b/reference/AddScoreDensityPC.html new file mode 100644 index 0000000..80097a7 --- /dev/null +++ b/reference/AddScoreDensityPC.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreKBET.html b/reference/AddScoreKBET.html new file mode 100644 index 0000000..ed8ea95 --- /dev/null +++ b/reference/AddScoreKBET.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreNMI.html b/reference/AddScoreNMI.html new file mode 100644 index 0000000..bac55dc --- /dev/null +++ b/reference/AddScoreNMI.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreRegressPC.CellCycle.html b/reference/AddScoreRegressPC.CellCycle.html new file mode 100644 index 0000000..dfba014 --- /dev/null +++ b/reference/AddScoreRegressPC.CellCycle.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/AddScoreRegressPC.html b/reference/AddScoreRegressPC.html new file mode 100644 index 0000000..7689440 --- /dev/null +++ b/reference/AddScoreRegressPC.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/CellCycleScoringPerBatch.html b/reference/CellCycleScoringPerBatch.html new file mode 100644 index 0000000..d885256 --- /dev/null +++ b/reference/CellCycleScoringPerBatch.html @@ -0,0 +1,154 @@ + +Score cell cycle phases per batch — CellCycleScoringPerBatch • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Assign cell cycle scores to cells. Scores are computed for each batch +independantly.

    +
    + +
    +

    Usage

    +
    CellCycleScoringPerBatch(
    +  object,
    +  batch.var = NULL,
    +  s.features,
    +  g2m.features,
    +  ctrl = NULL,
    +  assay = NULL,
    +  layer = NULL,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    batch.var
    +

    The name of the batch variable (must be in the object metadata)

    + + +
    s.features
    +

    A vector of features associated with S phase

    + + +
    g2m.features
    +

    A vector of features associated with G2M phase

    + + +
    ctrl
    +

    Number of control features selected from the same bin per +analyzed feature supplied to AddModuleScore. +Defaults to value equivalent to minimum number of features +present in 's.features' and 'g2m.features'.

    + + +
    assay
    +

    assay to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    layer
    +

    layer to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    ...
    +

    Arguments to be passed to CellCycleScoring, +then AddModuleScore (with the exception of +set.ident which is always FALSE)

    + +
    +
    +

    Value

    +

    A Seurat object with the following columns added to object meta data: S.Score, G2M.Score, and Phase

    +
    +
    +

    See also

    +

    CellCycleScoring to compute cc scores on the whole +dataset.

    +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- CellCycleScoringPerBatch(obj, batch.var = 'Method',
    +                                s.features = cc.genes.updated.2019$s.genes,
    +                                g2m.features = cc.genes.updated.2019$g2m.genes)
    +
    +head(obj[[]])
    +} # }
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/CombatIntegration.html b/reference/CombatIntegration.html new file mode 100644 index 0000000..272644a --- /dev/null +++ b/reference/CombatIntegration.html @@ -0,0 +1,214 @@ + +Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run ComBat or +ComBat_seq on multi-layered Seurat V5 object

    +
    + +
    +

    Usage

    +
    CombatIntegration(
    +  object,
    +  orig = NULL,
    +  groups = NULL,
    +  groups.name = NULL,
    +  layers = "data",
    +  scale.layer = "scale.data",
    +  features = NULL,
    +  reconstructed.assay = "combat.reconstructed",
    +  key.assay = "combat_",
    +  combat.function = c("combat", "combat_seq"),
    +  use.scaled = FALSE,
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    orig
    +

    DimReduc object. Not to be set +directly when called with IntegrateLayers, use +orig.reduction argument instead

    + + +
    groups
    +

    A named data frame with grouping information. Preferably +one-column when groups.name = NULL

    + + +
    groups.name
    +

    Column name from groups data frame that stores +grouping information. If groups.name = NULL, the first column is used

    + + +
    layers
    +

    Name of the layers to use in the integration

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    features
    +

    Vector of feature names to input to the integration method. +When features = NULL (default), the +VariableFeatures are used. To pass all features, +use the output of Features()

    + + +
    reconstructed.assay
    +

    Name for the assay containing the corrected +expression matrix

    + + +
    key.assay
    +

    Optional key for the new combat assay. Format: "[:alnum:]*_"

    + + +
    combat.function
    +

    ComBat implementation to use. One of +combat, combat_seq. Note that +ComBat_seq is an improved model from ComBat but requires a dense matrix. +Sparse to dense matrix conversion can be memory-intensive.

    + + +
    use.scaled
    +

    By default the layer passed to the layer argument is +used. When use.scaled = TRUE, the scale.layer is input to ComBat.

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    ...
    +

    Additional arguments passed on to ComBat or +ComBat_seq.

    + +
    +
    +

    Value

    +

    The function itself returns a list containing:

    • a new Assay of name reconstructed.assay (key set to + assay.key) with corrected cell counts.

    • +

    When called via IntegrateLayers, a Seurat object with +the new assay is returned

    +
    +
    +

    Note

    +

    This function requires the +sva +(Surrogate Variable Analysis) package to be installed

    +
    +
    +

    References

    +

    Johnson, W. E., Li, C. & Rabinovic, A. Adjusting batch effects in +microarray expression data using empirical Bayes methods. Biostatistics 8, +118–127 (2006). DOI

    +

    Zhang, Y., Parmigiani, G. & Johnson, W. E. ComBat-seq: batch effect +adjustment for RNA-seq count data. NAR Genomics and Bioinformatics 2 (2020). +DOI

    +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- UpdateSeuratObject(SeuratData::LoadData("pbmcsca"))
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers based on the "Method" variable:
    +obj <- IntegrateLayers(object = obj, method = CombatIntegration,
    +                       verbose = TRUE, layers = "data", scale.layer = NULL,
    +                       features = VariableFeatures(
    +                         FindVariableFeatures(obj, nfeatures = 5e3)
    +                       ))
    +
    +# We can also change parameters such as the input data.
    +# Here we use the scale data, the ComBat implementation and we use the cell
    +# labels as a "biological condition of interest" (/!\ long):
    +
    +obj <- IntegrateLayers(object = obj,  method = CombatIntegration,
    +                       verbose = TRUE, features = VariableFeatures(obj),
    +                       use.scaled = FALSE, combat.function = 'combat_seq',
    +                       group = obj[[]]$CellType, groups = obj[[]],
    +                       groups.name = "Method", layers = "counts")
    +} # }
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/CondaEnv-class.html b/reference/CondaEnv-class.html new file mode 100644 index 0000000..33aa544 --- /dev/null +++ b/reference/CondaEnv-class.html @@ -0,0 +1,115 @@ + +Encapsulates information about a conda environment — CondaEnv-class • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    The CondaEnv class provides a basic structure to store information +about a conda environment for a given method. It is designed to be used by +the CondaEnvManager class.

    +
    + + +
    +

    Slots

    + + +
    method
    +

    1-length character. Indicating the method this CondaEnv +refers to

    + + +
    needs.conda
    +

    logical. Whether the method needs conda (yes if +python-based, no if R-based)

    + + +
    conda.bin
    +

    single string. path to conda binary. If empty (""), +NULL or "conda", "auto" is passed to +conda_binary to find path to conda binary in PATH

    + + +
    conda.env.name
    +

    1-length character. Name of the conda environment

    + + +
    conda.env.path
    +

    1-length character. Path to the conda environment

    + + +
    is.valid
    +

    logical. Whether the environment is valid. Should not be set +by the user. Set by checkCondaEnv.

    + + +
    + + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/CondaEnv.html b/reference/CondaEnv.html new file mode 100644 index 0000000..2dd3215 --- /dev/null +++ b/reference/CondaEnv.html @@ -0,0 +1,120 @@ + +Handy CondaEnv instance constructor — CondaEnv • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Wrapper to create a CondaEnv object meant to store +information about a single conda environment for a specific method. In most +cases, it is best that the user favors CondaEnvManager-related +functions.

    +
    + +
    +

    Usage

    +
    CondaEnv(
    +  method = known.methods,
    +  conda.bin = NULL,
    +  conda.env.name = NULL,
    +  conda.env.path = NULL
    +)
    +
    + +
    +

    Arguments

    + + +
    method
    +

    the method name. One of "combat", "harmony", "mnn", "bbknn", +"scvi", "scanvi", "scanorama"

    + + +
    conda.bin
    +

    the path to the conda binary. If empty (""), +NULL or "conda", "auto" is passed to +conda_binary() to find the path to the conda binary in +PATH

    + + +
    conda.env.name
    +

    name of the conda environment

    + + +
    conda.env.path
    +

    path to the conda environment

    + +
    +
    +

    Value

    +

    a CondaEnv object

    +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/CondaEnvManager-class.html b/reference/CondaEnvManager-class.html new file mode 100644 index 0000000..0254752 --- /dev/null +++ b/reference/CondaEnvManager-class.html @@ -0,0 +1,117 @@ + +Manager of conda environments for python-based integration methods — CondaEnvManager-class • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    The CondaEnvManager class provides a handy way to set up, store and use +conda environments for python-based integration methods. It is designed to be +set up and modified via helper functions, not directly by the user.

    +
    + + +
    +

    Slots

    + + +
    combat
    +

    CondaEnv. For R-based combat method, nothing to set up.

    + + +
    harmony
    +

    CondaEnv. For R-based harmony method, nothing to set up.

    + + +
    mnn
    +

    CondaEnv. For R-based MNN method, nothing to set up.

    + + +
    bbknn
    +

    CondaEnv. For python-based bbknn method.

    + + +
    scvi
    +

    CondaEnv. For python-based SCVI method. Can be shared with SCANVI.

    + + +
    scanvi
    +

    CondaEnv. For python-based SCANVI method. Can be shared with SCVI.

    + + +
    scanorama
    +

    CondaEnv. For python-based Scanorama method

    + + +
    trvae
    +

    CondaEnv. For python-based trVAE method

    + + +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/CondaManager.html b/reference/CondaManager.html new file mode 100644 index 0000000..2df05b7 --- /dev/null +++ b/reference/CondaManager.html @@ -0,0 +1,119 @@ + +Handy CondaEnvManger instance constructor — CondaManager • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Wrapper to create a CondaEnvManager object meant to store +information about conda environments for all known methods out of a data.frame +object (typically stored in the package's cache). In most cases, it is best +that the user favors the UpdateEnvCache() function +which enables to create/overwrite conda environments and to update the +package's internal cache.

    +
    + +
    +

    Usage

    +
    CondaManager(cache)
    +
    + +
    +

    Arguments

    + + +
    cache
    +

    a correctly formatted (see below) data.frame or a path to such a +data.frame stored inside a RDS file. If cache is missing, return an blank +object (i.e. in an uninitialized state).

    + +
    +
    +

    Value

    +

    a CondaEnvManager object

    +
    +
    +

    Details

    +

    The cache data.frame's expected column names are:

    • method

    • +
    • needs.conda

    • +
    • conda.bin.value

    • +
    • conda.bin.valid

    • +
    • conda.env.name.value

    • +
    • conda.env.name.valid

    • +
    • conda.env.path.value

    • +
    • conda.env.path.valid

    • +
    • is.valid

    • +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/CutKnn.html b/reference/CutKnn.html new file mode 100644 index 0000000..cef89c9 --- /dev/null +++ b/reference/CutKnn.html @@ -0,0 +1,115 @@ + +Remove excessive number of neighbours in a knn graph — CutKnn • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Ensure that each cell's number of neighbours does not exceed a cutoff

    +
    + +
    +

    Usage

    +
    CutKnn(
    +  object,
    +  graph.name,
    +  new.graph = NULL,
    +  k.max,
    +  assay = NULL,
    +  verbose = TRUE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    graph.name
    +

    name of a Graph or Neighbor instance stored in +the Seurat object.

    + + +
    new.graph
    +

    name of the trimmed graph to save in the Seurat object

    + + +
    k.max
    +

    maximum number of neigbours allowed per cell

    + + +
    assay
    +

    name of the assay to use. Ignored when graph object is a +Neighbor object. If not specified (default), the default assay is used

    + + +
    verbose
    +

    whether to print messages. Set to FALSE to disable

    + +
    +
    +

    Value

    +

    the Seurat object with a new Graph or Neighbor instance

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/DoIntegrate.html b/reference/DoIntegrate.html new file mode 100644 index 0000000..0684849 --- /dev/null +++ b/reference/DoIntegrate.html @@ -0,0 +1,171 @@ + +Integrate layers using one or multiple integration method(s) — DoIntegrate • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Integrate layers of a Seurat object using one or more integration methods.

    +

    Available integration methods are listed at the bottom of this page. +DoIntegrate() works best with SeuratIntegrate's methods.

    +
    + +
    +

    Usage

    +
    DoIntegrate(
    +  object,
    +  ...,
    +  use.hvg = TRUE,
    +  use.future = TRUE,
    +  future.globals.size = getOption("future.globals.maxSize")
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    ...
    +

    one or more integration method call(s) to correct batch +effects with. Must be of the form package::MethodIntegration(). It is +recommended to use :: because it is safer in case of namespace +collision or if the package is not attached nor loaded. Don't forget +the parentheses.

    + + +
    use.hvg
    +

    whether to use highly variable genes. FALSE causes all +the features present in the assay to be used.

    + + +
    use.future
    +

    whether to use future to run integrations in +a background session. Useful when python-based algorithms are invoked.

    + + +
    future.globals.size
    +

    maximum allowed size (in bytes) of global +variables to export. By default, uses the value of the option +"future.globals.maxSize". If it is NULL, thrice the size of the Seurat +object is used. Inoperative when use.future = FALSE

    + +
    +
    +

    Value

    +

    the updated Seurat object enriched with the integration methods' +outputs.

    +
    +
    +

    Details

    +

    Each call to an integration method require parentheses. Parameter +values specific to each method can be enclosed between these brackets, +although the defaults arguments should be good enough for most cases. Note +that for each integration method, the argument values specified in +its call supersede DoIntegrate's internal computations. For instance,

    +
    
    +DoIntegrate(seu,
    +            SeuratIntegrate::CombatIntegration(features = Features(seu)),
    +            Seurat::CCAIntegration(),
    +            use.hvg = TRUE)
    + +

    forces ComBat but not CCA to use all features instead of the variable ones.

    +
    +
    +

    Note

    +

    The desired value of parameters use.hvg, use.future and +future.globals.size can be different for each method called. Hence, +they accept vectors with more than one element. They must be in the same +order as the integration method calls.

    +

    This unconventional way of calling methods presents a few advantages: +With a single call to DoIntegrate, you can perform multiple +integrations at once, while preserving the flexibility of an individual +method call by fine-tuning integration-specific parameters.

    +
    + + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/ExpandNeighbours,Seurat-method.html b/reference/ExpandNeighbours,Seurat-method.html new file mode 100644 index 0000000..c4098c3 --- /dev/null +++ b/reference/ExpandNeighbours,Seurat-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/ExpandNeighbours.html b/reference/ExpandNeighbours.html new file mode 100644 index 0000000..b5f6922 --- /dev/null +++ b/reference/ExpandNeighbours.html @@ -0,0 +1,201 @@ + +Expand knn graph to increase the number of neighbours — ExpandNeighbours • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Expand a knn graph to increase the number of nearest neighbours using +Dijkstra's algorithm, or a diffusion algorithm. Dijkstra's algorithm is used +to prepare for LISI score, while diffusion is suited for preparing to compute +the kBET score. Beware that diffusion is designed to work on connectivity +matrices and is not adequate for distance-based networks.

    +
    + +
    +

    Usage

    +
    ExpandNeighbours(
    +  object,
    +  graph.name = "RNA_nn",
    +  new.graph.name = NULL,
    +  graph.type = c("distances", "connectivities"),
    +  k.target = 90L,
    +  do.symmetrize = FALSE,
    +  algo = c("dijkstra", "diffusion"),
    +  which.dijkstra = c("auto", "igraph", "fast", "slow"),
    +  dijkstra.ncores = 1L,
    +  dijkstra.tol = 1L,
    +  diffusion.iter = 26L,
    +  assay = NULL,
    +  verbose = TRUE
    +)
    +
    +# S4 method for class 'Seurat'
    +ExpandNeighbours(
    +  object,
    +  graph.name = "RNA_nn",
    +  new.graph.name = NULL,
    +  graph.type = c("distances", "connectivities"),
    +  k.target = 90L,
    +  do.symmetrize = FALSE,
    +  algo = c("dijkstra", "diffusion"),
    +  which.dijkstra = c("auto", "igraph", "fast", "slow"),
    +  dijkstra.ncores = 1L,
    +  dijkstra.tol = 1L,
    +  diffusion.iter = 26L,
    +  assay = NULL,
    +  verbose = TRUE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat, Graph or Neighbor object

    + + +
    graph.name
    +

    name of a Graph or Neighbor instance stored in +the Seurat object.

    + + +
    new.graph.name
    +

    name of the return Graph to store in the +Seurat object.

    + + +
    graph.type
    +

    One of "distances" or "connectivities", indicating the type +of metric stored in the graph object.

    + + +
    k.target
    +

    number of nearest neighbours to reach

    + + +
    do.symmetrize
    +

    whether to make the input graph symmetric if necessary. +See Details section for further explanations

    + + +
    algo
    +

    One of "dijkstra" or "diffusion". "diffusion" is suited for +connectivity matrices only

    + + +
    which.dijkstra
    +

    one of "igraph", "fast" or "slow". "auto" (default) +chooses for you. See Details section

    + + +
    dijkstra.ncores
    +

    number of cores to use for Dijkstra's algorithm. +Ignored when which.dijkstra = "igraph"

    + + +
    dijkstra.tol
    +

    number of sequential iterations with identical best +neighbours found to consider that Dijkstra's algorithm should be stopped. +Ignored when which.dijkstra = "igraph"

    + + +
    diffusion.iter
    +

    maximum number of iterations to reach k.target

    + + +
    assay
    +

    name of the assay to store in the output Graph

    + + +
    verbose
    +

    whether to print progress messages

    + +
    +
    +

    Value

    +

    the Seurat object with a new Graph instance or a +dgCMatrix representing the Graph itself

    +
    +
    +

    Details

    +

    The approximate nature of the nearest neighbour search algorithm used to +compute the knn graph makes the resulting adjacency matrix asymmetric. +It means that \(cell_i\) can be a nearest neighbour of \(cell_j\) while +the reverse is not true even though the distance between \(cell_i\) and +\(cell_j\) is lower than the distance between \(cell_j\) and some of its +nearest neighbours.

    +

    One can choose to keep the graph as it is and consider it as a directed graph +(do.symmetrize = FALSE). +The alternative solution is to use all computed distances to extend the knn +graph by making the matrix symmetric. Note that connectivity graphs are +already symmetric, so the argument value should have no effect on the result.

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/FindOptimalClusters.html b/reference/FindOptimalClusters.html new file mode 100644 index 0000000..8456d9c --- /dev/null +++ b/reference/FindOptimalClusters.html @@ -0,0 +1,214 @@ + +Find a clustering that maximises NMI or ARI — FindOptimalClusters • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute clusters for multiple resolutions and saves in the metadata the +clustering result that reaches the maximum NMI and/or ARI value for a given +cell-type label variable.

    +
    + +
    +

    Usage

    +
    FindOptimalClusters(
    +  object,
    +  graph.name = NULL,
    +  cell.var = NULL,
    +  cluster.name = "{graph.name}_{cell.var}_{metric}",
    +  modularity.fxn = 1,
    +  initial.membership = NULL,
    +  node.sizes = NULL,
    +  resolutions = seq(from = 0.1, to = 2, by = 0.1),
    +  optimisation.metric = c("nmi", "ari"),
    +  method = "matrix",
    +  algorithm = 1,
    +  n.start = 10,
    +  n.iter = 10,
    +  random.seed = 0,
    +  group.singletons = TRUE,
    +  temp.file.location = NULL,
    +  edge.file.name = NULL,
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    graph.name
    +

    the name of the knn graph to score.

    + + +
    cell.var
    +

    The name(s) of the column(s) with cell type label variable +(must be in the object metadata). Multiple column names are accepted

    + + +
    cluster.name
    +

    a (optionally 'glue') string used as the new metadata +column name (see Details section)

    + + +
    modularity.fxn
    +

    Modularity function (1 = standard; 2 = alternative).

    + + +
    initial.membership, node.sizes
    +

    Parameters to pass to the Python leidenalg function.

    + + +
    resolutions
    +

    the resolutions to compute clusters for

    + + +
    optimisation.metric
    +

    one of "nmi" or "ari" or both (default). +The metric(s) to use to check clustering results against the cell.var.

    + + +
    method
    +

    Method for running leiden (defaults to matrix which is fast for small datasets). +Enable method = "igraph" to avoid casting large data to a dense matrix.

    + + +
    algorithm
    +

    Algorithm for modularity optimization (1 = original Louvain +algorithm; 2 = Louvain algorithm with multilevel refinement; 3 = SLM +algorithm; 4 = Leiden algorithm). Leiden requires the leidenalg python.

    + + +
    n.start
    +

    Number of random starts.

    + + +
    n.iter
    +

    Maximal number of iterations per random start.

    + + +
    random.seed
    +

    Seed of the random number generator.

    + + +
    group.singletons
    +

    Group singletons into nearest cluster. If FALSE, assign all singletons to +a "singleton" group

    + + +
    temp.file.location
    +

    Directory where intermediate files will be written. +Specify the ABSOLUTE path.

    + + +
    edge.file.name
    +

    Edge file to use as input for modularity optimizer jar.

    + + +
    verbose
    +

    Print output

    + + +
    ...
    +

    Arguments passed to other methods

    + +
    +
    +

    Value

    +

    the updated seurat object with the new metadata column(s)

    +
    +
    +

    Details

    +

    cluster.name can use the 'glue' syntax to avoid overwriting metadata +columns when multiple metrics and/or cell-type label variables are provided. +But it can be ignored otherwise. Injectable variables are "graph.name", +"cell.var" and "metric" (not "optimisation.metric"). They +must be flanked by single curly brackets ("{" and "}").

    +

    For instance, if you prefer to name the clusters with an integration instead +of the graph.name, don't use the glue syntax for it (e.g. +"combat_{cell.var}_{metric}" would work, but any of +"{combat}_{cell.var}_{metric}" or +"{integration}_{cell.var}_{metric}" would throw an error)

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/GetConnectivities.html b/reference/GetConnectivities.html new file mode 100644 index 0000000..12b321f --- /dev/null +++ b/reference/GetConnectivities.html @@ -0,0 +1,206 @@ + +Derive connectivities from distances — GetConnectivities • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Adapted from scanpy's strategy in sc.pp.neighbors() to compute +connectivities. Two methods are available, using a Gaussian kernel or a fuzzy +union of simplical sets as implemented in umap-learn

    +
    + +
    +

    Usage

    +
    GetConnectivities(
    +  object,
    +  neighbors.use,
    +  method = c("umap", "gauss"),
    +  graph.name = NULL,
    +  assay = NULL,
    +  umap.set.op.mix.ratio = 1,
    +  umap.local.connectivity = 1,
    +  umap.niter.smoothing = 64L,
    +  umap.apply.set.operations = TRUE,
    +  umap.bipartite = FALSE,
    +  gauss.sigmas = NULL,
    +  gauss.median.sigma = FALSE,
    +  verbose = TRUE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    neighbors.use
    +

    name of a Neighbor instance stored in the +Seurat object to derive connectivities from.

    + + +
    method
    +

    one of "umap" or "gauss". Decides whether connectivities are +computed using a fuzzy union of simplical sets ("umap") or a Gaussian kernel +("gauss")

    + + +
    graph.name
    +

    name of the return Graph of connectivities to store +in the Seurat object.

    + + +
    assay
    +

    name of the assay to reference in the output Graph object. +Use the default assay of object if not provided.

    + + +
    umap.set.op.mix.ratio
    +

    float between 0 and 1. Controls how the fuzzy +sets are mixed to obtain a global fuzzy simplicial set. 0 and 1 correspond to +a pure fuzzy intersection and union, respectively. Both fuzzy set operations +use the product t-norm. Only applies to the umap method.

    + + +
    umap.local.connectivity
    +

    The local connectivity required, i.e. the +expected number of nearest neighbours locally connected. The higher, the more +local connections are output. In practice, this should be not more than the +local intrinsic dimension of the manifold. Only applies to the umap +method when umap.apply.set.operations = TRUE.

    + + +
    umap.niter.smoothing
    +

    maximum number of iterations during the smoothing +process of distances. Only applies to the umap method.

    + + +
    umap.apply.set.operations
    +

    set to FALSE to disable the fuzzy +union or intersection of the local fuzzy simplicial sets into a global fuzzy +simplicial set. Only applies to the umap +method.

    + + +
    umap.bipartite
    +

    whether the knn network is bipartite (FALSE by +default). Only applies to the umap method.

    + + +
    gauss.sigmas
    +

    by default, a sigma value (i.e. width of the kernel) per +cell is computed internally. Those sigmas are controlling for each cell's +connectivities range and magnitude. Alternatively, you can provide your own +width(s). If the length of sigmas is shorter than the number of cells, +it will be recycled. Only applies to the Gaussian method.

    + + +
    gauss.median.sigma
    +

    which estimation method to use when +sigmas = NULL. By default, use the cell’s distance to its kth nearest +neighbour. When median.sigma = TRUE, use the median of distances to +the nearest neighbours (excluding self). Only applies to the +Gaussian method.

    + + +
    verbose
    +

    whether to print progress messages

    + +
    +
    +

    Value

    +

    the Seurat object with a new Graph instance of name +graph.name

    +
    +
    +

    Note

    +

    The UMAP method is a re-implementation of the function +fuzzy_simplicial_set() from umap-learn and should estimate +identical connectivities. You can check the +original documentation.

    +The Gaussian kernel method is a re-implementation of the analogous function +from scanpy called by sc.pp.neighbors(). You can have a look at +the +original function
    median.sigmas = FALSE is the method used in Haghverdi L. et al.,2016.

    +
    +
    +

    References

    +

    McInnes, L., Healy, J. & Melville, J. UMAP: Uniform Manifold +Approximation and Projection for Dimension Reduction. arXiv preprint (2018). +DOI

    +

    Wolf, F. A., Angerer, P. & Theis, F. J. SCANPY: large-scale +single-cell gene expression data analysis. Genome Biology 19, (2018).

    +

    Coifman, R. R., Lafon, S., Lee, A. B., Maggioni, M., Nadler, B., +Warner, F. & Zucker, S. W. Geometric diffusions as a tool for harmonic +analysis and structure definition of data: Diffusion maps. PNAS 102, 7426–7431 +(2005). DOI

    +

    Haghverdi, L., Büttner, M., Wolf, F. A., Buettner, F. & Theis, F. +J. Diffusion pseudotime robustly reconstructs lineage branching. Nature +Methods 13, 845–848 (2016). DOI

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/GetMiscScores.html b/reference/GetMiscScores.html new file mode 100644 index 0000000..9890520 --- /dev/null +++ b/reference/GetMiscScores.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch,Graph,ANY-method.html b/reference/GetNeighborsPerBatch,Graph,ANY-method.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighborsPerBatch,Graph,ANY-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch,Matrix,ANY-method.html b/reference/GetNeighborsPerBatch,Matrix,ANY-method.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighborsPerBatch,Matrix,ANY-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch,Neighbor,ANY-method.html b/reference/GetNeighborsPerBatch,Neighbor,ANY-method.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighborsPerBatch,Neighbor,ANY-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch,Seurat,character-method.html b/reference/GetNeighborsPerBatch,Seurat,character-method.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighborsPerBatch,Seurat,character-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch,Seurat,data.frame-method.html b/reference/GetNeighborsPerBatch,Seurat,data.frame-method.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighborsPerBatch,Seurat,data.frame-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch,matrix,ANY-method.html b/reference/GetNeighborsPerBatch,matrix,ANY-method.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighborsPerBatch,matrix,ANY-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetNeighborsPerBatch.html b/reference/GetNeighborsPerBatch.html new file mode 100644 index 0000000..509ea04 --- /dev/null +++ b/reference/GetNeighborsPerBatch.html @@ -0,0 +1,127 @@ + +Calculate number of nearest neighbours between batches — GetNeighborsPerBatch • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Calculate number of nearest neighbours between batches out of a knn graph

    +
    + +
    +

    Usage

    +
    GetNeighborsPerBatch(
    +  object,
    +  batch.var,
    +  graph.name = "RNA_nn",
    +  count.self = TRUE
    +)
    +
    +# S4 method for class 'Seurat,character'
    +GetNeighborsPerBatch(
    +  object,
    +  batch.var,
    +  graph.name = "RNA_nn",
    +  count.self = TRUE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    batch.var
    +

    name of a column in the Seurat object's metadata +containing batch information

    + + +
    graph.name
    +

    name of a Graph or Neighbor instance stored in +object. When available, prefer the distance based network to the +connectivities graph (especially when computed with the UMAP method).

    + + +
    count.self
    +

    whether to include self-to-self vertices in the calculation

    + +
    +
    +

    Value

    +

    a square count matrix of size number of batches (see Details +section)

    +
    +
    +

    Details

    +

    The output matrix will likely not be symmetrical. This is due to the approximate +nature of the nearest neighbour search algorithm used to compute the knn +graph. It must be read by row. For instance, the number of times +cells of batch 1 have cells of batch 3 in their nn is matrix[1,3]

    +
    +
    +

    See also

    +

    The classes Graph and +Neighbor

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/GetNeighboursPerBatch.html b/reference/GetNeighboursPerBatch.html new file mode 100644 index 0000000..77bc87e --- /dev/null +++ b/reference/GetNeighboursPerBatch.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/GetPropInterBatch.html b/reference/GetPropInterBatch.html new file mode 100644 index 0000000..9e9114c --- /dev/null +++ b/reference/GetPropInterBatch.html @@ -0,0 +1,120 @@ + +Calculate proportion of nearest neighbours between batches — GetPropInterBatch • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Calculate the proportion of nearest neighbours between batches out of a knn +graph

    +
    + +
    +

    Usage

    +
    GetPropInterBatch(
    +  object,
    +  batch.var,
    +  graph.name = "RNA_nn",
    +  count.self = TRUE,
    +  per.batch = TRUE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    batch.var
    +

    name of a column in the Seurat object's metadata +containing batch information

    + + +
    graph.name
    +

    name of a Graph or Neighbor instance stored in +object. When available, prefer the distance based network to the +connectivities graph (especially when computed with the UMAP method).

    + + +
    count.self
    +

    whether to include self-to-self vertices in the calculation

    + + +
    per.batch
    +

    whether to keep proportions per batch or to aggregate +everything

    + +
    +
    +

    Value

    +

    a vector of length 1 or number of batches, depending on +per.batch argument value

    +
    + + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/GetPropIntraBatch.html b/reference/GetPropIntraBatch.html new file mode 100644 index 0000000..2792284 --- /dev/null +++ b/reference/GetPropIntraBatch.html @@ -0,0 +1,120 @@ + +Calculate proportion of nearest neighbours within batches — GetPropIntraBatch • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Calculate the proportion of nearest neighbours within batches out of a knn +graph

    +
    + +
    +

    Usage

    +
    GetPropIntraBatch(
    +  object,
    +  batch.var,
    +  graph.name = "RNA_nn",
    +  count.self = TRUE,
    +  per.batch = TRUE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    batch.var
    +

    name of a column in the Seurat object's metadata +containing batch information

    + + +
    graph.name
    +

    name of a Graph or Neighbor instance stored in +object. When available, prefer the distance based network to the +connectivities graph (especially when computed with the UMAP method).

    + + +
    count.self
    +

    whether to include self-to-self vertices in the calculation

    + + +
    per.batch
    +

    whether to keep proportions per batch or to aggregate +everything

    + +
    +
    +

    Value

    +

    a vector of length 1 or number of batches, depending on +per.batch argument value

    +
    + + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/HarmonyIntegration.fix.html b/reference/HarmonyIntegration.fix.html new file mode 100644 index 0000000..a837257 --- /dev/null +++ b/reference/HarmonyIntegration.fix.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/HarmonyIntegration.html b/reference/HarmonyIntegration.html new file mode 100644 index 0000000..a7d7557 --- /dev/null +++ b/reference/HarmonyIntegration.html @@ -0,0 +1,286 @@ + +Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run Harmony on multi-layered Seurat V5 object

    +

    Can be called via SeuratIntegrate::HarmonyIntegration() or +HarmonyIntegration.fix()

    +
    + +
    +

    Usage

    +
    HarmonyIntegration(
    +  object,
    +  orig,
    +  groups = NULL,
    +  groups.name = NULL,
    +  layers = NULL,
    +  scale.layer = "scale.data",
    +  features = NULL,
    +  new.reduction = "harmony",
    +  dims = NULL,
    +  key = "harmony_",
    +  seed.use = 42L,
    +  theta = NULL,
    +  sigma = 0.1,
    +  lambda = NULL,
    +  nclust = NULL,
    +  ncores = 1L,
    +  max_iter = 10,
    +  early_stop = TRUE,
    +  plot_convergence = FALSE,
    +  .options = harmony_options(),
    +  verbose = TRUE,
    +  ...
    +)
    +
    +HarmonyIntegration.fix(...)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    orig
    +

    DimReduc object. Not to be set +directly when called with IntegrateLayers, use +orig.reduction argument instead

    + + +
    groups
    +

    A named data frame with grouping information. Preferably +one-column when groups.name = NULL

    + + +
    groups.name
    +

    Column name from groups data frame that stores +grouping information. If groups.name = NULL, the first column is used

    + + +
    layers
    +

    Ignored unless groups = NULL, then used to create +grouping variable to correct batch-effect.

    + + +
    scale.layer
    +

    Ignored

    + + +
    features
    +

    Ignored

    + + +
    new.reduction
    +

    Name of the new integrated dimensional reduction

    + + +
    dims
    +

    Dimensions of dimensional reduction to use for integration. +All used by default

    + + +
    key
    +

    Prefix for the dimension names computed by harmony.

    + + +
    seed.use
    +

    An integer to generate reproducible outputs. +Set seed.use = NULL to disable

    + + +
    theta
    +

    Diversity clustering penalty parameter. Specify for +each variable in vars_use Default theta=2. theta=0 does not +encourage any diversity. Larger values of theta result in more +diverse clusters.

    + + +
    sigma
    +

    Width of soft kmeans clusters. Default +sigma=0.1. Sigma scales the distance from a cell to cluster +centroids. Larger values of sigma result in cells assigned to +more clusters. Smaller values of sigma make soft kmeans cluster +approach hard clustering.

    + + +
    lambda
    +

    Ridge regression penalty. Default lambda=1. Bigger +values protect against over correction. If several covariates +are specified, then lambda can also be a vector which needs to +be equal length with the number of variables to be +corrected. In this scenario, each covariate level group will be +assigned the scalars specified by the user. If set to NULL, +harmony will start lambda estimation mode to determine lambdas +automatically and try to minimize overcorrection (Use with caution still +in beta testing).

    + + +
    nclust
    +

    Number of clusters in model. nclust=1 equivalent to +simple linear regression.

    + + +
    ncores
    +

    Number of processors to be used for math operations +when optimized BLAS is available. If BLAS is not supporting +multithreaded then this option has no effect. By default, +ncore=1 which runs as a single-threaded process. Although +Harmony supports multiple cores, it is not optimized for +multithreading. Increase this number for large datasets iff +single-core performance is not adequate.

    + + +
    max_iter
    +

    Maximum number of rounds to run Harmony. One round +of Harmony involves one clustering and one correction step.

    + + +
    early_stop
    +

    Enable early stopping for harmony. The +harmonization process will stop when the change of objective +function between corrections drops below 1e-4

    + + +
    plot_convergence
    +

    Whether to print the convergence plot of +the clustering objective function. TRUE to plot, FALSE to +suppress. This can be useful for debugging.

    + + +
    .options
    +

    Setting advanced parameters of RunHarmony. This must be the +result from a call to `harmony_options`. See ?`harmony_options` for +parameters not listed above and more details.

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    ...
    +

    Ignored for HarmonyIntegration(), or all of the above for +HarmonyIntegration.fix()

    + +
    +
    +

    Value

    +

    The function itself returns a list containing:

    • a new DimReduc of name reduction.name (key set to + reduction.key) with corrected cell embeddings matrix of + length(dims) columns.

    • +

    When called via IntegrateLayers, a Seurat object with +the new reduction is returned

    +
    +
    +

    Note

    +

    This function requires the +harmony package +to be installed

    +
    +
    +

    References

    +

    Korsunsky, I., Millard, N., Fan, J., Slowikowski, K., Zhang, F., +Wei, K., Baglaenko, Y., Brenner, M., Loh, P. & Raychaudhuri, S. Fast, +sensitive and accurate integration of single-cell data with Harmony. +Nat Methods 16, 1289–1296 (2019). DOI

    +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- UpdateSeuratObject(SeuratData::LoadData("pbmcsca"))
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers based on the "Method" variable:
    +obj <- IntegrateLayers(object = obj, method = SeuratIntegrate::HarmonyIntegration,
    +                       verbose = TRUE)
    +
    +# We can also change parameters such as the batch-effect variable.
    +# Here we change the groups variable, the number of dimension used from the original
    +# PCA and minor options from `harmony_options()`:
    +harmonyOptions <- harmony::harmony_options()
    +harmonyOptions$max.iter.cluster <- 10   #  20 by default
    +harmonyOptions$block.size <- .1         # .05 by default
    +obj <- IntegrateLayers(object = obj, method = SeuratIntegrate::HarmonyIntegration,
    +                       dims = 1:30, plot_convergence = TRUE,
    +                       groups = obj[[]]$Experiment,
    +                       new.reduction = "harmony_custom",
    +                       .options = harmonyOptions, verbose = TRUE)
    +} # }
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/IntegrationScores.html b/reference/IntegrationScores.html new file mode 100644 index 0000000..9890520 --- /dev/null +++ b/reference/IntegrationScores.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/MNNIntegration.html b/reference/MNNIntegration.html new file mode 100644 index 0000000..0afdf7a --- /dev/null +++ b/reference/MNNIntegration.html @@ -0,0 +1,175 @@ + +Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run mnnCorrect on multi-layered Seurat V5 object

    +
    + +
    +

    Usage

    +
    MNNIntegration(
    +  object,
    +  orig = NULL,
    +  groups = NULL,
    +  layers = NULL,
    +  scale.layer = NULL,
    +  features = 2000,
    +  reconstructed.assay = "mnn.reconstructed",
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    orig
    +

    DimReduc object. Not to be set +directly when called with IntegrateLayers, use +orig.reduction argument instead

    + + +
    groups
    +

    Ignored

    + + +
    layers
    +

    Name of the layers to use in the integration

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    features
    +

    Either a list of features to use when calculating batch +correction, or a number (2000 by default) of variable features to select.

    + + +
    reconstructed.assay
    +

    Name for the assay containing the low-rank +reconstruction of the expression matrix.

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    ...
    +

    Extra parameters passed to mnnCorrect

    + +
    +
    +

    Value

    +

    A Seurat object merged from the objects in object.list and a +new DimReduc of name reduction.name (key set to reduction.key) +with corrected embeddings matrix as well as the rotation matrix used for the +PCA stored in the feature loadings slot. Also returns an expression matrix +reconstructed from the low-rank approximation in the +reconstructed.assay assay; all other metadata info +mnnCorrect is stored in the tool slot, +accessible with Tool

    +
    +
    +

    Note

    +

    This function requires the +batchelor package +to be installed

    +
    +
    +

    See also

    + +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- UpdateSeuratObject(SeuratData::LoadData("pbmcsca"))
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers:
    +obj <- IntegrateLayers(object = obj, method = MNNIntegration,
    +  new.reduction = 'integrated.mnn', verbose = FALSE)
    +
    +# We can also add parameters specific to mnnCorrect.
    +# Here we set `k` to specify the number of nearest neighbors
    +# to use when identifying MNNs:
    +obj <- IntegrateLayers(object = obj, method = MNNIntegration,
    +  new.reduction = 'integrated.mnn', k = 15, verbose = FALSE)
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/NormaliseL2.html b/reference/NormaliseL2.html new file mode 100644 index 0000000..99576f4 --- /dev/null +++ b/reference/NormaliseL2.html @@ -0,0 +1,95 @@ + +Normalise a matrix using L2 norm — NormaliseL2 • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Normalise the rows or columns of a matrix using L2 norm

    +
    + +
    +

    Usage

    +
    NormaliseL2(mat, MARGIN = 1)
    +
    + +
    +

    Arguments

    + + +
    mat
    +

    a matrix (sparse or dense)

    + + +
    MARGIN
    +

    one of 1 or 2, corresponding to normalisation per rows and +columns respectively

    + +
    +
    +

    Value

    +

    the matrix with normalised rows or columns

    +
    +
    +

    Note

    +

    Adapted from Seurat:::L2Norm

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/PlotScores.html b/reference/PlotScores.html new file mode 100644 index 0000000..2748747 --- /dev/null +++ b/reference/PlotScores.html @@ -0,0 +1,180 @@ + +Visualise and compare the performances of integration algorithms — PlotScores • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Plot the scaled integration scores to compare the obtained integrations

    +
    + +
    +

    Usage

    +
    PlotScores(
    +  object,
    +  plot.type = c("dot", "radar", "lollipop"),
    +  split.by.score.type = TRUE,
    +  order.by = c("score", "name", "asis"),
    +  hide.zeros = FALSE,
    +  include.integration = NULL,
    +  exclude.integration = NULL,
    +  include.score = NULL,
    +  exclude.score = NULL,
    +  recompute.overall.scores = TRUE,
    +  rescale = TRUE,
    +  batch.coeff = 0.4,
    +  bio.coeff = 0.6,
    +  point.max.size = 20L,
    +  use.ggforce = is_installed("ggforce")
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    plot.type
    +

    one of 'table' (default), 'radar' or 'lollipop'. Type of +desired plot

    + + +
    split.by.score.type
    +

    whether to split scores by type (bio-conservation, +batch correction and overall scores). When set to FALSE, all scores +are mixed in a single figure.

    + + +
    order.by
    +

    one of 'score' (default), 'name' or 'asis'. Determines the +order of integrations in the legend (and on the y-axis for lolliplop and +table plots). Scores are ordered by decreasing overall score by default, +by name or by row-order when setting 'name' and 'asis' respectively.

    + + +
    hide.zeros
    +

    whether zero(ed) scores should be visible on the plot.

    + + +
    include.integration
    +

    name of the integration(s) to include. The +default value (NULL) enable to include them all.

    + + +
    exclude.integration
    +

    name of the integration(s) to exclude. The default +value (NULL) enable to include them all.

    + + +
    include.score
    +

    name of the score(s) to include. The default value +(NULL) enable to include them all.

    + + +
    exclude.score
    +

    name of the score(s) to exclude. The default value +(NULL) enable to include them all.

    + + +
    recompute.overall.scores
    +

    whether to recompute overall scores. Useful +when there is a restriction on scores to plot. When FALSE, +coefficient parameters have no impact.

    + + +
    rescale
    +

    whether to rescale each score between 0 and 1 using min-max +normalisation before computing overall scores. This ensures that each metric +equally contributes to the overall scores. Has no effect when +recompute.overall.scores = FALSE. TRUE by default

    + + +
    batch.coeff
    +

    the weight of batch correction performance evaluation +scores in the overall score.

    + + +
    bio.coeff
    +

    the weight of bio-conservation performance evaluation scores +in the overall score.

    + + +
    point.max.size
    +

    inoperative unless plot.type = 'table' and +use.ggforce = FALSE. Determine the maximum size of the points +(only achieved for a score of 1) to fit the plotting area (handled +automaticaly when ggforce is used).

    + + +
    use.ggforce
    +

    for plot.type = 'table', enable or disable the use +of ggforce to draw the circles. Used by default when the package is +installed

    + +
    +
    +

    Value

    +

    a ggplot object

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/ScaleScores.html b/reference/ScaleScores.html new file mode 100644 index 0000000..8d36bb3 --- /dev/null +++ b/reference/ScaleScores.html @@ -0,0 +1,118 @@ + +Scale the scores in the score tibble to plot them — ScaleScores • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Once the scores of interest have been computed and saved in the score tibble, +they can be scaled to make them comparable by bounding them between 0 and 1 +and harmonise their direction (0 and 1 always mean bad and good performance +respectively). This is also a prerequisite for plotting.

    +
    + +
    +

    Usage

    +
    ScaleScores(
    +  object,
    +  ref = "Unintegrated",
    +  rescale = FALSE,
    +  batch.coeff = 0.4,
    +  bio.coeff = 0.6
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    ref
    +

    the name of the integration to use as a reference for scaling. +Useful for PCA regression (and density) and cell cycle conservation scores.

    + + +
    rescale
    +

    whether to rescale each score between 0 and 1 using min-max +normalisation before computing overall scores. This ensures that each metric +equally contributes to the overall scores. TRUE by default

    + + +
    batch.coeff
    +

    the weight of batch correction performance evaluation +scores in the overall score.

    + + +
    bio.coeff
    +

    the weight of bio-conservation performance evaluation scores +in the overall score.

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/ScanoramaIntegration.html b/reference/ScanoramaIntegration.html new file mode 100644 index 0000000..26d0ef5 --- /dev/null +++ b/reference/ScanoramaIntegration.html @@ -0,0 +1,285 @@ + +Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run Scanorama on multi-layered Seurat V5 object. +Requires a conda environment with scanorama and necessary dependencies

    +
    + +
    +

    Usage

    +
    ScanoramaIntegration(
    +  object,
    +  orig,
    +  layers = NULL,
    +  features = NULL,
    +  scale.layer = "scale.data",
    +  conda_env = NULL,
    +  new.reduction = "integrated.scanorama",
    +  reduction.key = "scanorama_",
    +  reconstructed.assay = "scanorama.reconstructed",
    +  ncores = 1L,
    +  ndims.out = 100L,
    +  return_dense = TRUE,
    +  batch_size = 5000,
    +  approx = TRUE,
    +  sigma = 15L,
    +  alpha = 0.1,
    +  knn = 20L,
    +  hvg.scanorama = NULL,
    +  union.features = FALSE,
    +  sketch = FALSE,
    +  sketch_method = c("geosketch", "uniform"),
    +  sketch_max = 10000,
    +  seed.use = 42L,
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    orig
    +

    DimReduc object. Not to be set +directly when called with IntegrateLayers, use +orig.reduction argument instead

    + + +
    layers
    +

    Name of the layers to use in the integration

    + + +
    features
    +

    Vector of feature names to input to the integration method. +When features = NULL (default), the +VariableFeatures are used. To pass all features, +use the output of Features()

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    conda_env
    +

    Path to conda environment to run scanorama (should also +contain the scipy python module). By default, uses the conda environment +registered for scanorama in the conda environment manager

    + + +
    new.reduction
    +

    Name to store resulting +dimensional reduction object. NULL or +FALSE disables the dimension reduction computation

    + + +
    reduction.key
    +

    Key for resulting +dimensional reduction object. Ignored if +reduction.key is NULL or FALSE

    + + +
    reconstructed.assay
    +

    Name for the assay containing the corrected +expression matrix of dimension #features x #cells. NULL or +FALSE disables the corrected expression matrix computation

    + + +
    ncores
    +

    Number of parallel threads to create through +blas_set_num_threads. Pointless if BLAS is not supporting +multithreaded

    + + +
    ndims.out
    +

    Number of dimensions for new.reduction output. +Scanorama specific argument

    + + +
    return_dense
    +

    Whether scanorama returns numpy.ndarray matrices +instead of scipy.sparse.csr_matrix. Scanorama specific argument

    + + +
    batch_size
    +

    Used in the alignment vector computation. Higer values +increase memory burden.Scanorama specific argument

    + + +
    approx
    +

    Whether scanorama approximates nearest neighbors computation. +Scanorama specific argument

    + + +
    sigma
    +

    Correction smoothing parameter on gaussian kernel. Scanorama +specific argument

    + + +
    alpha
    +

    Minimum alignment score. Scanorama specific argument

    + + +
    knn
    +

    Number of nearest neighbours used for matching. Scanorama +specific argument

    + + +
    hvg.scanorama
    +

    A positive integer to turn scanorama's internal HVG +selection on. Disabled by default. Scanorama specific argument

    + + +
    union.features
    +

    By default, scanorama uses the intersection of features +to perform integration. Set this parameter to TRUE to use the union. +Discouraged. Scanorama specific argument

    + + +
    sketch
    +

    Turns on sketching-based acceleration by first downsampling the +datasets. See Hie et al., Cell Systems (2019). Disabled by default. Ignored +when reconstructed.assay is enabled. Scanorama specific argument

    + + +
    sketch_method
    +

    A skething method to apply to the data. Either +'geosketch' (default) or 'uniform'. Ignored when reconstructed.assay +is enabled or when sketch is FALSE. Scanorama specific argument

    + + +
    sketch_max
    +

    Downsampling cutoff. Ignored when sketching disabled. +Scanorama specific argument

    + + +
    seed.use
    +

    An integer to generate reproducible outputs. +Set seed.use = NULL to disable

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    ...
    +

    Ignored

    + +
    +
    +

    Value

    +

    A list containing at least one of:

    • a new DimReduc of name reduction.name (key set to + reduction.key) with corrected embeddings matrix of ndims.out.

    • +
    • a new Assay of name reconstructed.assay with corrected counts + for each features (or less if hvg is set to a lower integer).

    • +

    When called via IntegrateLayers, a Seurat object with +the new reduction and/or assay is returned

    +
    +
    +

    Note

    +

    This function requires the +Scanorama package +to be installed (along with scipy)

    +
    +
    +

    References

    +

    Hie, B., Bryson, B. & Berger, B. Efficient integration of +heterogeneous single-cell transcriptomes using Scanorama. Nat Biotechnol 37, +685–691 (2019). DOI

    +
    +
    +

    See also

    + +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers:
    +obj <- IntegrateLayers(object = obj, method = ScanoramaIntegration)
    +
    +# To disable feature expression matrix correction:
    +obj <- IntegrateLayers(object = obj, method = ScanoramaIntegration,
    +                       reconstructed.assay = NULL)
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/ScoreASW.html b/reference/ScoreASW.html new file mode 100644 index 0000000..18e38da --- /dev/null +++ b/reference/ScoreASW.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/ScoreASWBatch.html b/reference/ScoreASWBatch.html new file mode 100644 index 0000000..18e38da --- /dev/null +++ b/reference/ScoreASWBatch.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/ScoreLISI.html b/reference/ScoreLISI.html new file mode 100644 index 0000000..738c79a --- /dev/null +++ b/reference/ScoreLISI.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/SetMiscScore.html b/reference/SetMiscScore.html new file mode 100644 index 0000000..0e7cfa6 --- /dev/null +++ b/reference/SetMiscScore.html @@ -0,0 +1,112 @@ + +Set the value of a score in the score tibble — SetMiscScore • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Set a score value for a given integration and a given score name. If they +don't exist yet, they are created though AddMiscIntegrations +and AddMiscScores respectively.

    +
    + +
    +

    Usage

    +
    SetMiscScore(object, integration, score.name, score.value, ...)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    integration
    +

    the name of the integration for which the score was +computed.

    + + +
    score.name
    +

    the name of the computed score

    + + +
    score.value
    +

    the value of the score

    + + +
    ...
    +

    additional parameter to pass to AddMiscScores. Has +no effect if the score slot is already present in the tibble. Otherwise, +enable to pass the class argument to specify the class of the score +slot to create.

    + +
    +
    +

    Value

    +

    the Seurat object with updated table of scores.

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/SeuratIntegrate-package.html b/reference/SeuratIntegrate-package.html new file mode 100644 index 0000000..389b01c --- /dev/null +++ b/reference/SeuratIntegrate-package.html @@ -0,0 +1,88 @@ + +SeuratIntegrate: Expands the set of integration methods available to Seurat — SeuratIntegrate-package • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    +

    R package gathering a set of wrappers to apply various integration methods to Seurat objects (and rate such methods). Intended to apply to Seurat V5 objects bearing multiple layers.

    +
    + + + +
    +

    Author

    +

    Maintainer: Florian Specque florian.specque@u-bordeaux.fr (ORCID)

    +

    Authors:

    Other contributors:

    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/SeuratIntegrate.html b/reference/SeuratIntegrate.html new file mode 100644 index 0000000..0da9abb --- /dev/null +++ b/reference/SeuratIntegrate.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/SymmetrizeKnn,Graph-method.html b/reference/SymmetrizeKnn,Graph-method.html new file mode 100644 index 0000000..a256377 --- /dev/null +++ b/reference/SymmetrizeKnn,Graph-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/SymmetrizeKnn,Matrix-method.html b/reference/SymmetrizeKnn,Matrix-method.html new file mode 100644 index 0000000..a256377 --- /dev/null +++ b/reference/SymmetrizeKnn,Matrix-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/SymmetrizeKnn,Neighbor-method.html b/reference/SymmetrizeKnn,Neighbor-method.html new file mode 100644 index 0000000..a256377 --- /dev/null +++ b/reference/SymmetrizeKnn,Neighbor-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/SymmetrizeKnn,Seurat-method.html b/reference/SymmetrizeKnn,Seurat-method.html new file mode 100644 index 0000000..a256377 --- /dev/null +++ b/reference/SymmetrizeKnn,Seurat-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/SymmetrizeKnn.html b/reference/SymmetrizeKnn.html new file mode 100644 index 0000000..480fa0d --- /dev/null +++ b/reference/SymmetrizeKnn.html @@ -0,0 +1,125 @@ + +Symmetrize a nearest neighbours graph — SymmetrizeKnn • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    The approximate nature of the nearest neighbour search algorithm used to +compute the knn graph makes the resulting adjacency matrix asymmetric. +Those functions symmetrize a Graph or a Neighbor object.

    +
    + +
    +

    Usage

    +
    SymmetrizeKnn(object, graph.name = "RNA_nn", use.max = TRUE, assay = NULL)
    +
    +# S4 method for class 'Seurat'
    +SymmetrizeKnn(object, graph.name = "RNA_nn", use.max = TRUE, assay = NULL)
    +
    +# S4 method for class 'Matrix'
    +SymmetrizeKnn(object, use.max = TRUE)
    +
    +# S4 method for class 'Graph'
    +SymmetrizeKnn(object, use.max = TRUE)
    +
    +# S4 method for class 'Neighbor'
    +SymmetrizeKnn(object, use.max = TRUE)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat, Graph or Neighbor object

    + + +
    graph.name
    +

    name of a Graph or Neighbor instance stored in +the Seurat object.

    + + +
    use.max
    +

    by default, use the maximum value in case of discrepancy +between m[i,j] and m[j,i]. Set to FALSE to use the minimum value.

    + + +
    assay
    +

    name of the assay to store in the output Graph

    + +
    +
    +

    Value

    +

    the Seurat object with a new Graph instance or a +dgCMatrix representing the Graph itself

    +
    +
    +

    See also

    +

    The classes Graph and +Neighbor and +symmetrize.pmax.sparse

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/UpdateEnvCache.html b/reference/UpdateEnvCache.html new file mode 100644 index 0000000..c488b2d --- /dev/null +++ b/reference/UpdateEnvCache.html @@ -0,0 +1,157 @@ + +Handy CondaEnvManger instance modifier — UpdateEnvCache • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Wrapper to update the CondaEnvManager object stored in cache +and used as configuration for conda environments for all known methods +(typically stored in the package's cache). A single method can be +updated at the time. In most cases, this is the best way to modify the +package's conda environments registry.

    +
    + +
    +

    Usage

    +
    UpdateEnvCache(
    +  method = known.methods,
    +  conda.bin = "auto",
    +  conda.env = NULL,
    +  conda.env.is.path = "auto",
    +  separate.scvi.envs = FALSE,
    +  overwrite.env = FALSE,
    +  dry.run = FALSE
    +)
    +
    + +
    +

    Arguments

    + + +
    method
    +

    the name of the method to update. One of "combat", "harmony", +"mnn", "bbknn", "scvi", "scanvi", "scanorama", "trvae"

    + + +
    conda.bin
    +

    the path to the conda binary. If empty (""), +NULL or "conda", "auto" is passed to +conda_binary() to find the path to the conda binary in +PATH

    + + +
    conda.env
    +

    Either the name of a conda environment or the path to such +an environment. Must be reachable by provided conda.bin. NULL +enable to use the default environment names. (see Details section)

    + + +
    conda.env.is.path
    +

    Whether the conda.env is a path (TRUE), +or a name (FALSE). The default ("auto") guesses. Be +careful not to make a mistake if you switch to a non-default value

    + + +
    separate.scvi.envs
    +

    By default, SCVI and SCANVI share the same conda +environment, since they rely on the same python package. If you wish to have +a distinct environment for each, set it to TRUE. Ignored if +method is not SCVI nor SCANVI.

    + + +
    overwrite.env
    +

    Turn it to TRUE to enable overwriting an existing +environment (same name or same path). When the provided conda.env +already exists, the default behaviour is to update the package's registry +with the existing environment as it is

    + + +
    dry.run
    +

    When TRUE, the package's current cache is not updated. +But the new conda environment (if any) will be created. FALSE by default.

    + +
    +
    +

    Value

    +

    a CondaEnvManager object

    +
    +
    +

    Details

    +

    The conda environments default names are:

    • bbknn: SeuratIntegrate_scvi

    • +
    • SCVI: SeuratIntegrate_scvi-tools

    • +
    • SCANVI: SeuratIntegrate_scvi-tools

    • +
    • scanorama: SeuratIntegrate_scanorama

    • +
    • trVAE: SeuratIntegrate_trvae

    • +
    + + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/[,numeric_lisi,ANY,ANY,ANY-method.html b/reference/[,numeric_lisi,ANY,ANY,ANY-method.html new file mode 100644 index 0000000..154c755 --- /dev/null +++ b/reference/[,numeric_lisi,ANY,ANY,ANY-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/add-score.html b/reference/add-score.html new file mode 100644 index 0000000..aedac44 --- /dev/null +++ b/reference/add-score.html @@ -0,0 +1,107 @@ + +Add integration(s) or score(s) slot(s) to the score tibble — add-score • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    AddMiscIntegrations: Add integration(s) slot(s) to the score tibble +(or make sure they are in it). This enables to save their scores later.

    +

    AddMiscScores: Add score(s) slot(s) to the score tibble (or make sure +they are in it). This enables to save them later.

    +
    + +
    +

    Usage

    +
    AddMiscIntegrations(object, which)
    +
    +AddMiscScores(object, which, class = "numeric")
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + +
    which
    +

    the name of the new integration(s) or score(s)

    + + +
    class
    +

    the class of the column, such as 'numeric' (default). For +instance, cell cycle conservation scores are 'list' and LISI scores are +'numeric_lisi'.

    + +
    +
    +

    Value

    +

    the Seurat object with updated table of scores.

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/bbknnIntegration.html b/reference/bbknnIntegration.html new file mode 100644 index 0000000..78bc879 --- /dev/null +++ b/reference/bbknnIntegration.html @@ -0,0 +1,261 @@ + +Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run bbknn on multi-layered Seurat V5 object. +Requires a conda environment with bbknn and necessary dependencies

    +
    + +
    +

    Usage

    +
    bbknnIntegration(
    +  object,
    +  orig,
    +  groups = NULL,
    +  groups.name = NULL,
    +  layers = "data",
    +  scale.layer = "scale.data",
    +  conda_env = NULL,
    +  new.graph = "bbknn",
    +  new.reduction = "pca.bbknn",
    +  reduction.key = "bbknnPCA_",
    +  reconstructed.assay = "bbknn.ridge",
    +  ndims = 50L,
    +  ndims.use = 30L,
    +  ridge_regression = T,
    +  graph.use = c("connectivities", "distances"),
    +  verbose = TRUE,
    +  seed.use = 42L,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    orig
    +

    DimReduc object. Not to be set +directly when called with IntegrateLayers, use +orig.reduction argument instead

    + + +
    groups
    +

    A named data frame with grouping information. Preferably +one-column when groups.name = NULL

    + + +
    groups.name
    +

    Column name from groups data frame that stores +grouping information. If groups.name = NULL, the first column is used

    + + +
    layers
    +

    Name of the layers to use in the integration

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    conda_env
    +

    Path to conda environment to run bbknn (should also +contain the scipy python module). By default, uses the conda environment +registered for bbknn in the conda environment manager

    + + +
    new.graph
    +

    Name of the Graph object

    + + +
    new.reduction
    +

    Name of the new integrated dimensional reduction

    + + +
    reduction.key
    +

    Key for the new integrated dimensional reduction

    + + +
    reconstructed.assay
    +

    Name for the assay containing the corrected +expression matrix

    + + +
    ndims
    +

    Number of dimensions for the new PCA computed on first output of +bbknn. 50 by default. Ignored when ridge_regression = FALSE

    + + +
    ndims.use
    +

    Number of dimensions from orig to use for bbknn, and +from newly computed PCA when ridge_regression = TRUE.

    + + +
    ridge_regression
    +

    When set to TRUE (default), new clusters are +computed on the output of bbknn, then a ridge regression is performed to +remove technical variables while preserving biological variables. Then, a new +bbknn run is performed.

    + + +
    graph.use
    +

    Which graph(s) of bbknn to output. At least one of +"connectivities" or "distances". If both are provided (default) +and ridge_regression = TRUE, the first one ("connectivities" by +default, recommended) is used as input for computing clusters.

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    seed.use
    +

    An integer to generate reproducible outputs. +Set seed.use = NULL to disable

    + + +
    ...
    +

    Additional arguments to be passed to bbknn.bbknn(). When +ridge_regression = TRUE, also accepts arguments to pass to +Seurat::FindClusters(), Seurat::RunPCA() and +bbknn.ridge_regression(). See Details section

    + +
    +
    +

    Value

    +

    A list containing at least one of:

    • 1 or 2 new Graph(s) of name + [new_graph]_scale.data_[graph.use] + corresponding to the output(s) of the first run of bbknn

    • +
    • a new Assay of name reconstructed.assay with corrected counts + for each feature from scale.layer.

    • +
    • a new DimReduc (PCA) of name new.reduction (key set to + reduction.key)

    • +
    • 1 or 2 new Graph(s) of name + [new_graph]_ridge.residuals_[graph.use] + corresponding to the output(s) of the second run of bbknn

    • +

    [graph.use] can take two values (either "connectivities" or +"distances"), depending on the graph.use parameter.

    +

    When called via IntegrateLayers, a Seurat object with +the new reduction and/or assay is returned

    +
    +
    +

    Details

    +

    This wrappers calls three python functions through reticulate. +Find the bbknn-specific arguments there:

    +
    +

    Note

    +

    This function requires the +bbknn package +to be installed (along with scipy)

    +
    +
    +

    References

    +

    Polański, K., Young, M. D., Miao, Z., Meyer, K. B., Teichmann, +S. A. & Park, J.-E. BBKNN: fast batch alignment of single cell transcriptomes. +Bioinformatics 36, 964–965 (2019). +DOI

    +
    + + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers:
    +obj <- IntegrateLayers(object = obj, method = bbknnIntegration,
    +                       conda_env = 'bbknn', groups = obj[[]],
    +                       groups.name = 'Method')
    +
    +# To disable the ridge regression and subsequent steps:
    +obj <- IntegrateLayers(object = obj, method = bbknnIntegration,
    +                       conda_env = 'bbknn', groups = obj[[]],
    +                       groups.name = 'Method', ridge_regression = FALSE)
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/checkCondaBin,CondaEnv-method.html b/reference/checkCondaBin,CondaEnv-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaBin,CondaEnv-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaBin,CondaEnvSlot-method.html b/reference/checkCondaBin,CondaEnvSlot-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaBin,CondaEnvSlot-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnv,CondaEnv-method.html b/reference/checkCondaEnv,CondaEnv-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnv,CondaEnv-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnv,CondaEnvManager-method.html b/reference/checkCondaEnv,CondaEnvManager-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnv,CondaEnvManager-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnv.html b/reference/checkCondaEnv.html new file mode 100644 index 0000000..d88ba4e --- /dev/null +++ b/reference/checkCondaEnv.html @@ -0,0 +1,129 @@ + +Check the validity of conda environment's components — checkCondaBin • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Check the validity of conda environment's components. Best used on a +CondaEnv object. Internally call:

    + +
    +

    Usage

    +
    checkCondaBin(x, ..., verbose = getOption("verbose"))
    +
    +checkCondaEnvPath(x, ..., verbose = getOption("verbose"))
    +
    +checkCondaEnvName(x, ..., verbose = getOption("verbose"))
    +
    +checkCondaEnv(x, ..., verbose = getOption("verbose"))
    +
    + +
    +

    Arguments

    + + +
    x
    +

    a CondaEnv object or a sub element of it of class +CondaEnvSlot. checkCondaEnv() only accepts a CondaEnv object

    + + +
    ...
    +

    ignored when x is a CondaEnv object. +Otherwise, additional arguments to reticulate functions in +Description such as conda = ...

    + + +
    verbose
    +

    ignored

    + +
    +
    +

    Value

    +

    an updated object of same class as input x

    +
    +
    +

    Note

    +

    checkCondaEnv is a wrapper that calls all checks.

    +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/checkCondaEnvName,CondaEnv-method.html b/reference/checkCondaEnvName,CondaEnv-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnvName,CondaEnv-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnvName,CondaEnvSlot-method.html b/reference/checkCondaEnvName,CondaEnvSlot-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnvName,CondaEnvSlot-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnvName.html b/reference/checkCondaEnvName.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnvName.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnvPath,CondaEnv-method.html b/reference/checkCondaEnvPath,CondaEnv-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnvPath,CondaEnv-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnvPath,CondaEnvSlot-method.html b/reference/checkCondaEnvPath,CondaEnvSlot-method.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnvPath,CondaEnvSlot-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/checkCondaEnvPath.html b/reference/checkCondaEnvPath.html new file mode 100644 index 0000000..2ad4792 --- /dev/null +++ b/reference/checkCondaEnvPath.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/colSort.html b/reference/colSort.html new file mode 100644 index 0000000..409aa67 --- /dev/null +++ b/reference/colSort.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/colSorted.html b/reference/colSorted.html new file mode 100644 index 0000000..409aa67 --- /dev/null +++ b/reference/colSorted.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/figures/logo.png b/reference/figures/logo.png new file mode 100644 index 0000000..ed84ab2 Binary files /dev/null and b/reference/figures/logo.png differ diff --git a/reference/get-score.html b/reference/get-score.html new file mode 100644 index 0000000..33bb343 --- /dev/null +++ b/reference/get-score.html @@ -0,0 +1,123 @@ + +Retrieve integration scores from a Seurat object — GetMiscIntegrations • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Scores are stored as tibble objects in Misc. Slot for raw scores is named +'si_scores' while scaled scores are found under 'si_scaled.scores'.

    +

    GetMiscIntegrations: Get (or search for) integration names in the +score tibble

    +

    GetMiscScores: Get (or search for) score names in the score tibble

    +

    IntegrationScores: Get the tibble with scaled or unscaled scores

    +
    + +
    +

    Usage

    +
    GetMiscIntegrations(object, search = NULL)
    +
    +GetMiscScores(object, search = NULL)
    +
    +IntegrationScores(object, scaled = FALSE)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    a Seurat object

    + + + +

    a character vector of names to search for through +case-insensitive exact match. NULL disables the search (default)

    + + +
    scaled
    +

    whether to query the unscaled (default) or scaled scores (if +scaling has been performed)

    + +
    +
    +

    Value

    +

    GetMiscIntegrations: a character vector of integration names, +or NULL when the object doesn't have 'si_scores' in Misc or when +search did not return any result.

    +

    GetMiscScores: a character vector of score names, or NULL when +the object doesn't have 'si_scores' in Misc or when search did not return any +result.

    +

    IntegrationScores: either NULL if the requested object does not +exist, otherwise a tibble. The first column contains the name of the +integrations, and each following column corresponds to a score.

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/getCache.html b/reference/getCache.html new file mode 100644 index 0000000..1427bc2 --- /dev/null +++ b/reference/getCache.html @@ -0,0 +1,86 @@ + +Get current cache of conda environments — getCache • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Get current cache of conda environments from package environment or cache on disk

    +
    + +
    +

    Usage

    +
    getCache(from = c("env", "cache"))
    +
    + +
    +

    Arguments

    + + +
    from
    +

    Either "env" or "cache". Where to load cache from.

    + +
    +
    +

    Value

    +

    a CondaEnvManager object

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/getCachePath.html b/reference/getCachePath.html new file mode 100644 index 0000000..f3aba3d --- /dev/null +++ b/reference/getCachePath.html @@ -0,0 +1,87 @@ + +Get path to package config cache — getCachePath • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Get path to package config cache file or directory

    +
    + +
    +

    Usage

    +
    getCachePath(include.file = TRUE)
    +
    + +
    +

    Arguments

    + + +
    include.file
    +

    Set to FALSE to retrieve the directory containing +the cache file. Return the path to the file by default.

    + +
    +
    +

    Value

    +

    A single character, the path to the cache file or directory

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/idx2col.html b/reference/idx2col.html new file mode 100644 index 0000000..db772f3 --- /dev/null +++ b/reference/idx2col.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/idx2row.html b/reference/idx2row.html new file mode 100644 index 0000000..db772f3 --- /dev/null +++ b/reference/idx2row.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/index.html b/reference/index.html new file mode 100644 index 0000000..64e1558 --- /dev/null +++ b/reference/index.html @@ -0,0 +1,585 @@ + +Package index • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Conda environment management

    + + + + +
    + +

    Modification interface

    +

    Set, update, remove conda environments

    + + +
    + + + + +
    + + UpdateEnvCache() + +
    +
    Handy CondaEnvManger instance modifier
    +
    + + resetCache() + +
    +
    Reset a conda environment
    +
    + + saveToCache() + +
    +
    Save a conda environment manager to cache
    +
    + +

    Access interface

    +

    Show the current state of environments or the location of cache on disk

    + + +
    + + + + +
    + + getCache() + +
    +
    Get current cache of conda environments
    +
    + + getCachePath() + +
    +
    Get path to package config cache
    +
    + + reloadCache() + +
    +
    Reload cache from disk
    +
    + +

    Class constructors

    + + + +
    + + + + +
    + + CondaEnv() + +
    +
    Handy CondaEnv instance constructor
    +
    + + CondaManager() + +
    +
    Handy CondaEnvManger instance constructor
    +
    + +

    Checkers

    +

    Check usability of conda environments

    + + +
    + + + + +
    + + isValid() + +
    +
    Check the validity of conda environment's components
    +
    + + checkCondaBin() checkCondaEnvPath() checkCondaEnvName() checkCondaEnv() + +
    +
    Check the validity of conda environment's components
    +
    +

    Data integration

    + + + + +
    + +

    Main interface

    +

    Integrate the layers of a Seurat object with one or more methods

    + + +
    + + + + +
    + + DoIntegrate() + +
    +
    Integrate layers using one or multiple integration method(s)
    +
    + +

    Methods included in SeuratIntegrate

    + + + +
    + + + + +
    + + CombatIntegration() + +
    +
    Run ComBat on Seurat's Assay5 object through IntegrateLayers
    +
    + + HarmonyIntegration() HarmonyIntegration.fix() + +
    +
    Run Harmony on Seurat's Assay5 object through IntegrateLayers
    +
    + + MNNIntegration() + +
    +
    Run classical MNN on Seurat's Assay5 object through IntegrateLayers
    +
    + + ScanoramaIntegration() + +
    +
    Run Scanorama on Seurat's Assay5 object through IntegrateLayers
    +
    + + bbknnIntegration() + +
    +
    Run bbknn on Seurat's Assay5 object through IntegrateLayers
    +
    + + scANVIIntegration() + +
    +
    Run scANVI on Seurat's Assay5 object through IntegrateLayers
    +
    + + scVIIntegration() scVIIntegration.fix() + +
    +
    Run scVI on Seurat's Assay5 object through IntegrateLayers
    +
    + + trVAEIntegration() + +
    +
    Run trVAE on Seurat's Assay5 object through IntegrateLayers
    +
    + +

    Compatible methods from other packages

    + + + +
    + + + + +
    + + RPCAIntegration() + +
    +
    Seurat-RPCA Integration (from Seurat)
    +
    + + CCAIntegration() + +
    +
    Seurat-CCA Integration (from Seurat)
    +
    + + FastMNNIntegration() + +
    +
    Run fastMNN in Seurat 5 (from SeuratWrappers)
    +
    +

    Scoring

    + + + + +
    + +

    Preprocessing

    +

    Useful functions to preprocess outputs before scoring

    + + +
    + + + + +
    + + FindOptimalClusters() + +
    +
    Find a clustering that maximises NMI or ARI
    +
    + + CellCycleScoringPerBatch() + +
    +
    Score cell cycle phases per batch
    +
    + +

    Scoring

    +

    Functions to score integrations

    + + +
    + + + + +
    + + ScoreARI() AddScoreARI() + +
    +
    Score a clustering result with adjusted rand index
    +
    + + ScoreASW() AddScoreASW() ScoreASWBatch() AddScoreASWBatch() + +
    +
    Score an embedding or a count matrix with the average silhouette width
    +
    + + ScoreRegressPC.CellCycle() AddScoreRegressPC.CellCycle() + +
    +
    Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance
    +
    + + ScoreConnectivity() AddScoreConnectivity() + +
    +
    Score a knn graph based on cell-type label connectivity
    +
    + + ScoreDensityPC() AddScoreDensityPC() + +
    +
    Score a corrected or uncorrected PCA to estimate batch mixing
    +
    + + ScoreKBET() AddScoreKBET() + +
    +
    Score an embedding or a knn graph with the kBET test
    +
    + + AddScoreLISI() ScoreLISI() + +
    +
    Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index
    +
    + + ScoreNMI() AddScoreNMI() + +
    +
    Score a clustering result with normalised mutual information
    +
    + + ScoreRegressPC() AddScoreRegressPC() + +
    +
    Score a corrected or uncorrected PCA to estimate batch mixing
    +
    + +

    Postprocessing

    +

    Once AddScore[..] functions have been run, scores are to be scaled then plotted

    + + +
    + + + + +
    + + ScaleScores() + +
    +
    Scale the scores in the score tibble to plot them
    +
    + + PlotScores() + +
    +
    Visualise and compare the performances of integration algorithms
    +
    + +

    General getters and setters of score table

    +

    Get, set, modify scores in a more flexible way

    + + +
    + + + + +
    + + GetMiscIntegrations() GetMiscScores() IntegrationScores() + +
    +
    Retrieve integration scores from a Seurat object
    +
    + + SetMiscScore() + +
    +
    Set the value of a score in the score tibble
    +
    + + AddMiscIntegrations() AddMiscScores() + +
    +
    Add integration(s) or score(s) slot(s) to the score tibble
    +
    +

    Graph-based utilities

    + + + + +
    + +

    Graph manipulation

    +

    Handy functions to manipulate and modify graphs

    + + +
    + + + + +
    + + SymmetrizeKnn() + +
    +
    Symmetrize a nearest neighbours graph
    +
    + + CutKnn() + +
    +
    Remove excessive number of neighbours in a knn graph
    +
    + + ExpandNeighbours() + +
    +
    Expand knn graph to increase the number of neighbours
    +
    + + GetConnectivities() + +
    +
    Derive connectivities from distances
    +
    + +

    Connectivity between batches

    +

    Handy functions to overview inter- and intra-batches connections in a knn graph

    + + +
    + + + + +
    + + GetPropInterBatch() + +
    +
    Calculate proportion of nearest neighbours between batches
    +
    + + GetPropIntraBatch() + +
    +
    Calculate proportion of nearest neighbours within batches
    +
    +

    Utility functions for matrices

    + +

    Functions designed for smaller-scale, auxiliary tasks on matrices.

    + + +
    + +

    Matrix normalisation

    + + + +
    + + + + +
    + + NormaliseL2() + +
    +
    Normalise a matrix using L2 norm
    +
    + +

    Matrix sorting

    + + + +
    + + + + +
    + + rowSort() colSort() rowSorted() colSorted() + +
    +
    Matrix sorting
    +
    + +

    Sparse matrix symmetry

    + + + +
    + + + + +
    + + symmetrize.pmax.sparse() symmetrize.pmin.sparse() + +
    +
    Matrix symmetrizing
    +
    + +

    Matrix sorting

    + + + +
    + + + + +
    + + rowSort() colSort() rowSorted() colSorted() + +
    +
    Matrix sorting
    +
    + +

    Conversion of matrix indices

    + + + +
    + + + + +
    + + rowcol2idx() idx2col() idx2row() + +
    +
    Matrix indexing
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/isValid,CondaEnv-method.html b/reference/isValid,CondaEnv-method.html new file mode 100644 index 0000000..523f8f9 --- /dev/null +++ b/reference/isValid,CondaEnv-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/isValid,CondaEnvManager-method.html b/reference/isValid,CondaEnvManager-method.html new file mode 100644 index 0000000..523f8f9 --- /dev/null +++ b/reference/isValid,CondaEnvManager-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/isValid,CondaEnvSlot-method.html b/reference/isValid,CondaEnvSlot-method.html new file mode 100644 index 0000000..523f8f9 --- /dev/null +++ b/reference/isValid,CondaEnvSlot-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/isValid.html b/reference/isValid.html new file mode 100644 index 0000000..e204ee5 --- /dev/null +++ b/reference/isValid.html @@ -0,0 +1,120 @@ + +Check the validity of conda environment's components — isValid • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Get the validity of conda environment's components. Best used on a +CondaEnvManager or a +CondaEnv object.

    +
    + +
    +

    Usage

    +
    isValid(x, ...)
    +
    +# S4 method for class 'CondaEnvSlot'
    +isValid(x, ...)
    +
    +# S4 method for class 'CondaEnv'
    +isValid(x, do.check = FALSE, ...)
    +
    +# S4 method for class 'CondaEnvManager'
    +isValid(x, ...)
    +
    + +
    +

    Arguments

    + + +
    x
    +

    a CondaEnvManager, a +CondaEnv object or a sub element of it of class +CondaEnvSlot.

    + + +
    ...
    +

    ignored when x is a CondaEnvSlot object. Otherwise, +can be used to pass do.check argument.

    + + +
    do.check
    +

    whether to call check functions. Does +not apply when x is a CondaEnvSlot object.

    + +
    +
    +

    Value

    +

    TRUE or FALSE or a logical named vector when x +is a CondaEnvManager object (one element per +method)

    +
    + + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/matrix-indexing.html b/reference/matrix-indexing.html new file mode 100644 index 0000000..1a45396 --- /dev/null +++ b/reference/matrix-indexing.html @@ -0,0 +1,110 @@ + +Matrix indexing — matrix-indexing • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Switch between rows & columns indices and vector-like indices of matrices.

    rowcol2idx get indices out of rows and columns
    idx2col get columns out of indices
    idx2row get rows out of indices

    +
    + +
    +

    Usage

    +
    rowcol2idx(rows.idx, cols.idx, height)
    +
    +idx2col(idx, height)
    +
    +idx2row(idx, height)
    +
    + +
    +

    Arguments

    + + +
    rows.idx
    +

    indices of rows

    + + +
    cols.idx
    +

    indices of columns

    + + +
    height
    +

    height of the matrix (number of rows)

    + + +
    idx
    +

    vector-like, matrix-wide indices

    + +
    +
    +

    Value

    +

    a vector of indices

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/matrix-sorting.html b/reference/matrix-sorting.html new file mode 100644 index 0000000..c8c0415 --- /dev/null +++ b/reference/matrix-sorting.html @@ -0,0 +1,121 @@ + +Matrix sorting — matrix-sorting • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Sort a matrix in a row- or column-wise manner, or check that it is

    rowSort sort each row independently
    colSort sort each column independently

    rowSorted check that each row is independently sorted
    colSorted check that each column is independently sorted

    +
    + +
    +

    Usage

    +
    rowSort(mat, by = NULL, ncol = NULL, decreasing = FALSE)
    +
    +colSort(mat, by = NULL, ncol = NULL, decreasing = FALSE)
    +
    +rowSorted(mat, decreasing = FALSE)
    +
    +colSorted(mat, decreasing = FALSE)
    +
    + +
    +

    Arguments

    + + +
    mat
    +

    matrix to sort or to check

    + + +
    by
    +

    matrix to sort by. If NULL, sort mat by itself (default)

    + + +
    ncol
    +

    number of desired columns for the sorted mat. If +NULL, keep original dimensions of mat (default)

    + + +
    decreasing
    +

    logical. Should the sort be increasing or decreasing? + Not available for partial sorting.

    + +
    +
    +

    Value

    +

    a sorted matrix of ncol columns

    +
    +
    +

    Note

    +

    If mat and by have different dimensions, results might be +incorrect

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/matrix-symmetrize.html b/reference/matrix-symmetrize.html new file mode 100644 index 0000000..b190d72 --- /dev/null +++ b/reference/matrix-symmetrize.html @@ -0,0 +1,113 @@ + +Matrix symmetrizing — matrix-symmetrize • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Create a sparse matrix using i, j and x (row indices, column indicies and +values respectively) then symmetrizes it with low memory footprint

    symmetrize.pmax.sparse symmetrize matrix with max(m[i,j], m[j,i])
    symmetrize.pmin.sparse symmetrize matrix with min(m[i,j], m[j,i])

    +
    + +
    +

    Usage

    +
    symmetrize.pmax.sparse(i, j, x, height)
    +
    +symmetrize.pmin.sparse(i, j, x, height)
    +
    + +
    +

    Arguments

    + + +
    i
    +

    row indices (1-based)

    + + +
    j
    +

    column indices (1-based)

    + + +
    x
    +

    values such that m[i,j] = x

    + + +
    height
    +

    height of the matrix (number of rows)

    + +
    +
    +

    Value

    +

    a symmetric sparse dgCMatrix of size height x height

    +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/numeric_lisi-methods.html b/reference/numeric_lisi-methods.html new file mode 100644 index 0000000..656da58 --- /dev/null +++ b/reference/numeric_lisi-methods.html @@ -0,0 +1,113 @@ + +Convert a numeric vector to a `numeric_lisi` vector — as.numeric,numeric_lisi-method • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Convert a numeric vector to a `numeric_lisi` vector

    +

    Indexing method for `numeric_lisi` (keep `@N` slot)

    +

    Replicate method for numeric_lisi (keep `@N` slot)

    +

    Value replacement method for `numeric_lisi` (check `@N` slot compatibility)

    +
    + +
    +

    Usage

    +
    # S4 method for class 'numeric_lisi'
    +as.numeric(x)
    +
    +# S4 method for class 'numeric_lisi,ANY,ANY,ANY'
    +x[i]
    +
    +# S4 method for class 'numeric_lisi'
    +rep(x, ...)
    +
    +# S4 method for class 'numeric_lisi,ANY,ANY,ANY'
    +x[i] <- value
    +
    + +
    +

    Arguments

    + + +
    x
    +

    a numeric_lisi vector

    + + +
    i
    +

    indices specifying elements to extract or replace

    + + +
    ...
    +

    passed to rep.numeric

    + + +
    value
    +

    value to replace with

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/reloadCache.html b/reference/reloadCache.html new file mode 100644 index 0000000..4becb97 --- /dev/null +++ b/reference/reloadCache.html @@ -0,0 +1,81 @@ + +Reload cache from disk — reloadCache • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Reload cache from disk to update current list of conda environments in +package environment

    +
    + +
    +

    Usage

    +
    reloadCache()
    +
    + +
    +

    Value

    +

    a CondaEnvManager object (invisibly)

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/rep,numeric_lisi-method.html b/reference/rep,numeric_lisi-method.html new file mode 100644 index 0000000..154c755 --- /dev/null +++ b/reference/rep,numeric_lisi-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/resetCache.html b/reference/resetCache.html new file mode 100644 index 0000000..dd5be0b --- /dev/null +++ b/reference/resetCache.html @@ -0,0 +1,90 @@ + +Reset a conda environment — resetCache • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Reset (unset) a conda environment linked to a provided method. Update cache +on disk and in package environment

    +
    + +
    +

    Usage

    +
    resetCache(method = known.methods)
    +
    + +
    +

    Arguments

    + + +
    method
    +

    the name of the method to update. One of "combat", "harmony", +"mnn", "bbknn", "scvi", "scanvi", "scanorama", "trvae"

    + +
    +
    +

    Value

    +

    a CondaEnvManager object (invisibly)

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/rowSort.html b/reference/rowSort.html new file mode 100644 index 0000000..409aa67 --- /dev/null +++ b/reference/rowSort.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/rowSorted.html b/reference/rowSorted.html new file mode 100644 index 0000000..409aa67 --- /dev/null +++ b/reference/rowSorted.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/rowcol2idx.html b/reference/rowcol2idx.html new file mode 100644 index 0000000..db772f3 --- /dev/null +++ b/reference/rowcol2idx.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/saveToCache,CondaEnvManager-method.html b/reference/saveToCache,CondaEnvManager-method.html new file mode 100644 index 0000000..722edac --- /dev/null +++ b/reference/saveToCache,CondaEnvManager-method.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/saveToCache.html b/reference/saveToCache.html new file mode 100644 index 0000000..55be941 --- /dev/null +++ b/reference/saveToCache.html @@ -0,0 +1,103 @@ + +Save a conda environment manager to cache — saveToCache • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Save a conda environment manager to cache ( +R_user_dir("SeuratIntegrate", which = "config")) +as a data.frame in a compressed RDS file.

    +
    + +
    +

    Usage

    +
    saveToCache(x, ..., verbose = getOption("verbose"))
    +
    +# S4 method for class 'CondaEnvManager'
    +saveToCache(x)
    +
    + +
    +

    Arguments

    + + +
    x
    +

    a CondaEnvManager object

    + + +
    ...
    +

    ignored

    + + +
    verbose
    +

    ignored

    + +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/scANVIIntegration.html b/reference/scANVIIntegration.html new file mode 100644 index 0000000..0e96375 --- /dev/null +++ b/reference/scANVIIntegration.html @@ -0,0 +1,329 @@ + +Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run scANVI on multi-layered Seurat V5 object. +Requires a conda environment with scvi-tools and necessary dependencies

    +

    Recommendations: use raw counts and all features +(features = Features(object), layers = "counts")

    +
    + +
    +

    Usage

    +
    scANVIIntegration(
    +  object,
    +  groups = NULL,
    +  groups.name = NULL,
    +  labels.name = NULL,
    +  labels.null = NULL,
    +  features = NULL,
    +  layers = "counts",
    +  scale.layer = "scale.data",
    +  conda_env = NULL,
    +  new.reduction = "integrated.scANVI",
    +  reduction.key = "scANVIlatent_",
    +  torch.intraop.threads = 4L,
    +  torch.interop.threads = NULL,
    +  model.save.dir = NULL,
    +  ndims.out = 10,
    +  n_hidden = 128L,
    +  n_layers = 1L,
    +  dropout_rate = 0.1,
    +  dispersion = c("gene", "gene-batch", "gene-label", "gene-cell"),
    +  gene_likelihood = c("zinb", "nb", "poisson"),
    +  linear_classifier = FALSE,
    +  max_epochs = NULL,
    +  train_size = 0.9,
    +  batch_size = 128L,
    +  seed.use = 42L,
    +  verbose = TRUE,
    +  verbose.scvi = c("INFO", "NOTSET", "DEBUG", "WARNING", "ERROR", "CRITICAL"),
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    groups
    +

    A named data frame with grouping information. Can also +contain cell labels to guide scANVI.

    + + +
    groups.name
    +

    Column name from groups data frame that stores +grouping information. If groups.name = NULL, the first column is used

    + + +
    labels.name
    +

    Column name from groups data frame that stores +cell label information. If labels.name = NULL, all cells are assigned +the same label.

    + + +
    labels.null
    +

    One value of groups$labels.name that indicates unlabeled +observations. labels.null = NULL means all labels are valid. Only applies +when labels.name != NULL.

    + + +
    features
    +

    Vector of feature names to input to the integration method. +When features = NULL (default), the +VariableFeatures are used. To pass all features, +use the output of Features()

    + + +
    layers
    +

    Name of the layers to use in the integration. +'counts' is highly recommended

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    conda_env
    +

    Path to conda environment to run scANVI (should also +contain the scipy python module). By default, uses the conda environment +registered for scANVI in the conda environment manager

    + + +
    new.reduction
    +

    Name of the new integrated dimensional reduction

    + + +
    reduction.key
    +

    Key for the new integrated dimensional reduction

    + + +
    torch.intraop.threads
    +

    Number of intra-op threads available to torch +when training on CPU instead of GPU. Set via torch.set_num_threads().

    + + +
    torch.interop.threads
    +

    Number of intra-op threads available to torch +when training on CPU instead of GPU. Set via torch.set_num_interop_threads(). +Can only be changed once, on first call.

    + + +
    model.save.dir
    +

    Path to a directory to save the model to. Uses +SCANVI.save(). Does not save anndata. Note that neither the trainer +optimizer state nor the trainer history are saved. +model.save.dir = NULL (default) disables saving the model.

    + + +
    ndims.out
    +

    Number of dimensions for new.reduction output. +Corresponds to n_latent argument in the original API of SCANVI

    + + +
    n_hidden
    +

    Number of nodes per hidden layer.

    + + +
    n_layers
    +

    Number of hidden layers used for encoder and decoder NNs.

    + + +
    dropout_rate
    +

    Dropout rate for neural networks.

    + + +
    dispersion
    +

    One of the following:

    • gene: dispersion parameter of NB is constant per gene across cells (default)

    • +
    • gene-batch: dispersion can differ between different batches

    • +
    • gene-label: dispersion can differ between different labels

    • +
    • gene-cell: dispersion can differ for every gene in every cell

    • +
    + + +
    gene_likelihood
    +

    One of the following:

    • zinb: Zero-inflated negative binomial distribution (default)

    • +
    • nb: Negative binomial distribution

    • +
    • poisson: Poisson distribution

    • +
    + + +
    linear_classifier
    +

    When switched to TRUE, uses a single linear layer for +classification instead of a multi-layer perceptron.

    + + +
    max_epochs
    +

    Number of passes through the dataset for semisupervised training.

    + + +
    train_size
    +

    Size of training set in the range [0.0, 1.0]

    + + +
    batch_size
    +

    Minibatch size to use during training.

    + + +
    seed.use
    +

    An integer to generate reproducible outputs. +Set seed.use = NULL to disable

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    verbose.scvi
    +

    Verbosity level of scANVI. From quietest to talkiest: +CRITICAL, ERROR, WARNING, INFO (default), DEBUG, NOTSET

    + + +
    ...
    +

    Additional arguments to be passed to scvi.model.SCANVI, +SCANVI.setup_anndata or SCANVI.train (see Details section)

    + +
    +
    +

    Value

    +

    A list containing:

    • a new DimReduc of name new.reduction (key set to + reduction.key) consisting of the latent space of the model with + ndims.out dimensions.

    • +

    When called via IntegrateLayers, a Seurat object with +the new reduction and/or assay is returned

    +
    +
    +

    Details

    +

    This wrappers calls three python functions through reticulate. +Find the scVANVI-specific arguments there:

    +
    +

    Note

    +

    This function requires the +scvi-tools package +to be installed (along with scipy)

    +
    +
    +

    References

    +

    Kingma, D. P., Rezende, D. J., Mohamed, S. & Welling, M. Semi- +Supervised Learning with Deep Generative Models. Preprint at arXiv (2014). +DOI

    +

    Xu, C., Lopez, R., Mehlman, E., Regier, J., Jordan, M. I. & Yosef, N. +Probabilistic harmonization and annotation of single‐cell transcriptomics data +with deep generative models. Molecular Systems Biology 17, (2021). +DOI

    +
    + + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers:
    +obj <- IntegrateLayers(object = obj, method = scANVIIntegration,
    +                       features = Features(obj), conda_env = 'scvi-tools',
    +                       layers = 'counts', groups = obj[[]], groups.name = 'Method',
    +                       labels.name = 'CellType', labels.null = 'Unassigned')
    +
    +# To enable saving the model, add other 'nuisance' factors and increase number of threads used:
    +obj <- IntegrateLayers(object = obj, method = scANVIIntegration,
    +                       features = Features(obj), conda_env = 'scvi-tools',
    +                       layers = 'counts', groups = obj[[]], groups.name = "Method",
    +                       labels.name = "CellType", labels.null = "Unassigned",
    +                       categorical_covariate_keys = "Experiment",
    +                       continuous_covariate_keys = "percent.mito",
    +                       ncores = 8, model.save.dir = '~/Documents/scANVI.model')
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/scVIIntegration.fix.html b/reference/scVIIntegration.fix.html new file mode 100644 index 0000000..5885159 --- /dev/null +++ b/reference/scVIIntegration.fix.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/scVIIntegration.html b/reference/scVIIntegration.html new file mode 100644 index 0000000..92a6d72 --- /dev/null +++ b/reference/scVIIntegration.html @@ -0,0 +1,326 @@ + +Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run scVI on multi-layered Seurat V5 object. +Requires a conda environment with scvi-tools and necessary dependencies

    +

    Can be called via SeuratIntegrate::scVIIntegration() or +scVIIntegration.fix()

    +

    Recommendations: use raw counts and all features +(features = Features(object), layers = "counts")

    +
    + +
    +

    Usage

    +
    scVIIntegration(
    +  object,
    +  groups = NULL,
    +  groups.name = NULL,
    +  labels.name = NULL,
    +  features = NULL,
    +  layers = "counts",
    +  scale.layer = "scale.data",
    +  conda_env = NULL,
    +  new.reduction = "integrated.scVI",
    +  reduction.key = "scVIlatent_",
    +  torch.intraop.threads = 4L,
    +  torch.interop.threads = NULL,
    +  model.save.dir = NULL,
    +  ndims.out = 10,
    +  n_hidden = 128L,
    +  n_layers = 1L,
    +  dropout_rate = 0.1,
    +  dispersion = c("gene", "gene-batch", "gene-label", "gene-cell"),
    +  gene_likelihood = c("zinb", "nb", "poisson"),
    +  latent_distribution = c("normal", "ln"),
    +  max_epochs = NULL,
    +  train_size = 0.9,
    +  batch_size = 128L,
    +  seed.use = 42L,
    +  verbose = TRUE,
    +  verbose.scvi = c("INFO", "NOTSET", "DEBUG", "WARNING", "ERROR", "CRITICAL"),
    +  ...
    +)
    +
    +scVIIntegration.fix(...)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    groups
    +

    A named data frame with grouping information.

    + + +
    groups.name
    +

    Column name from groups data frame that stores +grouping information. If groups.name = NULL, the first column is used

    + + +
    labels.name
    +

    Column name from groups data frame that stores +cell label information. If labels.name = NULL, all cells are assigned +the same label.

    + + +
    features
    +

    Vector of feature names to input to the integration method. +When features = NULL (default), the +VariableFeatures are used. To pass all features, +use the output of Features()

    + + +
    layers
    +

    Name of the layers to use in the integration. +'counts' is highly recommended

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    conda_env
    +

    Path to conda environment to run scVI (should also +contain the scipy python module). By default, uses the conda environment +registered for scVI in the conda environment manager

    + + +
    new.reduction
    +

    Name of the new integrated dimensional reduction

    + + +
    reduction.key
    +

    Key for the new integrated dimensional reduction

    + + +
    torch.intraop.threads
    +

    Number of intra-op threads available to torch +when training on CPU instead of GPU. Set via torch.set_num_threads().

    + + +
    torch.interop.threads
    +

    Number of intra-op threads available to torch +when training on CPU instead of GPU. Set via torch.set_num_interop_threads(). +Can only be changed once, on first call.

    + + +
    model.save.dir
    +

    Path to a directory to save the model to. Uses +SCVI.save(). Does not save anndata. Note that neither the trainer +optimizer state nor the trainer history are saved. +model.save.dir = NULL (default) disables saving the model.

    + + +
    ndims.out
    +

    Number of dimensions for new.reduction output. +Corresponds to n_latent argument in the original API of SCVI

    + + +
    n_hidden
    +

    Number of nodes per hidden layer.

    + + +
    n_layers
    +

    Number of hidden layers used for encoder and decoder NNs.

    + + +
    dropout_rate
    +

    Dropout rate for neural networks.

    + + +
    dispersion
    +

    One of the following:

    • gene: dispersion parameter of NB is constant per gene across cells (default)

    • +
    • gene-batch: dispersion can differ between different batches

    • +
    • gene-label: dispersion can differ between different labels

    • +
    • gene-cell: dispersion can differ for every gene in every cell

    • +
    + + +
    gene_likelihood
    +

    One of the following:

    • zinb: Zero-inflated negative binomial distribution (default)

    • +
    • nb: Negative binomial distribution

    • +
    • poisson: Poisson distribution

    • +
    + + +
    latent_distribution
    +

    One of the following:

    • normal: Normal distribution (default)

    • +
    • ln: Logistic normal distribution (Normal(0, I) transformed by softmax)

    • +
    + + +
    max_epochs
    +

    Number of passes through the dataset for semisupervised training.

    + + +
    train_size
    +

    Size of training set in the range [0.0, 1.0]

    + + +
    batch_size
    +

    Minibatch size to use during training.

    + + +
    seed.use
    +

    An integer to generate reproducible outputs. +Set seed.use = NULL to disable

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    verbose.scvi
    +

    Verbosity level of scVI. From quietest to talkiest: +CRITICAL, ERROR, WARNING, INFO (default), DEBUG, NOTSET

    + + +
    ...
    +

    For scVIIntegration(), additional arguments to be passed to +scvi.model.SCVI, SCVI.setup_anndata or SCVI.train (see +Details section). For scVIIntegration.fix(), all of the above

    + +
    +
    +

    Value

    +

    A list containing:

    • a new DimReduc of name new.reduction (key set to + reduction.key) consisting of the latent space of the model with + ndims.out dimensions.

    • +

    When called via IntegrateLayers, a Seurat object with +the new reduction and/or assay is returned

    +
    +
    +

    Details

    +

    This wrappers calls three python functions through reticulate. +Find the scVI-specific arguments there:

    +
    +

    Note

    +

    This function requires the +scvi-tools package +to be installed (along with scipy)

    +
    +
    +

    References

    +

    Lopez, R., Regier, J., Cole, M. B., Jordan, M. I. & Yosef, N. +Deep generative modeling for single-cell transcriptomics. Nat Methods 15, +1053–1058 (2018). DOI

    +
    + + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers:
    +obj <- IntegrateLayers(object = obj, method = scVIIntegration,
    +                       features = Features(obj), conda_env = 'scvi-tools',
    +                       layers = 'counts', groups = obj[[]], groups.name = 'Method')
    +
    +# To enable cell label-guided correction, save the model, add other
    +# 'nuisance' factors and increase number of threads used:
    +obj <- IntegrateLayers(object = obj, method = scVIIntegration,
    +                       features = Features(obj), conda_env = 'scvi-tools',
    +                       layers = 'counts', groups = obj[[]], groups.name = "Method",
    +                       labels.name = "CellType",
    +                       categorical_covariate_keys = list("Experiment"),
    +                       continuous_covariate_keys = list("percent.mito"),
    +                       ncores = 8, model.save.dir = '~/Documents/scVI.model')
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-ari.html b/reference/score-ari.html new file mode 100644 index 0000000..0eafcb8 --- /dev/null +++ b/reference/score-ari.html @@ -0,0 +1,140 @@ + +Score a clustering result with adjusted rand index — ScoreARI • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute a score based on adjusted rand index between a clustering +result and one or more cell type label variable(s). 0 and 1 reflect a random +clustering and a perfect clustering as compared to cell type labelling +respectively.

    +
    + +
    +

    Usage

    +
    ScoreARI(object, cell.var, clust.var = "seurat_clusters")
    +
    +AddScoreARI(object, integration, cell.var, clust.var = "seurat_clusters")
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    cell.var
    +

    The name(s) of the column(s) with cell type label variable +(must be in the object metadata). Multiple column names are accepted

    + + +
    clust.var
    +

    The name of the column with cluster id assignment for each +cell (must be in the object metadata). Only one column name is accepted

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreARI: a named array with as many values as there are +common strings between cell.var and the column names of the object's +metadata. Names are cell.var and values are ARI.

    +

    AddScoreARI: the updated Seurat object with the ARI score(s) +set for the integration.

    +
    +
    +

    Details

    +

    ARI is rand index corrected for chance: +$$\displaystyle ARI = \frac{RI - RI_{expected}}{max(RI) - RI_{expected}}$$ +More precisely, a contingency table is computed with the two variables +\(L\) and \(C\) of \(r\) and \(s\) elements respectively. For +\(i \in [\![1,r]\!]\) and \(j \in [\![1,s]\!]\), \(n_{ij}\) is the +number of common samples (i.e. cells) between \(L_i\) and \(C_j\), +\(a_i\) is the number of samples in \(L_i\) and \(b_j\) is the number +of samples in \(C_j\). The ARI is: +$$\displaystyle ARI = \frac{\left. \sum_{ij} \binom{n_{ij}}{2} - \left(\sum_i \binom{a_i}{2} \sum_j \binom{b_j}{2}\right) \right/ \binom{n}{2} }{ \left. \frac{1}{2} \left(\sum_i \binom{a_i}{2} + \sum_j \binom{b_j}{2}\right) - \left(\sum_i \binom{a_i}{2} \sum_j \binom{b_j}{2}\right) \right/ \binom{n}{2}}$$

    +
    +
    +

    Note

    +

    The metric is symmetric. Switching cell.var with clust.var will return +the same value.

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-asw.html b/reference/score-asw.html new file mode 100644 index 0000000..6c88b1c --- /dev/null +++ b/reference/score-asw.html @@ -0,0 +1,267 @@ + +Score an embedding or a count matrix with the average silhouette width — score-asw • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute scores based on the average silhouette width (ASW) metric.

    +

    ScoreASW: First, cell-to-cell distances are computed on the provided +embedding or layer matrix. Then, the silhouette score is calculated to +estimate the quality of the partition according to the variable with cell +type labels. Hence, this score measures to what extent cells with identical +label cluster together.

    +

    ScoreASWBatch: Similar, but with the batch variable. This score +provides an estimation of batch mixing.

    +
    + +
    +

    Usage

    +
    ScoreASW(
    +  object,
    +  cell.var,
    +  what,
    +  assay = NULL,
    +  metric = c("euclidean", "cosine", "angular", "manhattan", "hamming"),
    +  dist.package = c("distances", "Rfast", "parallelDist", "stats"),
    +  verbose = TRUE,
    +  ...
    +)
    +
    +AddScoreASW(
    +  object,
    +  integration,
    +  cell.var,
    +  what,
    +  assay = NULL,
    +  metric = c("euclidean", "cosine", "angular", "manhattan", "hamming"),
    +  dist.package = c("distances", "Rfast", "parallelDist", "stats"),
    +  verbose = TRUE,
    +  ...
    +)
    +
    +ScoreASWBatch(
    +  object,
    +  batch.var = NULL,
    +  cell.var = NULL,
    +  what,
    +  per.cell.var = TRUE,
    +  assay = NULL,
    +  metric = c("euclidean", "cosine", "angular", "manhattan", "hamming"),
    +  dist.package = c("distances", "Rfast", "parallelDist", "stats"),
    +  verbose = TRUE,
    +  ...
    +)
    +
    +AddScoreASWBatch(
    +  object,
    +  integration,
    +  batch.var = NULL,
    +  cell.var = NULL,
    +  what,
    +  per.cell.var = TRUE,
    +  assay = NULL,
    +  metric = c("euclidean", "cosine", "angular", "manhattan", "hamming"),
    +  dist.package = c("distances", "Rfast", "parallelDist", "stats"),
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    cell.var
    +

    The name of the column with cell type label variable +(must be in the object metadata). +Ignored by ScoreASWBatch when per.cell.var = FALSE

    + + +
    what
    +

    the name of the dimension reduction or layer to score. Must be +in the Seurat object or obtainable after a +JoinLayers() call.

    + + +
    assay
    +

    name of the assay to use. The output of +DefaultAssay() is used by default

    + + +
    metric
    +

    name of the distance metric to use. One of 'euclidean', +'cosine', 'angular', 'manhattan', 'hamming'. See Note for details.

    + + +
    dist.package
    +

    name of the package to compute distances with. One of +'distances', 'Rfast' ,'parallelDist', 'stats'. The latter is always available, +the others must be installed beforehand. They are ordered from fastest to +slowest. When the requested package is not installed, the fastest amongst the +available ones is picked. See Note for details.

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    ...
    +

    additional parameters to pass to the distance computation +functions

    + + +
    integration
    +

    name of the integration to score

    + + +
    batch.var
    +

    The name of the column with batch variable. +(must be in the object metadata). Required by ScoreASWBatch.

    + + +
    per.cell.var
    +

    whether to compute silhouette coefficients with the batch +variable for each cell-type separately (default behaviour). Setting to +FALSE causes the silhouette coefficients to be computed on the whole +data directly.

    + +
    +
    +

    Value

    +

    ScoreASW and ScoreASWBatch: a single float between 0 +and 1, corresponding to the scaled average silhouette score.

    +

    AddScoreASW and AddScoreASWBatch: the updated Seurat +object with the ASW score(s) set for the integration.

    +
    +
    +

    Details

    +

    ScoreASW: Given a matrix (reduction dimension or layer), the +cell-to-cell distance matrix \(D\) is computed. Then, the silhouette width +\(s(i)\) is calculated for each cell \(i\) with a label \(c \in L\) +(\(L\) is the set of possible cell type labels). Then, the mean of all +\(s(i)\) is computed (i.e. the ASW) and scaled between 0 and 1: +$$\displaystyle ASW = \frac{1}{\left| L \right|} \times \sum_{i}{s(i)} \\[10pt] +score = \frac{ASW + 1}{2}$$

    +

    ScoreAWSBatch: The default parameters (per.cell.var = TRUE) +correspond to the original score from Luecken M.D. et al., 2022. It is +computed as follow: for each cell type label \(c\) among the set of all +labels \(L\), the cell-to-cell matrix distance \(D_c\) is computed for +cells \(i\) with label \(c\). Each cell's silhouette width \(s(i)\) is +calculated according to the batch variable and transformed to be as close to +1 as its absolute value is close to 0. An average silhouette width +\(ASW_c\) is then computed per cell type label \(c \in L\) and the mean +of those correspond to the final score: +$$\displaystyle ASW_c = \frac{1}{\left| c \right|} \times \sum_{i \in c}{1 - \left| s(i) \right|} \\[10pt] +score = \frac{1}{\left| L \right|} \times \sum_{c \in L}{ASW_c}$$

    +

    When per.cell.var = FALSE, \(ASW\) is computed for all cells at once +(just like for ScoreASW but on the batch variable), then scaled +and averaged similarly: +$$\displaystyle score = ASW = \frac{1}{N} \times \sum_{i=1}^{N}{1 - \left| s(i) \right|}$$ +with \(N\) being the total number of cells

    +
    +
    +

    Note

    +

    Those scores are an adaptation of the (cell-type) ASW and the batch ASW +as described in Luecken M.D. et al., 2022.

    +

    Hamming distance is only supported by the parallelDist package, while +distances can only compute euclidean and related distances (cosine and +angular). Angular distances are actually refereed to as 'cosine' in +FindNeighbors() (annoy.metric), +hence called 'angular' here. Actual cosine dissimilarity-derived distances +are returned when metric = 'cosine'. Internally, angular distances are +computed with euclidean distances on \(L^2\) norm. cosine distances are +further transformed with : +$$\displaystyle D_{cosine} = \frac{D_{angular}^2}{2}$$

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    +

    FindNeighbors, silhouette +to know more about the silhouette metric, GetNeighborsPerBatch +and GetPropInterBatch

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-cc.html b/reference/score-cc.html new file mode 100644 index 0000000..4eb8c05 --- /dev/null +++ b/reference/score-cc.html @@ -0,0 +1,242 @@ + +Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Linearly regresses S and G2M scores to predict principal components. The +resulting R2 are then weighted by each dimension's contribution to variance. +Cell cycles scores and PCAs are computed for each batch independently.

    +
    + +
    +

    Usage

    +
    ScoreRegressPC.CellCycle(
    +  object,
    +  batch.var = NULL,
    +  what = NULL,
    +  dims.use = NULL,
    +  npcs = 50L,
    +  s.var = "S.Score",
    +  g2m.var = "G2M.Score",
    +  compute.cc = TRUE,
    +  s.features = NULL,
    +  g2m.features = NULL,
    +  assay = NULL,
    +  weight.by = c("var", "stdev"),
    +  adj.r2 = FALSE,
    +  approx = FALSE
    +)
    +
    +AddScoreRegressPC.CellCycle(
    +  object,
    +  integration,
    +  batch.var = NULL,
    +  what = NULL,
    +  dims.use = NULL,
    +  npcs = 50L,
    +  s.var = "S.Score",
    +  g2m.var = "G2M.Score",
    +  compute.cc = TRUE,
    +  s.features = NULL,
    +  g2m.features = NULL,
    +  assay = NULL,
    +  weight.by = c("var", "stdev"),
    +  adj.r2 = FALSE,
    +  approx = FALSE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    batch.var
    +

    The name of the batch variable (must be in the object metadata)

    + + +
    what
    +

    the slot from Seurat to score. Can be a layer or a reduction.

    + + +
    dims.use
    +

    The dimensions from what to consider. All dimensions +are used by default

    + + +
    npcs
    +

    Total Number of PCs to compute and store (50 by default)

    + + +
    s.var
    +

    The name of the S phase score variable (must be in the object +metadata)

    + + +
    g2m.var
    +

    The name of the G2M phase score variable (must be in the +object metadata)

    + + +
    compute.cc
    +

    whether to (re-)compute the cell cycle scores. Should be +TRUE (default), unless you have run +CellCycleScoringPerBatch beforehand because cell cycles scores +are expected to be computed per batch

    + + +
    s.features
    +

    A vector of features associated with S phase

    + + +
    g2m.features
    +

    A vector of features associated with G2M phase

    + + +
    assay
    +

    assay to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    weight.by
    +

    one of 'var' (default) or 'stdev' (standing for variance and +standard deviation respectively). Use the variance or the standard deviation +explained by the principal components to weight the each PC's score.

    + + +
    adj.r2
    +

    Whether to use the adjusted R2 instead of the raw R2

    + + +
    approx
    +

    Use truncated singular value decomposition to approximate PCA

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreRegressPC.CellCycle: A 2-columns data frame with the +batch variable in the first one and the corresponding score in the second +one. It has as many rows as batches.

    +

    AddScoreRegressPC.CellCycle: the updated Seurat object with the +cell cycle conservation score set for the integration.

    +
    +
    +

    Details

    +

    The linear regression is +$$PC_i = S_{score} + G2M_{score}$$

    +

    The score is computed as follow : +$$\sum_{i=1}^{p} \left ( R^2_i * V_i \right )$$

    +

    For a PCA with p dimensions, \(PC_i\) is the principal component i, +\(R^2_i\) is the R squared coefficient of the linear regression for the +dimension i. \(V_i\) is the proportion of variance explained by the +\(PC_i\).

    +
    +
    +

    Note

    +

    This score is an adaptation of the principal component regression (PCR) +score from Luecken M.D. et al., 2022.

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    +

    CellCycleScoringPerBatch to compute cc scores per +batch. ScoreRegressPC to regresses PCs by batch.

    +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +score.cc.r2 <- ScoreRegressPC.CellCycle(obj, "Method", "pca", dim.use = 1:30)
    +score.cc.adj.r2 <- ScoreRegressPC.CellCycle(obj, "Method", "pca", dim.use = 1:30, adj.r2 = TRUE)
    +
    +score.cc.r2        # ~ 0.0249
    +score.cc.adj.r2    # ~ 0.0249
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-connectivity.html b/reference/score-connectivity.html new file mode 100644 index 0000000..52b3057 --- /dev/null +++ b/reference/score-connectivity.html @@ -0,0 +1,196 @@ + +Score a knn graph based on cell-type label connectivity — ScoreConnectivity • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute scores based on the connectivity between cells sharing the same label. +The score can be calculated in two fashions, either by quantifying the +connectivity of the largest subgraph for each cell label (identical to the +score used in Luecken M.D. et al., 2022), or directly on the whole +graph.

    +
    + +
    +

    Usage

    +
    ScoreConnectivity(
    +  object,
    +  graph.name,
    +  cell.var,
    +  do.symmetrize = TRUE,
    +  per.component = TRUE,
    +  count.self = FALSE,
    +  weight.by.ncells = FALSE
    +)
    +
    +AddScoreConnectivity(
    +  object,
    +  integration,
    +  graph.name,
    +  cell.var,
    +  do.symmetrize = TRUE,
    +  per.component = TRUE,
    +  count.self = FALSE,
    +  weight.by.ncells = FALSE
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    graph.name
    +

    The name of the knn graph to score.

    + + +
    cell.var
    +

    The name of the cell variable (must be in the object metadata).

    + + +
    do.symmetrize
    +

    whether to symmetrize the knn graph. Set toFALSE +to disable (not recommended, see Details)

    + + +
    per.component
    +

    whether to use the same score as in Luecken M.D. +et al., 2022. TRUE by default. See Details.

    + + +
    count.self
    +

    whether to account for loops (i.e. cells connected to +themselves). FALSE by default

    + + +
    weight.by.ncells
    +

    whether to weight the connectivity-derived scores +computed on each cell type label by their relative proportion in number of +cells. By default (FALSE), the overall score is computed as the mean +of scores computed per label. Ignored when per.component = TRUE

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreConnectivity: a single float between 0 and 1, +corresponding to the connectivity score.

    +

    AddScoreConnectivity: the updated Seurat object with the Graph +connectivity score set for the integration.

    +
    +
    +

    Details

    +

    The default parameters (per.component = TRUE, count.self = FALSE) +correspond to the original score from Luecken M.D. et al., 2022. It is +computed as follow: for each cell type label \(c\) among the set of all +labels \(L\), the sub graph \(subG_c\) exclusively composed of cells +\(c\) is extracted from the full graph \(G\). Then, the size (i.e. the +number of cells, hence of vertices \(V\)) of the largest connected +component is divided by the size of \(subG_c\). Then, the mean of sub +graphs' scores is computed: +$$ratio_c = \frac{max(\left|V(CC(subG_c))\right|)}{\left|V(subG_c)\right|}$$ +$$score = \frac{1}{\left| L \right|}\sum_{c \in L} ratio_c$$

    + +

    When per.component = FALSE, the connectivity is computed on the full +graph \(G\). Let's consider the set of all labels \(L\), +\(c \in L\) and \(L\prime = L \setminus \{c\}\). Let's also denote the +edges between cells \(\in \{c\}\) \(E_c = E_{c \to c}(G)\) +and the edges connecting cells \(\in \{c\}\) with cells \(\in L\prime\) +\(E_c^{\prime} = E_{c \to L\prime}(G)\). +When weight.by.ncells = TRUE, the score is computed as follow: +$$score = \sum_{c \in L} \left( \frac{\left| V(subG_c) \right|}{\left| V(G) \right|} \times \frac{\left| E_c \right|}{\left| E_c^\prime \right| + \left| E_c \right|}\right)$$

    +

    When weight.by.ncells = FALSE, the score is the mean of ratio of edges: +$$score = \frac{1}{\left| L \right|}\sum_{c \in L} \frac{\left| E_c \right|}{\left| E_c^\prime \right| + \left| E_c \right|}$$

    +

    In either case, it is recommended to keep do.symmetrize = TRUE.

    +
    +
    +

    Note

    +

    This score is an adaptation of the graph connectivity score as +described in Luecken M.D. et al., 2022.

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-densityPC.html b/reference/score-densityPC.html new file mode 100644 index 0000000..5f08737 --- /dev/null +++ b/reference/score-densityPC.html @@ -0,0 +1,224 @@ + +Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A batch-wise kernel density estimate is computed for each dimension of the PCA. +Then, the global area shared by all kernels is calculated and divided by a +reference area (see Arguments and Details) as a proxy to +batch mixing. Finally, the aforementioned proportions are weighted by each +dimension's contribution to variance.

    +
    + +
    +

    Usage

    +
    ScoreDensityPC(
    +  object,
    +  batch.var = NULL,
    +  reduction = "pca",
    +  dims = NULL,
    +  use.union = TRUE,
    +  bw.join = mean,
    +  bw.kernel = c("nrd0", "nrd", "ucv", "bcv", "sj"),
    +  weight.by = c("var", "stdev"),
    +  assay = NULL,
    +  layer = NULL
    +)
    +
    +AddScoreDensityPC(
    +  object,
    +  integration,
    +  batch.var = NULL,
    +  reduction = "pca",
    +  dims = NULL,
    +  use.union = TRUE,
    +  bw.join = mean,
    +  bw.kernel = c("nrd0", "nrd", "ucv", "bcv", "sj"),
    +  weight.by = c("var", "stdev"),
    +  assay = NULL,
    +  layer = NULL
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    batch.var
    +

    The name of the batch variable (must be in the object metadata)

    + + +
    reduction
    +

    The name of the reduction to score

    + + +
    dims
    +

    The dimensions to consider. All dimensions are used by default

    + + +
    use.union
    +

    Whether to use a union of densities (constructs a fake +density with pmax). The alternative is to use all density kernels and sum them

    + + +
    bw.join
    +

    A function to pick a joint bandwidth. The default is to use the +mean(). You can also chose median for instance. If you want to +use a distinct bandwidth for each batch, just set bw.join = c (not recommended)

    + + +
    bw.kernel
    +

    Bandwidth selector to use for Gaussian kernel density estimation. +One of 'nrd0', 'nrd', 'ucv','bcv' or 'sj' (see bandwidths). +nrd0 is the default

    + + +
    weight.by
    +

    one of 'var' (default) or 'stdev' (standing for variance and +standard deviation respectively). Use the variance or the standard deviation +explained by the principal components to weight the each PC's score.

    + + +
    assay
    +

    assay to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    layer
    +

    layer to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreDensityPC: A single float corresponding to the score of +the given reduction

    +

    AddScoreDensityPC: the updated Seurat object with the density +PCA score set for the integration.

    +
    +
    +

    Details

    +

    The score is computed as follow : +$$\sum_{i=1}^{p} \left ( \cfrac{ \bigcup_{b=1}^n D_{bi} }{ Ref_i } * V_i \right )$$

    +

    For a PCA with p dimensions and n batchs. \(D_{bi}\) is the vector of density +of batch b on the dimension i. \(V_i\) is the proportion of variance +explained by the \(PC_i\).

    +

    with \(Ref = \bigcap_{i=1}^n D_{bi}\) or \(Ref = \sum_{i=1}^n D_{bi}\) +when use.union is TRUE and FALSE respectively, for a +given dimension \(i\).

    +

    use.union = FALSE tends to result in lower score since the +reference is the sum of kernel densities instead of maximum

    +
    +
    +

    Note

    +

    This score is an adaptation of the principal component regression (PCR) +score from Luecken M.D. et al., 2022.

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    +

    ScoreRegressPC to compute the PCR score

    +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +score.union <- ScoreDensityPC(obj, "Method", "pca", dim = 1:30)
    +score.sum <- ScoreDensityPC(obj, "Method", "pca", dim = 1:30, use.union = FALSE)
    +
    +score.union   # ~ 0.1511
    +score.sum     # ~ 0.0319
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-kbet.html b/reference/score-kbet.html new file mode 100644 index 0000000..57b9bc3 --- /dev/null +++ b/reference/score-kbet.html @@ -0,0 +1,210 @@ + +Score an embedding or a knn graph with the kBET test — ScoreKBET • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute scores based on the k-nearest neighbour batch effect test (kBET). +Accepts a DimReduc instance or a +graph object (Graph or +Neighbor) provided that it +contains distances or connectivities.

    +

    If 'what' is a DimReduc +object, a knn graph is computed for k = 50. Then, (or if 'what' +is a Graph or a +Neighbor object), connectivities +are derives from 50 nearest neighbours distances. Finally, the kBET test is +computed for each cell-type label of all provided cell.var. kBET +measures if local batch label distribution is similar to the global one. The +result of kBET is the average test rejection rate (between 0 and 1). The +closest to zero, the less bias is attributable to the batch effect.

    +
    + +
    +

    Usage

    +
    ScoreKBET(
    +  object,
    +  batch.var,
    +  cell.var,
    +  what,
    +  graph.type = c("distances", "connectivities"),
    +  seed.use = 42L,
    +  verbose = TRUE,
    +  assay = NULL,
    +  layer = NULL
    +)
    +
    +AddScoreKBET(
    +  object,
    +  integration,
    +  batch.var,
    +  cell.var,
    +  what,
    +  graph.type = c("distances", "connectivities"),
    +  seed.use = 42L,
    +  verbose = TRUE,
    +  assay = NULL,
    +  layer = NULL
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    batch.var
    +

    The name of the batch variable (must be in the object +metadata)

    + + +
    cell.var
    +

    The name of the column with cell type label variable +(must be in the object metadata). If NULL is passed, the kBET score is +computed for all cells at once.

    + + +
    what
    +

    the name of the dimension reduction or Graph/Neighbor object to +score. Must be in the Seurat object.

    + + +
    graph.type
    +

    one of 'distances' (default) or 'connectivities', to +indicate the type of graph when what is not a dimension reduction.

    + + +
    seed.use
    +

    the value of the seed to obtain reproducible results. +NULL disables to use of a seed

    + + +
    verbose
    +

    whether to print progress messages

    + + +
    assay
    +

    assay to use. Passed to Seurat to automatically construct the +batch.var when not provided +(DefaultAssay() is used by default). +Useless otherwise

    + + +
    layer
    +

    layer to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreKBET: a list with one element per cell.var. Each +is a named numeric vector of kBET score (floats between 0 and 1), one per +cell-label.

    +

    AddScoreKBET: the updated Seurat object with the mean kBET +score(s) set for the integration.

    +
    +
    +

    References

    +

    Büttner, M., Miao, Z., Wolf, F. A., Teichmann, S. A. & Theis, F. +J. A test metric for assessing single-cell RNA-seq batch correction. +Nat Methods 16, 43–49 (2018). +DOI

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-lisi.html b/reference/score-lisi.html new file mode 100644 index 0000000..3378d60 --- /dev/null +++ b/reference/score-lisi.html @@ -0,0 +1,272 @@ + +Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute the Local Inverse Simpson's Index (LISI) to estimate batch mixing or +cell type mixing (iLISI and cLISI respectively according to Luecken M.D. +et al., 2022).

    +

    AddScoreLISI returns an updated Seurat object, while ScoreLISI +outputs the raw LISI scores for each cell

    +
    + +
    +

    Usage

    +
    AddScoreLISI(
    +  object,
    +  integration,
    +  batch.var = NULL,
    +  cell.var = NULL,
    +  reduction,
    +  dims = NULL,
    +  graph.name,
    +  graph.type = c("distances", "connectivities"),
    +  do.symmetrize = TRUE,
    +  save.graph = TRUE,
    +  new.graph = NULL,
    +  perplexity = 30,
    +  tol = 1e-05,
    +  do.scale = TRUE,
    +  largest.component.only = FALSE,
    +  assay = NULL,
    +  verbose = TRUE,
    +  ...
    +)
    +
    +ScoreLISI(
    +  object,
    +  batch.var = NULL,
    +  cell.var = NULL,
    +  reduction,
    +  dims = NULL,
    +  graph.name,
    +  graph.type = c("distances", "connectivities"),
    +  do.symmetrize = TRUE,
    +  return.graph = FALSE,
    +  perplexity = 30,
    +  tol = 1e-05,
    +  largest.component.only = FALSE,
    +  assay = NULL,
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    integration
    +

    name of the integration to score

    + + +
    batch.var
    +

    The name of the batch variable (must be in the object metadata). +Can be omitted if cell.var is not NULL

    + + +
    cell.var
    +

    The name of the cell variable (must be in the object metadata). +Can be omitted if batch.var is not NULL

    + + +
    reduction
    +

    The name of the reduction to score. Arguments +reduction and graph.name are mutually exclusive

    + + +
    dims
    +

    The dimensions of reduction to consider. All dimensions are +used by default. Ignored when scoring a graph

    + + +
    graph.name
    +

    The name of the knn graph to score. Arguments +reduction and graph.name are mutually exclusive

    + + +
    graph.type
    +

    one of 'distances' or 'connectivities' (not supported yet). +Ignored when scoring a cell embedding

    + + +
    do.symmetrize
    +

    whether to symmetrize the knn graphs. Set toFALSE +to disable (not recommended, especially when scoring a knn graph directly. +See Details)

    + + +
    save.graph
    +

    whether to save the graph used to compute the LISI score(s) +in the Seurat object

    + + +
    new.graph
    +

    name of the graph used to compute the LISI score(s). +When new.graph = NULL (default), a name is constructed depending on +input and arguments. Ignored when save.graph = FALSE

    + + +
    perplexity
    +

    third of number of each cell's neighbours. When the value of +perplexity and the number of neighbours (*3) are discrepant, the graph is +adapted. Multiple scores with varying values of perplexity are not comparable, +hence it is recommended to use the same value for each integration to score.

    + + +
    tol
    +

    Stop the computation of the local Simpson's index when it converges +to this tolerance.

    + + +
    do.scale
    +

    whether to scale the output LISI values between 0 and 1.

    + + +
    largest.component.only
    +

    whether to compute the scores on the largest +component or all sufficiently large components (default)

    + + +
    assay
    +

    the name of the assay to reference in the output Graph object ( +when save.graph = TRUE)

    + + +
    verbose
    +

    whether to print progress messages

    + + +
    ...
    +

    Additional parameters to pass to other methods +(see Details).

    + + +
    return.graph
    +

    whether to return the graph used to compute the LISI score(s)

    + +
    +
    +

    Value

    +

    ScoreLISI: a data frame with each cell's raw LISI score, or +a list containing the aforementioned data frame and the graph used to compute +it (return.graph = TRUE).

    +

    AddScoreLISI: the updated Seurat object, with cell-wise LISI +scores in the meta data (identical to ScoreLISI's output), global +scores in misc and a new Graph object when save.graph = TRUE.

    +
    +
    +

    Details

    +

    When scoring a reduction, a knn graph with enough neighbours per cell is +computed. If do.symmetrize = TRUE, the graph is symmetrized and the k +best neighbours are kept.

    +

    When scoring a knn graph, the graph is expanded with Dijkstra's algorithm to +reach enough neighbours per cell. If do.symmetrize = TRUE, the graph +is symmetrized beforehand. Note that when do.symmetrize = FALSE, +Dijkstra's algorithm is applied on the asymmetric distance matrix, and +components are computed. But each component is then symmetrized and Dijkstra's +algorithm is computed on each of them. Indeed, there is no guarantee that the +cells' number of neighbours is preserved after decomposing the directed graph. +Hence, when do.symmetrize = FALSE and a graph is input, the graph is +considered as directed only to find components.

    +

    In either case, it is recommended to keep do.symmetrize = TRUE.

    +

    For possible additional parameters, see FindNeighbors +(when inputting a reduction) or ExpandNeighbours (when +inputting a knn graph)

    +
    +
    +

    Note

    +

    This score is an adaptation of the LISI score as described in Korsunsky +I. et al., 2019 and also used in Luecken M.D. et al., 2022.

    +
    +
    +

    References

    +

    Korsunsky, I., Millard, N., Fan, J., Slowikowski, K., Zhang, F., +Wei, K., Baglaenko, Y., Brenner, M., Loh, P. & Raychaudhuri, S. Fast, +sensitive and accurate integration of single-cell data with Harmony. Nat +Methods 16, 1289–1296 (2019). +DOI

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    + +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-nmi.html b/reference/score-nmi.html new file mode 100644 index 0000000..ada995a --- /dev/null +++ b/reference/score-nmi.html @@ -0,0 +1,156 @@ + +Score a clustering result with normalised mutual information — ScoreNMI • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Compute a score based on normalised mutual information between a clustering +result and one or more cell type label variable(s). 0 and 1 reflect an absence +of mutual information and a perfect correlation respectively.

    +
    + +
    +

    Usage

    +
    ScoreNMI(
    +  object,
    +  cell.var,
    +  clust.var = "seurat_clusters",
    +  average.entropy = c("mean", "geom", "min", "max")
    +)
    +
    +AddScoreNMI(
    +  object,
    +  integration,
    +  cell.var,
    +  clust.var = "seurat_clusters",
    +  average.entropy = c("mean", "geom", "min", "max")
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    cell.var
    +

    The name(s) of the column(s) with cell type label variable +(must be in the object metadata). Multiple column names are accepted

    + + +
    clust.var
    +

    The name of the column with cluster id assignment for each +cell (must be in the object metadata). Only one column name is accepted

    + + +
    average.entropy
    +

    method to compute the value of the normalisation +denominator from each variable's entropy. one of 'mean', 'geom', 'min' and +'max', namely 'arithmetic mean of', 'geometric mean of', 'minimum' and +'maximum' entropy respectively.

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreNMI: a named array with as many values as there are +common strings between cell.var and the column names of the object's +metadata. Names are cell.var and values are NMI scores.

    +

    AddScoreNMI: the updated Seurat object with the NMI score(s) +set for the integration.

    +
    +
    +

    Details

    +

    Considering a \(N\)-cells dataset, with \(\left|L_i\right|\) the number +of cells labelled with cell type \(L_i\) and \(\left|C_i\right|\) the +number of cells in cluster \(C_i\). The discrete mutual information +\(MI\) approximation is given by: +$$\displaystyle MI(L, C) = \sum_{i=1}^{\left|L\right|}\sum_{j=1}^{\left|C\right|} \left( \frac{\left|L_i \cap C_j\right|}{N} \times log \left(\frac{N \times \left|L_i \cap C_j\right|}{\left|L_i\right| \left|C_j\right|} \right) \right)$$ +Then, \(MI\) is normalised (scaled) by a denominator, which is computed by +applying a function \(f\) on both variables' entropies (\(H\)). +\(f\) can either be the arithmetic mean, geometric mean, maximum or +minimum of entropies. +$$\displaystyle NMI(L, C) = \frac{MI(L, C)}{f(H(L), H(C))}$$

    +
    +
    +

    Note

    +

    The metric is symmetric. Switching cell.var with clust.var will return +the same value.

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    + +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/score-regressPC.html b/reference/score-regressPC.html new file mode 100644 index 0000000..a07d756 --- /dev/null +++ b/reference/score-regressPC.html @@ -0,0 +1,201 @@ + +Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    Linearly regresses principal components with batch variable as a proxy to +estimate batch mixing. The resulting R2 are then weighted by each dimension's +contribution to variance.

    +
    + +
    +

    Usage

    +
    ScoreRegressPC(
    +  object,
    +  batch.var = NULL,
    +  reduction = "pca",
    +  dims = NULL,
    +  adj.r2 = FALSE,
    +  weight.by = c("var", "stdev"),
    +  assay = NULL,
    +  layer = NULL
    +)
    +
    +AddScoreRegressPC(
    +  object,
    +  integration,
    +  batch.var = NULL,
    +  reduction = "pca",
    +  dims = NULL,
    +  adj.r2 = FALSE,
    +  weight.by = c("var", "stdev"),
    +  assay = NULL,
    +  layer = NULL
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object

    + + +
    batch.var
    +

    The name of the batch variable (must be in the object metadata)

    + + +
    reduction
    +

    The name of the reduction to score

    + + +
    dims
    +

    The dimensions to consider. All dimensions are used by default

    + + +
    adj.r2
    +

    Whether to use the adjusted R2 instead of the raw R2

    + + +
    weight.by
    +

    one of 'var' (default) or 'stdev' (standing for variance and +standard deviation respectively). Use the variance or the standard deviation +explained by the principal components to weight the each PC's score.

    + + +
    assay
    +

    assay to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    layer
    +

    layer to use. Passed to Seurat to automatically construct the +batch.var when not provided. Useless otherwise

    + + +
    integration
    +

    name of the integration to score

    + +
    +
    +

    Value

    +

    ScoreRegressPC: A single float corresponding to the score of +the given reduction

    +

    AddScoreRegressPC: the updated Seurat object with the regression +PCA score set for the integration.

    +
    +
    +

    Details

    +

    The linear regression is +$$PC_i = Batch$$

    + +

    The score is computed as follow : +$$\sum_{i=1}^{p} \left ( R^2_i * V_i \right )$$

    +

    For a PCA with p dimensions, \(PC_i\) is the principal component i, +\(R^2_i\) is the R squared coefficient of the linear regression for the +dimension i. \(V_i\) is the proportion of variance explained by the +\(PC_i\).

    +
    +
    +

    Note

    +

    This score is an adaptation of the principal component regression (PCR) +score from Luecken M.D. et al., 2022.

    +
    +
    +

    References

    +

    Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, A., +Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., +Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration in +single-cell genomics. Nat Methods 19, 41–50 (2021). +DOI

    +
    +
    +

    See also

    +

    ScoreDensityPC for an alternative and +ScoreRegressPC.CellCycle to regresses PCs by cell cycle scores.

    +
    + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +score.r2 <- ScoreRegressPC(obj, "Method", "pca", dim = 1:30)
    +score.adj.r2 <- ScoreRegressPC(obj, "Method", "pca", dim = 1:30, adj.r2 = TRUE)
    +
    +score.r2    # ~ 0.1147
    +score.adj.r2     # ~ 0.1145
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/reference/symmetrize.pmax.sparse.html b/reference/symmetrize.pmax.sparse.html new file mode 100644 index 0000000..0c640d4 --- /dev/null +++ b/reference/symmetrize.pmax.sparse.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/symmetrize.pmin.sparse.html b/reference/symmetrize.pmin.sparse.html new file mode 100644 index 0000000..0c640d4 --- /dev/null +++ b/reference/symmetrize.pmin.sparse.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/reference/trVAEIntegration.html b/reference/trVAEIntegration.html new file mode 100644 index 0000000..52c170b --- /dev/null +++ b/reference/trVAEIntegration.html @@ -0,0 +1,370 @@ + +Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration • SeuratIntegrate + Skip to contents + + +
    +
    +
    + +
    +

    A wrapper to run trVAE on multi-layered Seurat V5 object. +Requires a conda environment with scArches and necessary dependencies

    + +

    Recommendations: use raw counts (except for recon.loss = "mse") +and all features (features = Features(object), layers = "counts", +scale.layer = NULL).

    +
    + +
    +

    Usage

    +
    trVAEIntegration(
    +  object,
    +  orig = NULL,
    +  groups = NULL,
    +  groups.name = NULL,
    +  surgery.name = NULL,
    +  surgery.sort = TRUE,
    +  features = NULL,
    +  layers = ifelse(recon.loss == "mse", "data", "counts"),
    +  scale.layer = "scale.data",
    +  conda_env = NULL,
    +  new.reduction = "integrated.trVAE",
    +  reduction.key = "trVAElatent_",
    +  torch.intraop.threads = 4L,
    +  torch.interop.threads = NULL,
    +  model.save.dir = NULL,
    +  ndims.out = 10L,
    +  recon.loss = c("nb", "zinb", "mse"),
    +  hidden_layer_sizes = c(256L, 64L),
    +  dr_rate = 0.05,
    +  use_mmd = TRUE,
    +  mmd_on = c("z", "y"),
    +  mmd_boundary = NULL,
    +  beta = 1,
    +  use_bn = FALSE,
    +  use_ln = TRUE,
    +  n_epochs = 400L,
    +  lr = 0.001,
    +  eps = 0.01,
    +  hide.py.warn = T,
    +  seed.use = 42L,
    +  verbose = TRUE,
    +  ...
    +)
    +
    + +
    +

    Arguments

    + + +
    object
    +

    A Seurat object +(or an Assay5 object if +not called by IntegrateLayers)

    + + +
    orig
    +

    DimReduc object. Not to be set +directly when called with IntegrateLayers, use +orig.reduction argument instead

    + + +
    groups
    +

    A named data frame with grouping information. Can also +contain surgery groups to perform surgery integration.

    + + +
    groups.name
    +

    Column name from groups data frame that stores +grouping information. If groups.name = NULL, the first column is used

    + + +
    surgery.name
    +

    Column name from groups data frame that stores +surgery information. If surgery.name = NULL, a one shot integration is +performed

    + + +
    surgery.sort
    +

    change the order in which surgery groups are integrated. +By default (surgery.sort = TRUE), surgery groups are ordered by name. +When FALSE, each group is integrated in the order of first occurrence +in the column surgery.name

    + + +
    features
    +

    Vector of feature names to input to the integration method. +When features = NULL (default), the +VariableFeatures are used. To pass all features, +use the output of Features()

    + + +
    layers
    +

    Name of the layers to use in the integration

    + + +
    scale.layer
    +

    Name of the scaled layer in Assay

    + + +
    conda_env
    +

    Path to conda environment to run trVAE (should also +contain the scipy python module). By default, uses the conda environment +registered for trVAE in the conda environment manager

    + + +
    new.reduction
    +

    Name of the new integrated dimensional reduction

    + + +
    reduction.key
    +

    Key for the new integrated dimensional reduction

    + + +
    torch.intraop.threads
    +

    Number of intra-op threads available to torch +when training on CPU instead of GPU. Set via torch.set_num_threads().

    + + +
    torch.interop.threads
    +

    Number of intra-op threads available to torch +when training on CPU instead of GPU. Set via torch.set_num_interop_threads(). +Can only be changed once, on first call.

    + + +
    model.save.dir
    +

    Path to a directory to save the model(s) to. Uses +TRVAE.save(). Does not save anndata. model.save.dir = NULL +(default) disables saving the model(s).

    + + +
    ndims.out
    +

    Number of dimensions for new.reduction output. +Corresponds to latent_dim argument in the original API of TRVAE from +scArches

    + + +
    recon.loss
    +

    Definition of Reconstruction-Loss-Method. One of 'mse', 'nb' +or 'zinb' (hence mean squared error, negative binomial and zero-inflated +negative binomial respectively). Recommended to set layer = "data" for +'mse' (and layer = "counts" for (zi)nb)

    + + +
    hidden_layer_sizes
    +

    Hidden layer sizes for encoder network

    + + +
    dr_rate
    +

    Dropout rate applied to all layers. dr_rate = 0 disables +dropout.

    + + +
    use_mmd
    +

    Whether an additional MMD loss is to be calculated on the +latent dim. (see next argument)

    + + +
    mmd_on
    +

    Choose on which layer MMD loss will be calculated on. One of 'z' +for latent dim or 'y' for the first decoder layer. Only applies when +use_mmd = TRUE

    + + +
    mmd_boundary
    +

    On how many groups the MMD loss should be calculated on. +If mmd_boundary = NULL (default), MMD is calculated on all groups. +Only applies when use_mmd = TRUE

    + + +
    beta
    +

    Scaling factor for MMD loss (1 by default). Only applies when +use_mmd = TRUE

    + + +
    use_bn
    +

    Whether to apply a batch normalization to layers

    + + +
    use_ln
    +

    Whether to apply a layer normalization to layers

    + + +
    n_epochs
    +

    Maximum number of epochs to train the model

    + + +
    lr
    +

    Learning rate for training

    + + +
    eps
    +

    torch.optim.Adam eps parameter to improve numerical stability +(see here)

    + + +
    hide.py.warn
    +

    Disables some uninformative warnings from torch

    + + +
    seed.use
    +

    An integer to generate reproducible outputs. +Set seed.use = NULL to disable

    + + +
    verbose
    +

    Print messages. Set to FALSE to disable

    + + +
    ...
    +

    Additional arguments to be passed to +scarches.models.TRVAE.train, TRVAE.load_query_data +or TRVAE.get_latent (see Details section)

    + +
    +
    +

    Value

    +

    A list containing:

    • Without surgery groups: a new DimReduc of name + new.reduction (key set to reduction.key) consisting of the + latent space of the model with ndims.out dimensions.

    • +
    • With surgery groups: one new DimReduc per surgery groups of + name new.reduction_[surgery.group] (key set to + reduction.key[surgery.group]) consisting of the latent space of the + corresponding models with ndims.out dimensions, as well as a 'full' + latent representation of name new.reduction_[surgery1]_[surgery2]_... + and key set to reduction.keyFull-.

    • +

    When called via IntegrateLayers, a Seurat object with +the new reduction and/or assay is returned

    +
    +
    +

    Details

    +

    This wrappers calls three to four python functions through reticulate. +Find the trVAE-specific arguments there:

    Note that seed.use is passed to torch.manual_seed(). +If it is not sufficient to achieve full reproducibility, set +mean = TRUE or mean_var = TRUE

    +
    +
    +

    Note

    +

    This function requires the +scArches package +to be installed (along with scipy)

    +
    +
    +

    References

    +

    Lotfollahi, M., Naghipourfar, M., Theis, F. J. & Wolf, F. A. +Conditional out-of-distribution generation for unpaired data using transfer +VAE. Bioinformatics 36, i610–i617 (2020). +DOI

    +

    Lotfollahi, M., Naghipourfar, M., Luecken, M. D., Khajavi, M., +Büttner, M., Wagenstetter, M., Avsec, Ž., Gayoso, A., Yosef, N., Interlandi, +M., Rybakov, S., Misharin, A. V. & Theis, F. J. Mapping single-cell data to +reference atlases by transfer learning. Nat Biotechnol 40, 121–130 (2021). +DOI

    +
    + + +
    +

    Examples

    +
    if (FALSE) { # \dontrun{
    +# Preprocessing
    +obj <- SeuratData::LoadData("pbmcsca")
    +obj[["RNA"]] <- split(obj[["RNA"]], f = obj$Method)
    +obj <- NormalizeData(obj)
    +obj <- FindVariableFeatures(obj)
    +obj <- ScaleData(obj)
    +obj <- RunPCA(obj)
    +
    +# After preprocessing, we integrate layers:
    +obj <- IntegrateLayers(object = obj, method = trVAEIntegration,
    +                       features = Features(obj), scale.layer = NULL,
    +                       layers = 'counts', groups = obj[[]],
    +                       groups.name = 'Method')
    +
    +# To enable surgery and full reproducibility and change the recon loss method:
    +obj <- IntegrateLayers(object = obj, method = trVAEIntegration,
    +                       features = Features(obj), scale.layer = NULL,
    +                       layers = 'data', groups = obj[[]],
    +                       groups.name = 'Method', surgery.name = 'Experiment',
    +                       mean_var = TRUE, recon.loss = 'mse')
    +} # }
    +
    +
    +
    +
    + + +
    + + + +
    + + + + + + + diff --git a/search.json b/search.json new file mode 100644 index 0000000..b96cec4 --- /dev/null +++ b/search.json @@ -0,0 +1 @@ +[{"path":"https://cbib.github.io/Seurat-Integrate/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2024 Centre de Bioinformatique de Bordeaux (CBiB) Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"introduction","dir":"Articles","previous_headings":"","what":"Introduction","title":"Introduction to SeuratIntegrate","text":"SeuratIntegrate R package aims extend pool single-cell RNA sequencing (scRNA-seq) integration methods available Seurat. Moreover, SeuratIntegrate provides set tools evaluate performance integrations produced.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"integrations","dir":"Articles","previous_headings":"Introduction","what":"Integrations","title":"Introduction to SeuratIntegrate","text":"SeuratIntegrate provides access R Python methods correct batch effect: Comprehensive overview integration methods provided SeuratIntegrate SeuratIntegrate provides new interface integrate layers object: DoIntegrate(). Moreover, SeuratIntegrate compatible CCA RPCA (included Seurat) FastMNN (SeuratWrappers)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scoring","dir":"Articles","previous_headings":"Introduction","what":"Scoring","title":"Introduction to SeuratIntegrate","text":"SeuratIntegrate incorporates 11 scoring metrics: 6 quantify degree batch mixing (batch correction), 5 assess preservation biological differences (bio-conservation) based ground truth cell type labels. table summarising score’s input type: Table summarising inputs required score, type scores belongs . scores computed embedding (Seurat::DimReduc object) graph (Seurat::Neighbor Seurat::Graph object). exceptions ARI NMI, compare two categorical variables thus don’t need anything else cell-type cluster assignment variables.d anything else cell-type cluster assignment variables. scores based cell type label variable. consists estimate cell’s type obtained analysing batch separately using automatic cell annotation algorithm. estimate cell types must sufficient quality considered suitable ground truth.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"setup","dir":"Articles","previous_headings":"","what":"Setup","title":"Introduction to SeuratIntegrate","text":"use small dataset 200 immune liver cells around 6,500 genes included SeuratIntegrate. comprises 4 donors 2 studies. Among donors, 2 healthy 2 suffering hepatocellular carcinoma (HCC). Importantly, Seurat object’s metadata also embeds cell type annotation variables. Note albeit compulsory, high quality cell-type annotation important evaluate performance integrations many scoring metrics use ground truth. Moreover, helps verifying whether technical effects (usually called batch effects) overweight true biological differences. , use last one save : going test 3 integration methods output different types objects. use ComBat (corrected counts), BBKNN (corrected knn graph) Harmony (corrected dimension reduction). BBKNN Python method, need conda environment able use . Right now, don’t environment: Hopefully, SeuratIntegrate facilitates task UpdateEnvCache(): Note: Similarly, can call UpdateEnvCache() Python methods (“scvi”, “scanorama”, “trVAE”) set corresponding conda environments. process successful, cache conda environments updated: also want make sure conda environment umap-learn version compatible Seurat:","code":"library(SeuratIntegrate) data(\"liver_small\") dim(liver_small) # genes x cells ## [1] 6534 200 liver_small[[]][,c(13, 15:17)] cell.var <- \"manual_cell_type_short\" getCache() UpdateEnvCache(\"bbknn\") getCache() reticulate::conda_create('umap_0.5.4', packages = 'umap=0.5.4')"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"preprocessing-with-seurat","dir":"Articles","previous_headings":"","what":"Preprocessing with Seurat","title":"Introduction to SeuratIntegrate","text":"ensure SeuratIntegrate works well, indispensable split Seurat object. process distributes cells single-batch layers batch normalized independently. account potential technical variability samples designating “ID_sample” batch variable.","code":"batch.var <- \"ID_sample\" # save for later liver_small <- split(liver_small, f = liver_small$ID_sample) liver_small <- SCTransform(liver_small) liver_small <- RunPCA(liver_small) liver_small <- FindNeighbors(liver_small, dims = 1:20, k.param = 15L) liver_small <- RunUMAP(liver_small, dims = 1:20, n.neighbors = 15) DimPlot(liver_small, group.by = c(\"First_author\", \"ID_sample\")) DimPlot(liver_small, group.by = cell.var)"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"integration-with-seuratintegrate","dir":"Articles","previous_headings":"","what":"Integration with SeuratIntegrate","title":"Introduction to SeuratIntegrate","text":"take look Seurat object, can note enriched many objects: Important outputs : New assay combat.reconstructed New reduction harmony New graphs bbknn_ridge.residuals_[…]","code":"liver_small <- DoIntegrate(object = liver_small, # integrations CombatIntegration(), bbknnIntegration(orig = \"pca\", ndims.use = 20), SeuratIntegrate::HarmonyIntegration(orig = \"pca\", dims = 1:20), # additional parameters use.hvg = TRUE, use.future = c(FALSE, TRUE, FALSE) ) ## Integration 1 in 3: integrating using 'CombatIntegration' ## Integration 2 in 3: integrating using 'bbknnIntegration' ## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck ## ## Number of nodes: 200 ## Number of edges: 1784 ## ## Running Louvain algorithm... ## Maximum modularity in 10 random starts: 0.6251 ## Number of communities: 5 ## Elapsed time: 0 seconds ## Integration 3 in 3: integrating using 'SeuratIntegrate::HarmonyIntegration' print(liver_small) cat(\"\\n#####\\n\\n\") print(Graphs(liver_small)) ## An object of class Seurat ## 22602 features across 200 samples within 4 assays ## Active assay: SCT (6534 features, 3000 variable features) ## 3 layers present: counts, data, scale.data ## 3 other assays present: RNA, combat.reconstructed, bbknn.ridge ## 4 dimensional reductions calculated: pca, umap, pca.bbknn, harmony ## ## ##### ## ## [1] \"SCT_nn\" ## [2] \"SCT_snn\" ## [3] \"bbknn_scale.data_connectivities\" ## [4] \"bbknn_scale.data_distances\" ## [5] \"bbknn_ridge.residuals_connectivities\" ## [6] \"bbknn_ridge.residuals_distances\""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"post-processing","dir":"Articles","previous_headings":"","what":"Post-processing","title":"Introduction to SeuratIntegrate","text":"type output important consider, scoring metrics compatible output types. simplest strategy process output separately order obtain least PCA , even knn graph (indispensable compute clusters). Note several scores computed knn graphs, hence knn graph outputs (e.g. BBKNN) can evaluated reduced set metrics. summary output type (bracketed steps always necessary): corrected counts: [ScaleData()] -> RunPCA() -> [FindNeighbors() -> FindOptimalClusters()] Dimension reduction: [RunPCA()] -> [FindNeighbors() -> FindOptimalClusters()] knn graph: [FindOptimalClusters()] , use SymmetrizeKnn() FindNeighbors() FindOptimalClusters() return.neighbor = TRUE. useful keep distances cells KNN graph. Although compulsory, used stay line BBKNN’s output. prevent community detection algorithm output high fraction singletons, “symmetrize” matrix makes graph “undirected”.","code":"# corrected counts outputs DefaultAssay(liver_small) <- \"combat.reconstructed\" VariableFeatures(liver_small) <- VariableFeatures(liver_small[[\"SCT\"]]) liver_small <- ScaleData(liver_small) liver_small <- RunPCA(liver_small, npcs = 50L, reduction.name = \"pca.combat\") liver_small <- FindNeighbors(liver_small, reduction = \"pca.combat\", dims = 1:20, return.neighbor = TRUE, graph.name = \"knn.combat\") liver_small <- SymmetrizeKnn(liver_small, graph.name = \"knn.combat\") liver_small <- FindOptimalClusters(liver_small, graph.name = \"knn.combat_symmetric\", cluster.name = \"combat_{cell.var}_{metric}\", cell.var = cell.var, optimisation.metric = c(\"nmi\", \"ari\")) # default, compute both DefaultAssay(liver_small) <- \"SCT\" # dimension reduction outputs liver_small <- FindNeighbors(liver_small, reduction = \"pca\", dims = 1:20, k.param = 20L, return.neighbor = TRUE, graph.name = \"knn.unintegrated\") liver_small <- SymmetrizeKnn(liver_small, graph.name = \"knn.unintegrated\") liver_small <- FindOptimalClusters(liver_small, graph.name = \"knn.unintegrated_symmetric\", cluster.name = \"unintegrated_{cell.var}_{metric}\", cell.var = cell.var) liver_small <- FindNeighbors(liver_small, reduction = \"harmony\", dims = 1:20, return.neighbor = TRUE, graph.name = \"knn.harmony\") liver_small <- SymmetrizeKnn(liver_small, graph.name = \"knn.harmony\") liver_small <- FindOptimalClusters(liver_small, graph.name = \"knn.harmony_symmetric\", cell.var = cell.var, cluster.name = \"harmony_{cell.var}_{metric}\") # graph outputs liver_small <- SymmetrizeKnn(liver_small, graph.name = \"bbknn_ridge.residuals_distances\") liver_small <- FindOptimalClusters(liver_small, graph.name = \"bbknn_ridge.residuals_distances_symmetric\", cell.var = cell.var, cluster.name = \"bbknn_{cell.var}_{metric}\")"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scoring-1","dir":"Articles","previous_headings":"","what":"Scoring","title":"Introduction to SeuratIntegrate","text":"Now post-processed integration’s output, can compute multiple scores estimate accuracy integrations.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scores-not-requiring-a-cell-type-variable","dir":"Articles","previous_headings":"Scoring","what":"Scores not requiring a cell type variable","title":"Introduction to SeuratIntegrate","text":"scores run dimension reduction (PCA) compatible graph outputs. cell-type free score thus require cell-type label variable.","code":"liver_small <- AddScoreRegressPC(liver_small, integration = \"unintegrated\", batch.var = batch.var, reduction = \"pca\") liver_small <- AddScoreRegressPC(liver_small, integration = \"combat\", batch.var = batch.var, reduction = \"pca.combat\") liver_small <- AddScoreRegressPC(liver_small, integration = \"harmony\", batch.var = batch.var, reduction = \"harmony\") liver_small <- AddScoreDensityPC(liver_small, integration = \"unintegrated\", batch.var = batch.var, reduction = \"pca\") liver_small <- AddScoreDensityPC(liver_small, integration = \"combat\", batch.var = batch.var, reduction = \"pca.combat\") liver_small <- AddScoreRegressPC(liver_small, integration = \"harmony\", batch.var = batch.var, reduction = \"harmony\") liver_small <- CellCycleScoringPerBatch(liver_small, batch.var = batch.var, s.features = cc.genes$s.genes, g2m.features = cc.genes$g2m.genes) liver_small <- AddScoreRegressPC.CellCycle(liver_small, integration = \"unintegrated\", batch.var = batch.var, what = \"pca\", compute.cc = FALSE, dims.use = 1:20) liver_small <- AddScoreRegressPC.CellCycle(liver_small, integration = \"combat\", batch.var = batch.var, what = \"pca.combat\", compute.cc = FALSE, dims.use = 1:20) liver_small <- AddScoreRegressPC.CellCycle(liver_small, integration = \"harmony\", batch.var = batch.var, what = \"harmony\", compute.cc = FALSE, dims.use = 1:20)"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scores-based-on-silhouette-width","dir":"Articles","previous_headings":"Scoring","what":"Scores based on silhouette width","title":"Introduction to SeuratIntegrate","text":"scores return average silhouette width (ASW), either per cell type label per batch. run dimension reduction (PCA) compatible graph outputs. based cell-type label variable. However, ScoreASWBatch() can run cell-type label independent manner per.cell.var = FALSE.","code":"liver_small <- AddScoreASW(liver_small, integration = \"unintegrated\", cell.var = cell.var, what = \"pca\") liver_small <- AddScoreASW(liver_small, integration = \"combat\", cell.var = cell.var, what = \"pca.combat\") liver_small <- AddScoreASW(liver_small, integration = \"harmony\", cell.var = cell.var, what = \"harmony\") liver_small <- AddScoreASWBatch(liver_small, integration = \"unintegrated\", batch.var = batch.var, cell.var = cell.var, what = \"pca\") liver_small <- AddScoreASWBatch(liver_small, integration = \"combat\", batch.var = batch.var, cell.var = cell.var, what = \"pca.combat\") liver_small <- AddScoreASWBatch(liver_small, integration = \"harmony\", batch.var = batch.var, cell.var = cell.var, what = \"harmony\")"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scores-working-on-a-graph","dir":"Articles","previous_headings":"Scoring","what":"Scores working on a graph","title":"Introduction to SeuratIntegrate","text":"scores graph outputs. require cell-type label variable.","code":"liver_small <- AddScoreConnectivity(liver_small, integration = \"unintegrated\", graph.name = \"knn.unintegrated_symmetric\", cell.var = cell.var) liver_small <- AddScoreConnectivity(liver_small, integration = \"combat\", graph.name = \"knn.combat_symmetric\", cell.var = cell.var) liver_small <- AddScoreConnectivity(liver_small, integration = \"harmony\", graph.name = \"knn.harmony_symmetric\", cell.var = cell.var) liver_small <- AddScoreConnectivity(liver_small, integration = \"bbknn\", graph.name = \"bbknn_ridge.residuals_distances_symmetric\", cell.var = cell.var) liver_small <- AddScoreLISI(liver_small, integration = \"unintegrated\", batch.var = batch.var, cell.var = cell.var, reduction = \"pca\") liver_small <- AddScoreLISI(liver_small, integration = \"combat\", batch.var = batch.var, cell.var = cell.var, reduction = \"pca.combat\") liver_small <- AddScoreLISI(liver_small, integration = \"harmony\", batch.var = batch.var, cell.var = cell.var, reduction = \"harmony\") liver_small <- AddScoreLISI(liver_small, integration = \"bbknn\", batch.var = batch.var, cell.var = cell.var, reduction = NULL, graph.name = \"bbknn_ridge.residuals_distances_symmetric\")"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scores-comparing-two-categorical-variables","dir":"Articles","previous_headings":"Scoring","what":"Scores comparing two categorical variables","title":"Introduction to SeuratIntegrate","text":"scores compare two categorical variables. Thus, don’t need anything else cell-type cluster assignment variables (computed Post-processing FindOptimalClusters()).","code":"liver_small <- AddScoreARI(liver_small, integration = \"unintegrated\", cell.var = cell.var, clust.var = paste(\"unintegrated\", cell.var, \"ari\", sep = \"_\")) liver_small <- AddScoreARI(liver_small, integration = \"combat\", cell.var = cell.var, clust.var = paste(\"combat\", cell.var, \"ari\", sep = \"_\")) liver_small <- AddScoreARI(liver_small, integration = \"harmony\", cell.var = cell.var, clust.var = paste(\"harmony\", cell.var, \"ari\", sep = \"_\")) liver_small <- AddScoreARI(liver_small, integration = \"bbknn\", cell.var = cell.var, clust.var = paste(\"bbknn\", cell.var, \"ari\", sep = \"_\")) liver_small <- AddScoreNMI(liver_small, integration = \"unintegrated\", cell.var = cell.var, clust.var = paste(\"unintegrated\", cell.var, \"nmi\", sep = \"_\")) liver_small <- AddScoreNMI(liver_small, integration = \"combat\", cell.var = cell.var, clust.var = paste(\"combat\", cell.var, \"nmi\", sep = \"_\")) liver_small <- AddScoreNMI(liver_small, integration = \"harmony\", cell.var = cell.var, clust.var = paste(\"harmony\", cell.var, \"nmi\", sep = \"_\")) liver_small <- AddScoreNMI(liver_small, integration = \"bbknn\", cell.var = cell.var, clust.var = paste(\"bbknn\", cell.var, \"nmi\", sep = \"_\"))"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"scaling-and-comparison","dir":"Articles","previous_headings":"Scoring","what":"Scaling and comparison","title":"Introduction to SeuratIntegrate","text":"Now obtained several scores per integration, can compare performances. First, let’s scale scores zero one standardize direction (closer one, always better). step makes things easier compare improves interpretability. Now, let’s plot integrations. can observe 3 overall scores computed, namely batch correction, bio-conservation overall (average last two). balance score’s contribution overall scores, min-max rescaling applied score scaling, stretching original score’s bounds zero one. can disabled preview original scores: can also hide scores integrations. instance, “PCA.density” “PCA.regression” hardly informative. Let’s exclude see affects overall scores: Interestingly, obtained ranking integrations first figure.","code":"liver_small <- ScaleScores(liver_small) PlotScores(liver_small) PlotScores(liver_small, rescale = FALSE) PlotScores(liver_small, rescale = FALSE, exclude.score = c(\"PCA.density\", \"PCA.regression\"))"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html","id":"projecting-integrations-on-umaps","dir":"Articles","previous_headings":"","what":"Projecting integrations on UMAPs","title":"Introduction to SeuratIntegrate","text":"also possible project cells UMAP computed integration’s output, complementary (visual) inspection integration performances. UMAP unintegrated data UMAP ComBat integration UMAP BBKNN integration","code":"liver_small <- RunUMAP(liver_small, dims = 1:20, reduction = \"pca.combat\", reduction.name = \"umap.combat\") liver_small <- RunUMAP(liver_small, dims = 1:20, reduction = \"harmony\", reduction.name = \"umap.harmony\") library(future) plan(multisession) liver_small %<-% { reticulate::use_condaenv('umap_0.5.4') RunUMAP(liver_small, graph = \"bbknn_ridge.residuals_connectivities\", umap.method = \"umap-learn\", n.epochs = 200L, reduction.name = \"umap.bbknn\") } liver_small plan(sequential) DimPlot(liver_small, group.by = c(batch.var, cell.var), reduction = \"umap\") DimPlot(liver_small, group.by = c(batch.var, cell.var), reduction = \"umap.combat\") DimPlot(liver_small, group.by = c(batch.var, cell.var), reduction = \"umap.bbknn\") ## R version 4.4.2 (2024-10-31) ## Platform: x86_64-pc-linux-gnu ## Running under: Linux Mint 21 ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=fr_FR.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C ## ## time zone: Europe/Paris ## tzcode source: system (glibc) ## ## attached base packages: ## [1] stats graphics grDevices utils datasets methods base ## ## other attached packages: ## [1] future_1.34.0 dplyr_1.1.4 SeuratIntegrate_0.4.0 ## [4] Seurat_5.1.0 SeuratObject_5.0.2 sp_2.1-4 ## ## loaded via a namespace (and not attached): ## [1] RcppAnnoy_0.0.22 splines_4.4.2 ## [3] later_1.4.1 batchelor_1.20.0 ## [5] tibble_3.2.1 polyclip_1.10-7 ## [7] XML_3.99-0.17 fastDummies_1.7.4 ## [9] lifecycle_1.0.4 edgeR_4.2.2 ## [11] globals_0.16.3 lattice_0.22-6 ## [13] MASS_7.3-61 backports_1.5.0 ## [15] magrittr_2.0.3 limma_3.60.6 ## [17] plotly_4.10.4 sass_0.4.9 ## [19] rmarkdown_2.29 jquerylib_0.1.4 ## [21] yaml_2.3.10 httpuv_1.6.15 ## [23] glmGamPoi_1.16.0 sctransform_0.4.1 ## [25] spam_2.11-0 spatstat.sparse_3.1-0 ## [27] reticulate_1.40.0 DBI_1.2.3 ## [29] cowplot_1.1.3 pbapply_1.7-2 ## [31] RColorBrewer_1.1-3 ResidualMatrix_1.14.1 ## [33] abind_1.4-8 zlibbioc_1.50.0 ## [35] Rtsne_0.17 GenomicRanges_1.56.2 ## [37] purrr_1.0.2 BiocGenerics_0.50.0 ## [39] tweenr_2.0.3 rappdirs_0.3.3 ## [41] sva_3.52.0 GenomeInfoDbData_1.2.12 ## [43] IRanges_2.38.1 S4Vectors_0.42.1 ## [45] ggrepel_0.9.6 irlba_2.3.5.1 ## [47] listenv_0.9.1 spatstat.utils_3.1-1 ## [49] genefilter_1.86.0 goftest_1.2-3 ## [51] RSpectra_0.16-2 annotate_1.82.0 ## [53] spatstat.random_3.3-2 fitdistrplus_1.2-1 ## [55] parallelly_1.41.0 pkgdown_2.1.1 ## [57] DelayedMatrixStats_1.26.0 leiden_0.4.3.1 ## [59] codetools_0.2-20 DelayedArray_0.30.1 ## [61] ggforce_0.4.2 scuttle_1.14.0 ## [63] tidyselect_1.2.1 UCSC.utils_1.0.0 ## [65] farver_2.1.2 ScaledMatrix_1.12.0 ## [67] matrixStats_1.4.1 stats4_4.4.2 ## [69] spatstat.explore_3.3-3 jsonlite_1.8.9 ## [71] BiocNeighbors_1.22.0 progressr_0.15.1 ## [73] ggridges_0.5.6 survival_3.8-3 ## [75] systemfonts_1.1.0 tools_4.4.2 ## [77] ragg_1.3.3 ica_1.0-3 ## [79] Rcpp_1.0.13-1 glue_1.8.0 ## [81] gridExtra_2.3 SparseArray_1.4.8 ## [83] mgcv_1.9-1 xfun_0.49 ## [85] MatrixGenerics_1.16.0 GenomeInfoDb_1.40.1 ## [87] withr_3.0.2 fastmap_1.2.0 ## [89] digest_0.6.37 rsvd_1.0.5 ## [91] R6_2.5.1 mime_0.12 ## [93] textshaping_0.4.1 colorspace_2.1-1 ## [95] scattermore_1.2 tensor_1.5 ## [97] RSQLite_2.3.9 spatstat.data_3.1-4 ## [99] RhpcBLASctl_0.23-42 tidyr_1.3.1 ## [101] generics_0.1.3 data.table_1.16.4 ## [103] httr_1.4.7 htmlwidgets_1.6.4 ## [105] S4Arrays_1.4.1 uwot_0.2.2 ## [107] pkgconfig_2.0.3 gtable_0.3.6 ## [109] blob_1.2.4 lmtest_0.9-40 ## [111] SingleCellExperiment_1.26.0 XVector_0.44.0 ## [113] htmltools_0.5.8.1 dotCall64_1.2 ## [115] scales_1.3.0 Biobase_2.64.0 ## [117] png_0.1-8 lisi_1.0 ## [119] harmony_1.2.3 spatstat.univar_3.1-1 ## [121] knitr_1.49 rstudioapi_0.17.1 ## [123] reshape2_1.4.4 nlme_3.1-166 ## [125] cachem_1.1.0 zoo_1.8-12 ## [127] stringr_1.5.1 KernSmooth_2.23-24 ## [129] parallel_4.4.2 miniUI_0.1.1.1 ## [131] AnnotationDbi_1.66.0 desc_1.4.3 ## [133] pillar_1.10.0 grid_4.4.2 ## [135] vctrs_0.6.5 RANN_2.6.2 ## [137] promises_1.3.2 BiocSingular_1.20.0 ## [139] distances_0.1.11 beachmat_2.20.0 ## [141] xtable_1.8-4 cluster_2.1.8 ## [143] evaluate_1.0.1 locfit_1.5-9.10 ## [145] cli_3.6.3 compiler_4.4.2 ## [147] rlang_1.1.4 crayon_1.5.3 ## [149] future.apply_1.11.3 labeling_0.4.3 ## [151] plyr_1.8.9 forcats_1.0.0 ## [153] fs_1.6.5 stringi_1.8.4 ## [155] viridisLite_0.4.2 deldir_2.0-4 ## [157] BiocParallel_1.38.0 Biostrings_2.72.1 ## [159] munsell_0.5.1 lazyeval_0.2.2 ## [161] spatstat.geom_3.3-4 Matrix_1.7-1 ## [163] RcppHNSW_0.6.0 patchwork_1.3.0 ## [165] bit64_4.5.2 sparseMatrixStats_1.16.0 ## [167] ggplot2_3.5.1 statmod_1.5.0 ## [169] KEGGREST_1.44.1 shiny_1.10.0 ## [171] SummarizedExperiment_1.34.0 ROCR_1.0-11 ## [173] memoise_2.0.1 igraph_2.1.2 ## [175] broom_1.0.7 bslib_0.8.0 ## [177] bit_4.5.0.1"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"install-and-load-the-data","dir":"Articles","previous_headings":"","what":"Install and load the data","title":"Integration example with of the pbmcsca data","text":"use pbmcsca dataset available package SeuratData.","code":"# install `SeuratData` package (if not yet) if (! requireNamespace(\"SeuratData\", quietly = TRUE)) { devtools::install_github('satijalab/seurat-data') } # increase download timeout and install the dataset options(timeout = 300) SeuratData::InstallData('pbmcsca') # load the dataset (take 1,000 first cells to speed-up execution) seu <- SeuratData::LoadData('pbmcsca')[,1:1e3] ## Warning: Assay RNA changing from Assay to Assay ## Warning: Assay RNA changing from Assay to Assay5"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"inspect-the-dataset","dir":"Articles","previous_headings":"","what":"Inspect the dataset","title":"Integration example with of the pbmcsca data","text":"look metadata: column Method provides information single-cell technology used acquire cell’s trancriptome. consider batch origin. column CellType contains cell-types annotation use later . Let’s now define batch variable cell-type variable(s):","code":"# rmarkdown::paged_table -> prints data frames in a less ugly way than default rmarkdown::paged_table(head(seu[[]], n = 10)) table(seu$Method) ## ## 10x Chromium (v2) A CEL-Seq2 Smart-seq2 ## 494 253 253 rmarkdown::paged_table(as.data.frame(table(seu$CellType))) batch.var <- 'Method' # available in the metadata of the object cell.var <- 'CellType' # available in the metadata of the object"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"seurat-data-processing---standard-workflow","dir":"Articles","previous_headings":"","what":"Seurat data processing - Standard workflow","title":"Integration example with of the pbmcsca data","text":"current Seurat object split, meaning layer contains cells batches. select column Method separate cells batch-specific layers. step indispensable run integration methods enables normalise batch (.e. layer) independently. , proceed standard Seurat workflow obtain PCA reduction. now process object can visualise dispersion cells UMAP dimension reduction. Let’s colour cells according batch cell-type label. Albeit moderately, dispersion cells UMAP seems influenced batch effect. According “CellType” variable, B cells 10x CEL-Seq2 gathered together monocyte cells fully overlap. Now, want correct technical differences.","code":"cat('Layers before split:', paste(Layers(seu), collapse = \", \"), '\\n') ## Layers before split: counts, data seu[['RNA']] <- split(seu[['RNA']], f = seu$Method) cat('Layers after split:', paste(Layers(seu), collapse = \", \"), '\\n') ## Layers after split: counts.Smart-seq2, counts.CEL-Seq2, counts.10x_Chromium_v2_A, data.Smart-seq2, data.CEL-Seq2, data.10x_Chromium_v2_A seu <- SCTransform(seu) seu <- RunPCA(seu, verbose = F) seu <- FindNeighbors(seu, reduction = \"pca\", dims = 1:30, k.param = 20L) seu <- FindClusters(seu, graph.name = 'SCT_snn', resolution = .5) seu <- RunUMAP(seu, dims = 1:30, reduction = 'pca') ## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck ## ## Number of nodes: 1000 ## Number of edges: 43767 ## ## Running Louvain algorithm... ## Maximum modularity in 10 random starts: 0.8715 ## Number of communities: 8 ## Elapsed time: 0 seconds DimPlot(seu, label = T) + NoLegend() + ggplot2::coord_fixed(ratio = .7) DimPlot(seu, group.by = batch.var) + DimPlot(seu, group.by = cell.var) & ggplot2::coord_fixed(ratio = .7)"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"integrate-batches---seuratintegrate-workflow","dir":"Articles","previous_headings":"","what":"Integrate batches - SeuratIntegrate workflow","title":"Integration example with of the pbmcsca data","text":"integration commands extent similar Seurat V5 vignette. purpose package extend set available integration methods. See bottom ?IntegrateLayers comprehensive list relevant methods. Many methods supported SeuratIntegrate implemented Python, wrappers provided rely reticulate package conda environments. familiar CondaEnvManager, look vignette(\"setup_and_tips\"). important considerations performing integration: use interface DoIntegrate() SeuratIntegrate integrate cell batches (see next section) check method-specific arguments (e.g. ?bbknnIntegration) CondaEnvManager via UpdateEnvCache() (check vignette(\"setup_and_tips\")) custom conda environment passing path - name - conda_env parameter. overrides default behaviour loading specified environment instead fetching CondaEnvManager’s cache. methods expect raw count matrix, others expect scaled counts variable features, etc. help choice, look table data (recon loss “mse”) counts (otherwise) Layers: counts: raw counts data: normalised counts scale.data: scaled normalised counts variable features /!\\ IMPORTANT /!\\ use features calling integration method IntegrateLayers(): IntegrateLayers(object, features = Features(object), scale.layer = NULL). work SCTAssay.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"dointegrate-philosophy-do_integrate","dir":"Articles","previous_headings":"Integrate batches - SeuratIntegrate workflow","what":"DoIntegrate philosophy (#do_integrate)","title":"Integration example with of the pbmcsca data","text":"function DoIntegrate() handy way run multiple integrations single command. Note : ... place specify integration commands run. integration commands expected function calls, .e. form FooIntegration(), BarIntegration(), etc. Calls accept method-specific argument (e.g. FooIntegration(layers = \"data\")) use.hvg = TRUE results using variable features use.future = TRUE useful run Python-based methods (normal R session load one conda instance, future enables launch background sessions, preventing main load conda environment.). highly recommended set FALSE R-based methods. integration methods can used without modifying default parameters. vignette, change arguments meet needs. Notably, change number cores allocated method (possible). vignette, going use 3 Python-based methods, namely BBKNN, Scanorama scANVI scvi-tools suite. Let’s make sure available straight away: Let’s proceed batch-effect corrections:","code":"ncores <- parallel::detectCores() - 2 # BBKNN if (! isValid(getCache()$bbknn)) { UpdateEnvCache(\"bbknn\") } # Scanorama if (! isValid(getCache()$scanorama)) { UpdateEnvCache(\"scanorama\") } # scvi-tools if (! isValid(getCache()$scanvi)) { UpdateEnvCache(\"scanvi\") }"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"integration-part-1-using-r-based-methods","dir":"Articles","previous_headings":"Integrate batches - SeuratIntegrate workflow","what":"Integration part 1) Using R-based methods","title":"Integration example with of the pbmcsca data","text":"Note: use SeuratIntegrate:: HarmonyIntegration avoid confusion Seurat::HarmonyIntegration().","code":"seu <- DoIntegrate( object = seu, SeuratIntegrate::HarmonyIntegration(orig = \"pca\", dims = 1:30, ncores = ncores), CCAIntegration(orig = \"pca\", dims = 1:30 , new.reduction = \"cca.integrated\", normalization.method = \"SCT\"), RPCAIntegration(orig = \"pca\", dims = 1:30, new.reduction = \"rpca.integrated\", normalization.method = \"SCT\"), use.future = FALSE # R-based ) ## Integration 1 in 3: integrating using 'SeuratIntegrate::HarmonyIntegration' ## Integration 2 in 3: integrating using 'CCAIntegration' ## Integration 3 in 3: integrating using 'RPCAIntegration'"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"integration-part-2-using-python-based-methods","dir":"Articles","previous_headings":"Integrate batches - SeuratIntegrate workflow","what":"Integration part 2) Using python-based methods","title":"Integration example with of the pbmcsca data","text":"Note: set max_epochs = 20L scANVIIntegration save time ! default number epochs (400) results superior integration. take look Seurat object, can note enriched many objects: Great! successfully performed several integrations! However, stopping unsatisfactory still need process integration’s output(s) obtain least one UMAP projection . , also aim generating assessable representations score.","code":"seu <- DoIntegrate( object = seu, bbknnIntegration(orig = \"pca\", layers = \"data\", ndims = 30), ScanoramaIntegration(orig = \"pca\", ncores = ncores), scANVIIntegration(groups = seu[[]], groups.name = \"Method\", labels.name = \"CellType\", layers = \"counts\", torch.intraop.threads = ncores, torch.interop.threads = ncores, max_epochs = 20L), use.future = TRUE, # Python-based use.hvg = c(TRUE, TRUE, FALSE) ) ## Integration 1 in 3: integrating using 'bbknnIntegration' ## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck ## ## Number of nodes: 1000 ## Number of edges: 6866 ## ## Running Louvain algorithm... ## Maximum modularity in 10 random starts: 0.6812 ## Number of communities: 10 ## Elapsed time: 0 seconds ## Integration 2 in 3: integrating using 'ScanoramaIntegration' ## Integration 3 in 3: integrating using 'scANVIIntegration' print(seu) ## An object of class Seurat ## 69594 features across 1000 samples within 4 assays ## Active assay: SCT (16450 features, 3000 variable features) ## 3 layers present: counts, data, scale.data ## 3 other assays present: RNA, bbknn.ridge, scanorama.reconstructed ## 8 dimensional reductions calculated: pca, umap, harmony, cca.integrated, rpca.integrated, pca.bbknn, integrated.scanorama, integrated.scANVI cat(\"Graph objects:\", paste(Graphs(seu), collapse = \", \"), \"\\n\") cat(\"Neighbor objects:\", paste(Neighbors(seu), collapse = \", \"), \"\\n\") cat(\"Reduction dimensions:\", paste(Reductions(seu), collapse = \", \"), \"\\n\") cat(\"Assays:\", paste(Assays(seu), collapse = \", \"), \"\\n\") ## Graph objects: SCT_nn, SCT_snn, bbknn_scale.data_connectivities, bbknn_scale.data_distances, bbknn_ridge.residuals_connectivities, bbknn_ridge.residuals_distances ## Neighbor objects: ## Reduction dimensions: pca, umap, harmony, cca.integrated, rpca.integrated, pca.bbknn, integrated.scanorama, integrated.scANVI ## Assays: RNA, SCT, bbknn.ridge, scanorama.reconstructed"},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"process-outputs","dir":"Articles","previous_headings":"Score integrations","what":"Process outputs","title":"Integration example with of the pbmcsca data","text":"Several objects can produced integration algorithm, namely layer new assay (.e. corrected counts), dimension reduction (corrected embedding), knn network. even produce one output (instance Scanorama produces corrected counts dimension reduction). type output important consider, scoring metrics compatible output types. simplest strategy process output separately order obtain least PCA , even knn graph (essential compute clusters). Note scores computed knn graphs, hence knn graph outputs (e.g. BBKNN) can evaluated reduced set metrics. summary post-processing steps output type (bracketed steps always necessary): corrected counts: [ScaleData()] -> RunPCA() -> [FindNeighbors() -> FindOptimalClusters()] dimension reduction: [RunPCA()] -> [FindNeighbors() -> FindOptimalClusters()] knn graph: [FindOptimalClusters()] RunPCA() sometimes run even dimension reduction objects (within scoring functions) scores require variance associated dimension. Let’s process outputs. , go steps exhaustive demonstration. However, noted skipping final step FindOptimalClusters() makes neighbour graph computation step (FindNeighbors()) unnecessary. case however, one forgo two scoring metrics, namely ARI NMI. , use SymmetrizeKnn() FindNeighbors() FindOptimalClusters() set return.neighbor = TRUE FindNeighbors(). useful keep distances cells KNN graph rather FindNeighbors() default, converting KNN graph adjacency matrix 0/1s SNN network values bounded 0 1. compulsory, used stay line BBKNN’s output. prevent community detection algorithm output high fraction singletons, “symmetrize” matrix makes graph “undirected”. Note: Instead sticking default FindNeighbors(return.neighbors = FALSE) beginning, switched TRUE right away, process KNN graph SymmetrizeKnn() use subsequent steps (umap, clustering, etc.) FindOptimalClusters() adds metadata columns clustering results maximized metric (NMI ARI) Seurat object:","code":"# corrected counts outputs DefaultAssay(seu) <- \"scanorama.reconstructed\" seu <- ScaleData(seu) seu <- RunPCA(seu, npcs = 50L, reduction.name = \"pca.scanorama_counts\") seu <- FindNeighbors(seu, reduction = \"pca.scanorama_counts\", dims = 1:30, return.neighbor = TRUE, graph.name = \"knn.scanorama_counts\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.scanorama_counts\") seu <- FindOptimalClusters(seu, graph.name = \"knn.scanorama_counts_symmetric\", cluster.name = \"scanorama_counts_{cell.var}_{metric}\", cell.var = cell.var, optimisation.metric = c(\"nmi\", \"ari\")) # default, compute both # dimension reduction outputs DefaultAssay(seu) <- \"SCT\" seu <- FindNeighbors(seu, reduction = \"pca\", dims = 1:30, k.param = 20L, return.neighbor = TRUE, graph.name = \"knn.unintegrated\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.unintegrated\") seu <- FindOptimalClusters(seu, graph.name = \"knn.unintegrated_symmetric\", cluster.name = \"unintegrated_{cell.var}_{metric}\", cell.var = cell.var) seu <- FindNeighbors(seu, reduction = \"integrated.scanorama\", dims = 1:30, return.neighbor = TRUE, graph.name = \"knn.scanorama_reduction\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.scanorama_reduction\") seu <- FindOptimalClusters(seu, graph.name = \"knn.scanorama_reduction_symmetric\", cluster.name = \"scanorama_reduction_{cell.var}_{metric}\", cell.var = cell.var) seu <- FindNeighbors(seu, reduction = \"harmony\", dims = 1:30, return.neighbor = TRUE, graph.name = \"knn.harmony\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.harmony\") seu <- FindOptimalClusters(seu, graph.name = \"knn.harmony_symmetric\", cell.var = cell.var, cluster.name = \"harmony_{cell.var}_{metric}\") seu <- FindNeighbors(seu, reduction = \"cca.integrated\", dims = 1:30, return.neighbor = TRUE, graph.name = \"knn.cca\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.cca\") seu <- FindOptimalClusters(seu, graph.name = \"knn.cca_symmetric\", cell.var = cell.var, cluster.name = \"cca_{cell.var}_{metric}\") seu <- FindNeighbors(seu, reduction = \"rpca.integrated\", dims = 1:30, return.neighbor = TRUE, graph.name = \"knn.rpca\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.rpca\") seu <- FindOptimalClusters(seu, graph.name = \"knn.rpca_symmetric\", cell.var = cell.var, cluster.name = \"rpca_{cell.var}_{metric}\") seu <- FindNeighbors(seu, reduction = \"integrated.scANVI\", return.neighbor = TRUE, graph.name = \"knn.scanvi\") seu <- SymmetrizeKnn(seu, graph.name = \"knn.scanvi\") seu <- FindOptimalClusters(seu, graph.name = \"knn.scanvi_symmetric\", cell.var = cell.var, cluster.name = \"scanvi_{cell.var}_{metric}\") # graph outputs seu <- SymmetrizeKnn(seu, graph.name = \"bbknn_ridge.residuals_distances\") seu <- FindOptimalClusters(seu, graph.name = \"bbknn_ridge.residuals_distances_symmetric\", cell.var = cell.var, cluster.name = \"bbknn_{cell.var}_{metric}\") rmarkdown::paged_table(seu[[]][1:10, grep(\"CellType_[arinm]{3}$\", colnames(seu[[]]))])"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"add-scores-to-the-seurat-object","dir":"Articles","previous_headings":"Score integrations","what":"Add scores to the Seurat object","title":"Integration example with of the pbmcsca data","text":"Now computed objects ready scored, proceed assessing integration output. step, one can either use Score[score_name]() save scores separate variables use AddScore[score_name]() directly store scores within Seurat object. latter far convenient allows compare scores graphically. strategy going adopt . Last least, cell-type variable used scores, hence highly recommended estimate cell’s type (produce estimate) stored Seurat object column metadata. Note one doesn’t variable cell-labels (used ground truth multiple scores) produce without several scores. Alternatively, one can use automatic cell annotation algorithms (e.g. Azimuth package). One can also multiple cell label variables (e.g. Azimuth typically returns many cell label variables levels annotations contained reference). Scores requiring cell type annotations always accept multiple column names. risk confusion cell annotations using automatic cell annotation tools. Furthermore, case using Azimuth annotate cells, specific risk biasing results favouring RPCA integration Azimuth uses RPCA integrate query dataset onto reference. First , let’s organise outputs lists: Let’s finalise preparations: : Make sure kBET package installed run ScoreKBET() benefit faster implementation lisi algorithm, install lisi package benefit faster implementation euclidean distance computation, install distances package run ScoreRegressPC.CellCycle() (score cell cycle conservation), run CellCycleScoringPerBatch() beforehand (next chunk) Let’s now loop integration outputs: Now computed multiple scores, can look using IntegrationScores():","code":"reductions <- list( unintegrated = \"pca\", scanorama_counts = \"pca.scanorama_counts\", scanorama_reduction = \"integrated.scanorama\", harmony = \"harmony\", cca = \"cca.integrated\", rpca = \"rpca.integrated\", scanvi = \"integrated.scANVI\", bbknn = NULL ) graphs <- list( unintegrated = \"knn.unintegrated_symmetric\", scanorama_counts = \"knn.scanorama_counts_symmetric\", scanorama_reduction = \"knn.scanorama_reduction_symmetric\", harmony = \"knn.harmony_symmetric\", cca = \"knn.cca_symmetric\", rpca = \"knn.rpca_symmetric\", scanvi = \"knn.scanvi_symmetric\", bbknn = \"bbknn_ridge.residuals_distances_symmetric\" ) integrations <- names(reductions) seu <- CellCycleScoringPerBatch(seu, batch.var = batch.var, s.features = cc.genes$s.genes, g2m.features = cc.genes$g2m.genes) for (integ in integrations) { reduc <- reductions[[integ]] graph <- graphs[[integ]] clust.var.ari <- paste(integ, cell.var, \"ari\", sep = \"_\") # produced by `FindOptimalClusters()` clust.var.nmi <- paste(integ, cell.var, \"nmi\", sep = \"_\") # produced by `FindOptimalClusters()` if (! is.null(reduc)) { # all TRUE except bbknn seu <- AddScoreASW(seu, integration = integ, cell.var = cell.var, what = reduc, dist.package = \"distances\") seu <- AddScoreASWBatch(seu, integration = integ, batch.var = batch.var, cell.var = cell.var, what = reduc, dist.package = \"distances\") seu <- AddScoreDensityPC(seu, integration = integ, batch.var = batch.var, reduction = reduc) seu <- AddScoreRegressPC(seu, integration = integ, batch.var = batch.var, reduction = reduc) seu <- AddScoreRegressPC.CellCycle(seu, integration = integ, batch.var = batch.var, what = reduc, compute.cc = FALSE) # because CellCycleScoringPerBatch was ran before } seu <- AddScoreARI(seu, integration = integ, cell.var = cell.var, clust.var = clust.var.ari) seu <- AddScoreNMI(seu, integration = integ, cell.var = cell.var, clust.var = clust.var.nmi) seu <- AddScoreConnectivity(seu, integration = integ, graph.name = graph, cell.var = cell.var) seu <- AddScoreKBET(seu, integration = integ, batch.var = batch.var, cell.var = cell.var, what = reduc %||% sub(\"_symmetric$\", \"\", graph), graph.type = \"distances\", verbose = FALSE) seu <- AddScoreLISI(seu, integration = integ, batch.var = batch.var, cell.var = cell.var, reduction = reduc, graph.name = if (is.null(reduc)) sub(\"_symmetric$\", \"\", graph) else NULL, graph.type = \"distances\", ncores = ncores) } rmarkdown::paged_table(IntegrationScores(seu))"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/introduction.html","id":"compare-the-integrations","dir":"Articles","previous_headings":"Score integrations","what":"Compare the integrations","title":"Integration example with of the pbmcsca data","text":"Note scores raw. Let’s scale (make comparable): , can print : readily compare integrations, let’s plot scores: One might notice difference scale scores, comparing plot table just . case PCA density score instance. Indeed, PlotScores() rescales scores using min-max normalisation default (rescale = TRUE). One might chose disable : notice PCA based methods output low scores case. Since computed knn graphs, scores biased favour BBKNN. can exclude scores (recompute overall scores fly) can chose different type plot (radar lollipop): last plot, also exclude non-integrated dataset. Since rescale argument true default, scores rescaled without excluded integration’s scores. want compare UMAP embeddings. , first compute dimension reductions: BBKNN’s output graph, need use umap Python package: several observations made , require explanations: cells seem assigned wrong label CellType, highlighting importance cell annotations sufficient quality considered suitable ground truth (actually case ) scaled PCA regression scores set zero. unintegrated dataset lowest raw PCA regression score. likely consequence SCT normalisation, much efficient masking batch-specific differences classical LogNorm. Thus, inter-batch differences driving principal components. ScaleScores() produce scores can different scales (long rescale = FALSE) . Thus, min-max rescaling used default PlotScores(), balance score’s contribution overall scores. especially suited comparing large number integrations. However, drawbacks: can heavily distort scale scores maximum minimum far 1 0 respectively (e.g. cLISI scores 0.9). Hence, final decision whether use min-max rescaling left user’s discretion.","code":"seu <- ScaleScores(seu) rmarkdown::paged_table(IntegrationScores(seu, scaled = TRUE)) PlotScores(seu) print(sort(IntegrationScores(seu, scaled = TRUE)$PCA.density)) ## [1] 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.05713768 0.12268377 PlotScores(seu, rescale = FALSE) PlotScores(seu, rescale = FALSE, exclude.score = c(\"pca.density\", \"pca.regression\")) library(ggplot2) PlotScores(seu, plot.type = \"radar\") + # reduce overlap between axis names and figures theme(legend.position = \"top\", panel.spacing = unit(3, \"cm\"), plot.margin = margin(r = 3, l = 3, unit = \"cm\"), axis.text.x = element_text(size = 10)) ## Warning: Removed 5 rows containing missing values or values outside the scale range ## (`geom_point()`). PlotScores(seu, plot.type = \"lollipop\", exclude.integration = \"unintegrated\") ## Warning: Removed 5 rows containing missing values or values outside the scale range ## (`geom_point()`). ## Warning: Removed 5 rows containing missing values or values outside the scale range ## (`geom_errorbarh()`). for (integ in integrations) { reduc <- reductions[[integ]] if (! is.null(reduc)) { # all except BBKNN seu <- RunUMAP(seu, dims = 1:min(30, ncol(seu[[reduc]])), reduction = reduc, reduction.name = paste0(integ, \".umap\")) } } if (! reticulate::condaenv_exists('umap_0.5.4')) { reticulate::conda_create('umap_0.5.4', packages = 'umap=0.5.4') } library(future) plan(multisession) seu %<-% { reticulate::use_condaenv('umap_0.5.4') RunUMAP(seu, graph = \"bbknn_ridge.residuals_connectivities\", umap.method = \"umap-learn\", n.epochs = 200L, reduction.name = \"bbknn.umap\") } seu plan(sequential) library(ggplot2) plot_list <- sapply(integrations, function(integ) { DimPlot(seu, reduction = paste0(integ, \".umap\"), group.by = batch.var) + ggtitle(integ) + theme(axis.title = element_blank()) }, simplify = FALSE) patchwork::wrap_plots(plot_list, guides = \"collect\") library(ggplot2) plot_list <- sapply(integrations, function(integ) { DimPlot(seu, reduction = paste0(integ, \".umap\"), group.by = cell.var) + ggtitle(integ) + theme(axis.title = element_blank()) }, simplify = FALSE) patchwork::wrap_plots(plot_list, guides = \"collect\") ## R version 4.4.2 (2024-10-31) ## Platform: x86_64-pc-linux-gnu ## Running under: Linux Mint 21 ## ## Matrix products: default ## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0 ## ## locale: ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 ## [5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=en_US.UTF-8 ## [7] LC_PAPER=fr_FR.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C ## ## time zone: Europe/Paris ## tzcode source: system (glibc) ## ## attached base packages: ## [1] stats graphics grDevices utils datasets methods base ## ## other attached packages: ## [1] future_1.34.0 ggplot2_3.5.1 SeuratIntegrate_0.4.0 ## [4] Seurat_5.1.0 SeuratObject_5.0.2 sp_2.1-4 ## ## loaded via a namespace (and not attached): ## [1] fs_1.6.5 matrixStats_1.4.1 ## [3] spatstat.sparse_3.1-0 httr_1.4.7 ## [5] RColorBrewer_1.1-3 tools_4.4.2 ## [7] sctransform_0.4.1 backports_1.5.0 ## [9] R6_2.5.1 ResidualMatrix_1.14.1 ## [11] lazyeval_0.2.2 uwot_0.2.2 ## [13] mgcv_1.9-1 withr_3.0.2 ## [15] gridExtra_2.3 progressr_0.15.1 ## [17] cli_3.6.3 Biobase_2.64.0 ## [19] textshaping_0.4.1 spatstat.explore_3.3-3 ## [21] fastDummies_1.7.4 labeling_0.4.3 ## [23] sass_0.4.9 spatstat.data_3.1-4 ## [25] genefilter_1.86.0 ggridges_0.5.6 ## [27] pbapply_1.7-2 pkgdown_2.1.1 ## [29] systemfonts_1.1.0 hcabm40k.SeuratData_3.0.0 ## [31] harmony_1.2.3 parallelly_1.41.0 ## [33] limma_3.60.6 rstudioapi_0.17.1 ## [35] RSQLite_2.3.9 FNN_1.1.4.1 ## [37] generics_0.1.3 ica_1.0-3 ## [39] spatstat.random_3.3-2 dplyr_1.1.4 ## [41] Matrix_1.7-1 S4Vectors_0.42.1 ## [43] abind_1.4-8 lifecycle_1.0.4 ## [45] yaml_2.3.10 edgeR_4.2.2 ## [47] SummarizedExperiment_1.34.0 SparseArray_1.4.8 ## [49] Rtsne_0.17 glmGamPoi_1.16.0 ## [51] grid_4.4.2 blob_1.2.4 ## [53] ifnb.SeuratData_3.1.0 promises_1.3.2 ## [55] crayon_1.5.3 miniUI_0.1.1.1 ## [57] lattice_0.22-6 beachmat_2.20.0 ## [59] cowplot_1.1.3 annotate_1.82.0 ## [61] KEGGREST_1.44.1 pillar_1.10.0 ## [63] knitr_1.49 GenomicRanges_1.56.2 ## [65] kBET_0.99.6 future.apply_1.11.3 ## [67] codetools_0.2-20 leiden_0.4.3.1 ## [69] glue_1.8.0 spatstat.univar_3.1-1 ## [71] data.table_1.16.4 vctrs_0.6.5 ## [73] png_0.1-8 spam_2.11-0 ## [75] gtable_0.3.6 cachem_1.1.0 ## [77] xfun_0.49 S4Arrays_1.4.1 ## [79] mime_0.12 survival_3.8-3 ## [81] pbmcref.SeuratData_1.0.0 SingleCellExperiment_1.26.0 ## [83] statmod_1.5.0 fitdistrplus_1.2-1 ## [85] ROCR_1.0-11 nlme_3.1-166 ## [87] bit64_4.5.2 RcppAnnoy_0.0.22 ## [89] GenomeInfoDb_1.40.1 bslib_0.8.0 ## [91] irlba_2.3.5.1 KernSmooth_2.23-24 ## [93] colorspace_2.1-1 BiocGenerics_0.50.0 ## [95] DBI_1.2.3 tidyselect_1.2.1 ## [97] bit_4.5.0.1 compiler_4.4.2 ## [99] BiocNeighbors_1.22.0 desc_1.4.3 ## [101] DelayedArray_0.30.1 plotly_4.10.4 ## [103] scales_1.3.0 lmtest_0.9-40 ## [105] distances_0.1.11 rappdirs_0.3.3 ## [107] stringr_1.5.1 digest_0.6.37 ## [109] goftest_1.2-3 spatstat.utils_3.1-1 ## [111] rmarkdown_2.29 XVector_0.44.0 ## [113] RhpcBLASctl_0.23-42 htmltools_0.5.8.1 ## [115] pkgconfig_2.0.3 sparseMatrixStats_1.16.0 ## [117] MatrixGenerics_1.16.0 fastmap_1.2.0 ## [119] rlang_1.1.4 htmlwidgets_1.6.4 ## [121] UCSC.utils_1.0.0 shiny_1.10.0 ## [123] DelayedMatrixStats_1.26.0 farver_2.1.2 ## [125] jquerylib_0.1.4 zoo_1.8-12 ## [127] jsonlite_1.8.9 BiocParallel_1.38.0 ## [129] BiocSingular_1.20.0 magrittr_2.0.3 ## [131] scuttle_1.14.0 GenomeInfoDbData_1.2.12 ## [133] dotCall64_1.2 patchwork_1.3.0 ## [135] pbmcsca.SeuratData_3.0.0 munsell_0.5.1 ## [137] Rcpp_1.0.13-1 reticulate_1.40.0 ## [139] stringi_1.8.4 zlibbioc_1.50.0 ## [141] MASS_7.3-61 plyr_1.8.9 ## [143] parallel_4.4.2 listenv_0.9.1 ## [145] ggrepel_0.9.6 forcats_1.0.0 ## [147] deldir_2.0-4 Biostrings_2.72.1 ## [149] splines_4.4.2 tensor_1.5 ## [151] locfit_1.5-9.10 lisi_1.0 ## [153] bonemarrowref.SeuratData_1.0.0 igraph_2.1.2 ## [155] spatstat.geom_3.3-4 heartref.SeuratData_1.0.0 ## [157] RcppHNSW_0.6.0 reshape2_1.4.4 ## [159] stats4_4.4.2 ScaledMatrix_1.12.0 ## [161] XML_3.99-0.17 evaluate_1.0.1 ## [163] tweenr_2.0.3 httpuv_1.6.15 ## [165] batchelor_1.20.0 bmcite.SeuratData_0.3.0 ## [167] RANN_2.6.2 tidyr_1.3.1 ## [169] purrr_1.0.2 polyclip_1.10-7 ## [171] SeuratData_0.2.2.9001 scattermore_1.2 ## [173] ggforce_0.4.2 rsvd_1.0.5 ## [175] broom_1.0.7 xtable_1.8-4 ## [177] RSpectra_0.16-2 later_1.4.1 ## [179] viridisLite_0.4.2 ragg_1.3.3 ## [181] tibble_3.2.1 memoise_2.0.1 ## [183] AnnotationDbi_1.66.0 IRanges_2.38.1 ## [185] cluster_2.1.8 sva_3.52.0 ## [187] globals_0.16.3"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"introduction","dir":"Articles","previous_headings":"","what":"Introduction","title":"Generic advice about setting up and using conda environments","text":"SeuratIntegrate’s main purpose extend range scRNA-seq integration tools available R compatible Seurat. Many solely available Python, developed wrappers leveraging reticulate package’s capabilities. reticulate enables directly call Python R, give conda environments set beforehand. purpose vignette illustrate ease installation use environments. Prior starting, make sure : conda installed machine conda binary PATH (know location)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"set-up","dir":"Articles","previous_headings":"","what":"Set-up","title":"Generic advice about setting up and using conda environments","text":"need multiple conda environments. One bbknn, one Scanorama, one scVI/scANVI one trVAE. don’t plan using methods, whether decide set respective conda environments . One contrary, already conda environments appropriate libraries machine, can tell SeuratIntegrate use . Let’s see . look CondaEnvManager: ’s handy way glance implemented methods status conda environments. ComBat, Harmony MNN R-based methods don’t need conda environment. rest however Python-based function reticulate, hence require conda environments. don’t conda environments , look next sub-section. Conversely, want add existing conda environment, directly go following one.","code":"library(SeuratIntegrate) getCache()"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"create_env","dir":"Articles","previous_headings":"Set-up","what":"Option 1: Create new conda environments with SeuratIntegrate","title":"Generic advice about setting up and using conda environments","text":"Note commands tested Linux distributions Try following commands (aware execution might take time): Note : conda PATH set conda.bin = /path//conda scVI scANVI share environment. Hence, necessary run UpdateEnvCache('scvi') UpdateEnvCache('scanvi') look CondaEnvManager:","code":"UpdateEnvCache('bbknn') UpdateEnvCache('scvi') UpdateEnvCache('scanorama') UpdateEnvCache('trvae') getCache()"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"use_env","dir":"Articles","previous_headings":"Set-up","what":"Option 2: Use existing conda environments","title":"Generic advice about setting up and using conda environments","text":"already one (several) existing conda environment(s) one () methods, can tell SeuratIntegrate use (). Similarly, run problems UpdateEnvCache() commands , alternative set conda environments provide SeuratIntegrate. Whatever case, let’s proceed. ’ll use UpdateEnvCache(). can specify name conda environment path . default, UpdateEnvCache() try decide whether provided value conda.env path name based simple tests. avoid misinterpretation, can use conda.env..path = TRUE FALSE input path name environment, respectively. beware make mistakes !!! See examples . adapt arguments situation: Note : conda PATH set conda.bin = /path//conda conda.bin must correspond conda managing conda.env scVI scANVI share environment. Hence, necessary run UpdateEnvCache('scvi') UpdateEnvCache('scanvi') Now can use Python-based methods !","code":"# environment for bbknn UpdateEnvCache('bbknn', conda.env = 'bbknn_env', conda.env.is.path = FALSE) # default 'auto' would work # environment for bbknn in ./bbknn_env/ UpdateEnvCache('bbknn', conda.env = 'bbknn_env', conda.env.is.path = TRUE) # environment for bbknn, conda binary not in PATH UpdateEnvCache('bbknn', conda.env = 'bbknn_env', conda.bin = 'cutom/location/conda') # path for scvi-tools UpdateEnvCache('scvi', conda.env = '~/miniconda3/envs/scvi-tools_env', conda.env.is.path = TRUE) # default 'auto' would work"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"update-or-reset-conda-environments","dir":"Articles","previous_headings":"Set-up","what":"Update or reset conda environments","title":"Generic advice about setting up and using conda environments","text":"want update conda environment, use unset environment, use","code":"# change 'method' by the name of the method UpdateEnvCache(method = 'method', overwrite.env = TRUE, ...) # change 'method' by the name of the method resetCache(method = 'method')"},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"install_problem","dir":"Articles","previous_headings":"Troubleshouting with conda","what":"Common issues with setting up environments","title":"Generic advice about setting up and using conda environments","text":"can happen conda environment installed specific machine os. case, hardly anything better browse internet hope someone else experienced similar problem solution public. Otherwise, try modify set packages install, less stringent package versions install, etc. can also create conda environment Python pip, try install packages pip rather conda. problem solved (can ), can save new environment CondaEnvManager ","code":"# change 'method' by the name of the method # change'difficult_conda_env' by the name of the working conda environment UpdateEnvCache(method = 'method', conda.env = 'difficult_conda_env')"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"load_problem","dir":"Articles","previous_headings":"Troubleshouting with conda","what":"Possible issues with activating environments","title":"Generic advice about setting up and using conda environments","text":"can happen conda environment work (stops working) specific machine. potential causes conflicts Python libraries, conda components lead malfunctions (non exhaustive list): rmarkdown/knitr Check command works outside rmarkdown (e.g. R script), closed Rmardown file closed R session (restrated RStudio). something consider notably encounter error like: RStudio Check command works outside RStudio. instance, error integration scanpy imported, try: reticulate Check conda environment loads properly pure Python session. instance, error integration scanpy imported, try : First, try update reticulate. doesn’t work better, check someone encountered issue (browse web issues reticulate github repository. nothing works, either post issue reticulate github repos retry import installed different Python package versions. Python packages tricky. packages know incompatible. instance, jax jaxlib work better versions identical. experience, scvi-tools environment can set two discrepant versions jax jaxlib. check, try: local os list packages installed SeuratIntegrate","code":"ImportError: /opt/conda/envs/[env_name]/lib/python3.10/site-packages/PIL/../../../libtiff.so.6: undefined symbol: jpeg12_write_raw_data, version LIBJPEG_8.0 # from a terminal R > library(reticulate) > use_condaenv('[conda_env_name]') > scanpy <- import(\"scanpy\", convert = FALSE) # error here ? > conda activate [conda_env_name] python >>> import scanpy # error here ? >>> conda list -n [conda_env_name] jax"},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"subtleties-of-using-future","dir":"Articles","previous_headings":"","what":"Subtleties of using Future","title":"Generic advice about setting up and using conda environments","text":"following bullet points seem obscure, explanations given sections . brief, disable future R-based methods (DoIntegrate([...], use.future = FALSE)) never use CCA RPCA integration methods multisession (previous advice prevents , especially Windows users) multicore futures faster less memory-intensive multisession, unstable RStudio unavailable Windows force DoIntegrate() use multicore framework (risk), set options(parallelly.fork.enable = FALSE). Unavailable Windows","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"why-seuratintegrate-uses-future","dir":"Articles","previous_headings":"Subtleties of using Future","what":"Why SeuratIntegrate uses Future ?","title":"Generic advice about setting up and using conda environments","text":"R session can initialise one Python environment time via reticulate. known limitation reticualte overcome launching “background session” using Future. environment initialised instead main user’s R session. feature embedded DoIntegrate(). Futures therefore useless R-based methods disabled DoIntegrate([...], use.future = FALSE). Worse, discouraged CCAIntegration RPCAIntegration (explanations final part vignette)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"inconveniences","dir":"Articles","previous_headings":"Subtleties of using Future","what":"Inconveniences","title":"Generic advice about setting up and using conda environments","text":"vast majority cases, impact “futures” insignificant. obvious needed seconds launch future session export globals, addition reordering stdout message output, resulting messy less informative print statements intended user.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html","id":"tweaks","dir":"Articles","previous_headings":"Subtleties of using Future","what":"Tweaks","title":"Generic advice about setting up and using conda environments","text":"package implements sequential, multicore, multisession, cluster futures. SeuratIntegrate uses multicore multisession ones. DoIntegrate() automatically picks preferred one based output multicore supported, thus DoIntegrate() start multisession. explanations regarding settings giving priority multicore available function’s help (important part disclosure widget ?supportsMulticore) R supports forked processing Unix-like operating system Linux macOS, Microsoft Windows operating system. R environments considered unstable perform parallel processing based forking. example case using RStudio, cf. RStudio Inc. recommends using forked processing running R within RStudio software. function detects running environment returns FALSE, despite underlying operating system supports forked processing. warning also produced informing user first time time function called R session. warning can disabled setting R option parallelly.supportsMulticore.unstable, environment variable R_PARALLELLY_SUPPORTSMULTICORE_UNSTABLE \"quiet\". possible disable forked processing futures setting R option parallelly.fork.enable FALSE. Alternatively, one can set environment variable R_PARALLELLY_FORK_ENABLE false. Analogously, possible override disabled forking setting one TRUE. nutshell, multicore unavailable Windows discouraged (considered unstable) R environments, notably RStudio always used Unix-like operating systems options(parallelly.fork.enable = TRUE) main reason using multicore FORKing considered faster result lower memory overhead PSOCK (.e. multisession) (see technical details) Furthermore, DoIntegrate() uses future, also NSE (non-standard evaluation), enabling specify arguments within integration function call. Briefly, call inside DoIntegrate() (DoIntegrate(bbknnIntegration())) directly executed captured executed later (proper value object parameter can passed bbknnIntegration instance). details available book Advanced R Hadley Wickham. important part , unlike multicore, multisession future, DoIntegrate() evaluates argument launching integration background R session. Thus, Seurat Assay object passed structure (output str(object)). takes time makes call extremely long. unexpected side-effect. slows CCAIntegration RPCAIntegration lot input Seurat objects normalised SCTransform(). Indeed, call FindIntegrationAnchors() -> merge() -> merge.SCTAssay(). latter performs grep previous calls (output sys.calls()). multisession future, big objects Seurat Assay object passed structure grep can unnecessarily time-consuming. avoid , one can either specify use.future = FALSE R-based method (always preferable) least ban use CCA RPCA integrations multisession future (note Windows users can pick first option).","code":"parallelly::supportsMulticore() ## [1] FALSE help('supportsMulticore', package = 'parallelly')"},{"path":"https://cbib.github.io/Seurat-Integrate/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Florian Specque. Author, maintainer. Domitille Chalopin. Author. Macha Nikolski. Reviewer. Aurélien Barré. Contributor. Centre de Bioinformatique de Bordeaux (CBiB). Copyright holder.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Specque F, Chalopin D (2025). SeuratIntegrate: Expands set integration methods available Seurat. R package version 0.4.0, https://cbib.github.io/Seurat-Integrate/, https://github.com/cbib/Seurat-Integrate.","code":"@Manual{, title = {SeuratIntegrate: Expands the set of integration methods available to Seurat}, author = {Florian Specque and Domitille Chalopin}, year = {2025}, note = {R package version 0.4.0, https://cbib.github.io/Seurat-Integrate/}, url = {https://github.com/cbib/Seurat-Integrate}, }"},{"path":"https://cbib.github.io/Seurat-Integrate/index.html","id":"seuratintegrate","dir":"","previous_headings":"","what":"Expands the set of integration methods available to Seurat","title":"Expands the set of integration methods available to Seurat","text":"SeuratIntegrate streamlines single-cell transcriptomics (scRNA-seq) data integration batch effect correction. R package effortlessly extends Seurat workflow 8 popular integration methods across R Python, complemented 11 robust scoring metrics estimate performance. Integrations ComBat Harmony MNN BBKNN scVI scANVI Scanorama trVAE Scoring metrics ARI ASW Batch ASW Cell cycle conservation Graph connectivity PCA-density PCA-regression kBET cell-type (c)LISI batch ()LISI NMI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Expands the set of integration methods available to Seurat","text":"Install SeuratIntegrate github: benefit SeuratIntegrate’s full capabilities, recommend installing following packages:","code":"install.packages(c(\"remotes\", \"BiocManager\")) # if not installed remotes::install_github(\"cbib/Seurat-Integrate\", repos = BiocManager::repositories()) # fast distance computation install.packages('distances') # required to test for k-nearest neighbour batch effects remotes::install_github('theislab/kBET') # faster Local Inverse Simpson’s Index computation remotes::install_github('immunogenomics/lisi')"},{"path":"https://cbib.github.io/Seurat-Integrate/index.html","id":"conda-environments-for-python-methods","dir":"","previous_headings":"","what":"Conda environments for Python methods","title":"Expands the set of integration methods available to Seurat","text":"simplify creation management conda environments, suggest using UpdateEnvCache(): environments saved automatically used Python integration methods provided SeuratIntegrate. Alternatively, cache can updated pre-existing environment. can useful set conda environment command failed conda environment turned non-functional. cache remains persistent across sessions state can displayed : details provided vignette(\"setup_and_tips\").","code":"# create environments: UpdateEnvCache(\"bbknn\") UpdateEnvCache(\"scvi\") UpdateEnvCache(\"scanorama\") UpdateEnvCache(\"trvae\") # save \"my_bbknn_env\" (for bbknn) to cache UpdateEnvCache(\"bbknn\", conda.env = \"my_bbknn_env\") getCache()"},{"path":"https://cbib.github.io/Seurat-Integrate/index.html","id":"data-integration","dir":"","previous_headings":"","what":"Data integration","title":"Expands the set of integration methods available to Seurat","text":"run integration algorithms, developed function called DoIntegrate() enables: performing multiple integration methods single call control data (raw, normalised scaled) features use input flexible customisation parameters integration method , integration methods use variable features input, exception scVIIntegration() set use features. CombatIntegration() correct normalised counts, scVIIntegration() train raw counts. use.future must TRUE Python methods, FALSE R methods. Integration methods produce one several outputs. can multiple types - either new assay corrected counts, new dimension reduction corrected cell embeddings, new graph corrected edges. type output important consider, require different post-processing steps result integration can visualised UMAP: Corrected counts: ScaleData() -> RunPCA() -> RunUMAP() Dimension reduction: RunUMAP() KNN graph: RunUMAP(umap.method = \"umap-learn\")","code":"seu <- DoIntegrate(seu, # ... integrations CombatIntegration(layers = \"data\"), HarmonyIntegration(orig = \"pca\", dims = 1:30), ScanoramaIntegration(ncores = 4L, layers = \"data\"), scVIIntegration(layers = \"counts\", features = Features(seu)), # ... use.hvg = TRUE, # `VariableFeatures()` use.future = c(FALSE, FALSE, TRUE, TRUE) )"},{"path":"https://cbib.github.io/Seurat-Integrate/index.html","id":"scoring","dir":"","previous_headings":"","what":"Scoring","title":"Expands the set of integration methods available to Seurat","text":"SeuratIntegrate incorporates 11 scoring metrics: 6 quantify degree batch mixing (batch correction), 5 assess preservation biological differences (bio-conservation) based ground truth cell type labels. score can obtained using function form Score[score_name](), directly saved Seurat object using AddScore[score_name]() counterpart: AddScore functions advantage Score functions. allow scale scores zero one standardize direction (closer one, always better), improving interpretability. , scores can plotted readily compare different integrations:","code":"# save the score in a variable rpca_score <- ScoreRegressPC(seu, reduction = \"pca\") # or save the score in the Seurat object seu <- AddScoreRegressPC(seu, integration = \"unintegrated\", reduction = \"pca\") # scale seu <- ScaleScores(seu) # plot PlotScores(seu)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CellCycleScoringPerBatch.html","id":null,"dir":"Reference","previous_headings":"","what":"Score cell cycle phases per batch — CellCycleScoringPerBatch","title":"Score cell cycle phases per batch — CellCycleScoringPerBatch","text":"Assign cell cycle scores cells. Scores computed batch independantly.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CellCycleScoringPerBatch.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score cell cycle phases per batch — CellCycleScoringPerBatch","text":"","code":"CellCycleScoringPerBatch( object, batch.var = NULL, s.features, g2m.features, ctrl = NULL, assay = NULL, layer = NULL, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CellCycleScoringPerBatch.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score cell cycle phases per batch — CellCycleScoringPerBatch","text":"object Seurat object batch.var name batch variable (must object metadata) s.features vector features associated S phase g2m.features vector features associated G2M phase ctrl Number control features selected bin per analyzed feature supplied AddModuleScore. Defaults value equivalent minimum number features present 's.features' 'g2m.features'. assay assay use. Passed Seurat automatically construct batch.var provided. Useless otherwise layer layer use. Passed Seurat automatically construct batch.var provided. Useless otherwise ... Arguments passed CellCycleScoring, AddModuleScore (exception set.ident always FALSE)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CellCycleScoringPerBatch.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score cell cycle phases per batch — CellCycleScoringPerBatch","text":"Seurat object following columns added object meta data: S.Score, G2M.Score, Phase","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CellCycleScoringPerBatch.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Score cell cycle phases per batch — CellCycleScoringPerBatch","text":"","code":"if (FALSE) { # \\dontrun{ obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- CellCycleScoringPerBatch(obj, batch.var = 'Method', s.features = cc.genes.updated.2019$s.genes, g2m.features = cc.genes.updated.2019$g2m.genes) head(obj[[]]) } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"wrapper run ComBat ComBat_seq multi-layered Seurat V5 object","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"","code":"CombatIntegration( object, orig = NULL, groups = NULL, groups.name = NULL, layers = \"data\", scale.layer = \"scale.data\", features = NULL, reconstructed.assay = \"combat.reconstructed\", key.assay = \"combat_\", combat.function = c(\"combat\", \"combat_seq\"), use.scaled = FALSE, verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) orig DimReduc object. set directly called IntegrateLayers, use orig.reduction argument instead groups named data frame grouping information. Preferably one-column groups.name = NULL groups.name Column name groups data frame stores grouping information. groups.name = NULL, first column used layers Name layers use integration scale.layer Name scaled layer Assay features Vector feature names input integration method. features = NULL (default), VariableFeatures used. pass features, use output Features() reconstructed.assay Name assay containing corrected expression matrix key.assay Optional key new combat assay. Format: \"[:alnum:]*_\" combat.function ComBat implementation use. One combat, combat_seq. Note ComBat_seq improved model ComBat requires dense matrix. Sparse dense matrix conversion can memory-intensive. use.scaled default layer passed layer argument used. use.scaled = TRUE, scale.layer input ComBat. verbose Print messages. Set FALSE disable ... Additional arguments passed ComBat ComBat_seq.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"function returns list containing: new Assay name reconstructed.assay (key set assay.key) corrected cell counts. called via IntegrateLayers, Seurat object new assay returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"function requires sva (Surrogate Variable Analysis) package installed","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"Johnson, W. E., Li, C. & Rabinovic, . Adjusting batch effects microarray expression data using empirical Bayes methods. Biostatistics 8, 118–127 (2006). DOI Zhang, Y., Parmigiani, G. & Johnson, W. E. ComBat-seq: batch effect adjustment RNA-seq count data. NAR Genomics Bioinformatics 2 (2020). DOI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run ComBat on Seurat's Assay5 object through IntegrateLayers — CombatIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- UpdateSeuratObject(SeuratData::LoadData(\"pbmcsca\")) obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers based on the \"Method\" variable: obj <- IntegrateLayers(object = obj, method = CombatIntegration, verbose = TRUE, layers = \"data\", scale.layer = NULL, features = VariableFeatures( FindVariableFeatures(obj, nfeatures = 5e3) )) # We can also change parameters such as the input data. # Here we use the scale data, the ComBat implementation and we use the cell # labels as a \"biological condition of interest\" (/!\\ long): obj <- IntegrateLayers(object = obj, method = CombatIntegration, verbose = TRUE, features = VariableFeatures(obj), use.scaled = FALSE, combat.function = 'combat_seq', group = obj[[]]$CellType, groups = obj[[]], groups.name = \"Method\", layers = \"counts\") } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnv-class.html","id":null,"dir":"Reference","previous_headings":"","what":"Encapsulates information about a conda environment — CondaEnv-class","title":"Encapsulates information about a conda environment — CondaEnv-class","text":"CondaEnv class provides basic structure store information conda environment given method. designed used CondaEnvManager class.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnv-class.html","id":"slots","dir":"Reference","previous_headings":"","what":"Slots","title":"Encapsulates information about a conda environment — CondaEnv-class","text":"method 1-length character. Indicating method CondaEnv refers needs.conda logical. Whether method needs conda (yes python-based, R-based) conda.bin single string. path conda binary. empty (\"\"), NULL \"conda\", \"auto\" passed conda_binary find path conda binary PATH conda.env.name 1-length character. Name conda environment conda.env.path 1-length character. Path conda environment .valid logical. Whether environment valid. set user. Set checkCondaEnv.","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnv.html","id":null,"dir":"Reference","previous_headings":"","what":"Handy CondaEnv instance constructor — CondaEnv","title":"Handy CondaEnv instance constructor — CondaEnv","text":"Wrapper create CondaEnv object meant store information single conda environment specific method. cases, best user favors CondaEnvManager-related functions.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnv.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Handy CondaEnv instance constructor — CondaEnv","text":"","code":"CondaEnv( method = known.methods, conda.bin = NULL, conda.env.name = NULL, conda.env.path = NULL )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnv.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Handy CondaEnv instance constructor — CondaEnv","text":"method method name. One \"combat\", \"harmony\", \"mnn\", \"bbknn\", \"scvi\", \"scanvi\", \"scanorama\" conda.bin path conda binary. empty (\"\"), NULL \"conda\", \"auto\" passed conda_binary() find path conda binary PATH conda.env.name name conda environment conda.env.path path conda environment","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnv.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Handy CondaEnv instance constructor — CondaEnv","text":"CondaEnv object","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnvManager-class.html","id":null,"dir":"Reference","previous_headings":"","what":"Manager of conda environments for python-based integration methods — CondaEnvManager-class","title":"Manager of conda environments for python-based integration methods — CondaEnvManager-class","text":"CondaEnvManager class provides handy way set , store use conda environments python-based integration methods. designed set modified via helper functions, directly user.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaEnvManager-class.html","id":"slots","dir":"Reference","previous_headings":"","what":"Slots","title":"Manager of conda environments for python-based integration methods — CondaEnvManager-class","text":"combat CondaEnv. R-based combat method, nothing set . harmony CondaEnv. R-based harmony method, nothing set . mnn CondaEnv. R-based MNN method, nothing set . bbknn CondaEnv. python-based bbknn method. scvi CondaEnv. python-based SCVI method. Can shared SCANVI. scanvi CondaEnv. python-based SCANVI method. Can shared SCVI. scanorama CondaEnv. python-based Scanorama method trvae CondaEnv. python-based trVAE method","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaManager.html","id":null,"dir":"Reference","previous_headings":"","what":"Handy CondaEnvManger instance constructor — CondaManager","title":"Handy CondaEnvManger instance constructor — CondaManager","text":"Wrapper create CondaEnvManager object meant store information conda environments known methods data.frame object (typically stored package's cache). cases, best user favors UpdateEnvCache() function enables create/overwrite conda environments update package's internal cache.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaManager.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Handy CondaEnvManger instance constructor — CondaManager","text":"","code":"CondaManager(cache)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaManager.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Handy CondaEnvManger instance constructor — CondaManager","text":"cache correctly formatted (see ) data.frame path data.frame stored inside RDS file. cache missing, return blank object (.e. uninitialized state).","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaManager.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Handy CondaEnvManger instance constructor — CondaManager","text":"CondaEnvManager object","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CondaManager.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Handy CondaEnvManger instance constructor — CondaManager","text":"cache data.frame's expected column names : method needs.conda conda.bin.value conda.bin.valid conda.env.name.value conda.env.name.valid conda.env.path.value conda.env.path.valid .valid","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CutKnn.html","id":null,"dir":"Reference","previous_headings":"","what":"Remove excessive number of neighbours in a knn graph — CutKnn","title":"Remove excessive number of neighbours in a knn graph — CutKnn","text":"Ensure cell's number neighbours exceed cutoff","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CutKnn.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Remove excessive number of neighbours in a knn graph — CutKnn","text":"","code":"CutKnn( object, graph.name, new.graph = NULL, k.max, assay = NULL, verbose = TRUE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CutKnn.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Remove excessive number of neighbours in a knn graph — CutKnn","text":"object Seurat object graph.name name Graph Neighbor instance stored Seurat object. new.graph name trimmed graph save Seurat object k.max maximum number neigbours allowed per cell assay name assay use. Ignored graph object Neighbor object. specified (default), default assay used verbose whether print messages. Set FALSE disable","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/CutKnn.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Remove excessive number of neighbours in a knn graph — CutKnn","text":"Seurat object new Graph Neighbor instance","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":null,"dir":"Reference","previous_headings":"","what":"Integrate layers using one or multiple integration method(s) — DoIntegrate","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"Integrate layers Seurat object using one integration methods. Available integration methods listed bottom page. DoIntegrate() works best SeuratIntegrate's methods.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"","code":"DoIntegrate( object, ..., use.hvg = TRUE, use.future = TRUE, future.globals.size = getOption(\"future.globals.maxSize\") )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"object Seurat object ... one integration method call(s) correct batch effects . Must form package::MethodIntegration(). recommended use :: safer case namespace collision package attached loaded. forget parentheses. use.hvg whether use highly variable genes. FALSE causes features present assay used. use.future whether use future run integrations background session. Useful python-based algorithms invoked. future.globals.size maximum allowed size (bytes) global variables export. default, uses value option \"future.globals.maxSize\". NULL, thrice size Seurat object used. Inoperative use.future = FALSE","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"updated Seurat object enriched integration methods' outputs.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"call integration method require parentheses. Parameter values specific method can enclosed brackets, although defaults arguments good enough cases. Note integration method, argument values specified call supersede DoIntegrate's internal computations. instance, forces ComBat CCA use features instead variable ones.","code":"DoIntegrate(seu, SeuratIntegrate::CombatIntegration(features = Features(seu)), Seurat::CCAIntegration(), use.hvg = TRUE)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"desired value parameters use.hvg, use.future future.globals.size can different method called. Hence, accept vectors one element. must order integration method calls. unconventional way calling methods presents advantages: single call DoIntegrate, can perform multiple integrations , preserving flexibility individual method call fine-tuning integration-specific parameters.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html","id":"integration-method-functions","dir":"Reference","previous_headings":"","what":"Integration Method Functions","title":"Integrate layers using one or multiple integration method(s) — DoIntegrate","text":"following integration method functions available: SeuratIntegrate::bbknnIntegration SeuratIntegrate::CombatIntegration SeuratIntegrate::HarmonyIntegration SeuratIntegrate::HarmonyIntegration.fix SeuratIntegrate::MNNIntegration SeuratIntegrate::ScanoramaIntegration SeuratIntegrate::scANVIIntegration SeuratIntegrate::scVIIntegration SeuratIntegrate::scVIIntegration.fix SeuratIntegrate::trVAEIntegration CCAIntegration HarmonyIntegration JointPCAIntegration RPCAIntegration","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ExpandNeighbours.html","id":null,"dir":"Reference","previous_headings":"","what":"Expand knn graph to increase the number of neighbours — ExpandNeighbours","title":"Expand knn graph to increase the number of neighbours — ExpandNeighbours","text":"Expand knn graph increase number nearest neighbours using Dijkstra's algorithm, diffusion algorithm. Dijkstra's algorithm used prepare LISI score, diffusion suited preparing compute kBET score. Beware diffusion designed work connectivity matrices adequate distance-based networks.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ExpandNeighbours.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Expand knn graph to increase the number of neighbours — ExpandNeighbours","text":"","code":"ExpandNeighbours( object, graph.name = \"RNA_nn\", new.graph.name = NULL, graph.type = c(\"distances\", \"connectivities\"), k.target = 90L, do.symmetrize = FALSE, algo = c(\"dijkstra\", \"diffusion\"), which.dijkstra = c(\"auto\", \"igraph\", \"fast\", \"slow\"), dijkstra.ncores = 1L, dijkstra.tol = 1L, diffusion.iter = 26L, assay = NULL, verbose = TRUE ) # S4 method for class 'Seurat' ExpandNeighbours( object, graph.name = \"RNA_nn\", new.graph.name = NULL, graph.type = c(\"distances\", \"connectivities\"), k.target = 90L, do.symmetrize = FALSE, algo = c(\"dijkstra\", \"diffusion\"), which.dijkstra = c(\"auto\", \"igraph\", \"fast\", \"slow\"), dijkstra.ncores = 1L, dijkstra.tol = 1L, diffusion.iter = 26L, assay = NULL, verbose = TRUE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ExpandNeighbours.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Expand knn graph to increase the number of neighbours — ExpandNeighbours","text":"object Seurat, Graph Neighbor object graph.name name Graph Neighbor instance stored Seurat object. new.graph.name name return Graph store Seurat object. graph.type One \"distances\" \"connectivities\", indicating type metric stored graph object. k.target number nearest neighbours reach .symmetrize whether make input graph symmetric necessary. See Details section explanations algo One \"dijkstra\" \"diffusion\". \"diffusion\" suited connectivity matrices .dijkstra one \"igraph\", \"fast\" \"slow\". \"auto\" (default) chooses . See Details section dijkstra.ncores number cores use Dijkstra's algorithm. Ignored .dijkstra = \"igraph\" dijkstra.tol number sequential iterations identical best neighbours found consider Dijkstra's algorithm stopped. Ignored .dijkstra = \"igraph\" diffusion.iter maximum number iterations reach k.target assay name assay store output Graph verbose whether print progress messages","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ExpandNeighbours.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Expand knn graph to increase the number of neighbours — ExpandNeighbours","text":"Seurat object new Graph instance dgCMatrix representing Graph ","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ExpandNeighbours.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Expand knn graph to increase the number of neighbours — ExpandNeighbours","text":"approximate nature nearest neighbour search algorithm used compute knn graph makes resulting adjacency matrix asymmetric. means \\(cell_i\\) can nearest neighbour \\(cell_j\\) reverse true even though distance \\(cell_i\\) \\(cell_j\\) lower distance \\(cell_j\\) nearest neighbours. One can choose keep graph consider directed graph (.symmetrize = FALSE). alternative solution use computed distances extend knn graph making matrix symmetric. Note connectivity graphs already symmetric, argument value effect result.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html","id":null,"dir":"Reference","previous_headings":"","what":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","title":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","text":"Compute clusters multiple resolutions saves metadata clustering result reaches maximum NMI /ARI value given cell-type label variable.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","text":"","code":"FindOptimalClusters( object, graph.name = NULL, cell.var = NULL, cluster.name = \"{graph.name}_{cell.var}_{metric}\", modularity.fxn = 1, initial.membership = NULL, node.sizes = NULL, resolutions = seq(from = 0.1, to = 2, by = 0.1), optimisation.metric = c(\"nmi\", \"ari\"), method = \"matrix\", algorithm = 1, n.start = 10, n.iter = 10, random.seed = 0, group.singletons = TRUE, temp.file.location = NULL, edge.file.name = NULL, verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","text":"object Seurat object graph.name name knn graph score. cell.var name(s) column(s) cell type label variable (must object metadata). Multiple column names accepted cluster.name (optionally 'glue') string used new metadata column name (see Details section) modularity.fxn Modularity function (1 = standard; 2 = alternative). initial.membership, node.sizes Parameters pass Python leidenalg function. resolutions resolutions compute clusters optimisation.metric one \"nmi\" \"ari\" (default). metric(s) use check clustering results cell.var. method Method running leiden (defaults matrix fast small datasets). Enable method = \"igraph\" avoid casting large data dense matrix. algorithm Algorithm modularity optimization (1 = original Louvain algorithm; 2 = Louvain algorithm multilevel refinement; 3 = SLM algorithm; 4 = Leiden algorithm). Leiden requires leidenalg python. n.start Number random starts. n.iter Maximal number iterations per random start. random.seed Seed random number generator. group.singletons Group singletons nearest cluster. FALSE, assign singletons \"singleton\" group temp.file.location Directory intermediate files written. Specify ABSOLUTE path. edge.file.name Edge file use input modularity optimizer jar. verbose Print output ... Arguments passed methods","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","text":"updated seurat object new metadata column(s)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","text":"cluster.name can use 'glue' syntax avoid overwriting metadata columns multiple metrics /cell-type label variables provided. can ignored otherwise. Injectable variables \"graph.name\", \"cell.var\" \"metric\" (\"optimisation.metric\"). must flanked single curly brackets (\"{\" \"}\"). instance, prefer name clusters integration instead graph.name, use glue syntax (e.g. \"combat_{cell.var}_{metric}\" work, \"{combat}_{cell.var}_{metric}\" \"{integration}_{cell.var}_{metric}\" throw error)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Find a clustering that maximises NMI or ARI — FindOptimalClusters","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html","id":null,"dir":"Reference","previous_headings":"","what":"Derive connectivities from distances — GetConnectivities","title":"Derive connectivities from distances — GetConnectivities","text":"Adapted scanpy's strategy sc.pp.neighbors() compute connectivities. Two methods available, using Gaussian kernel fuzzy union simplical sets implemented umap-learn","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Derive connectivities from distances — GetConnectivities","text":"","code":"GetConnectivities( object, neighbors.use, method = c(\"umap\", \"gauss\"), graph.name = NULL, assay = NULL, umap.set.op.mix.ratio = 1, umap.local.connectivity = 1, umap.niter.smoothing = 64L, umap.apply.set.operations = TRUE, umap.bipartite = FALSE, gauss.sigmas = NULL, gauss.median.sigma = FALSE, verbose = TRUE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Derive connectivities from distances — GetConnectivities","text":"object Seurat object neighbors.use name Neighbor instance stored Seurat object derive connectivities . method one \"umap\" \"gauss\". Decides whether connectivities computed using fuzzy union simplical sets (\"umap\") Gaussian kernel (\"gauss\") graph.name name return Graph connectivities store Seurat object. assay name assay reference output Graph object. Use default assay object provided. umap.set.op.mix.ratio float 0 1. Controls fuzzy sets mixed obtain global fuzzy simplicial set. 0 1 correspond pure fuzzy intersection union, respectively. fuzzy set operations use product t-norm. applies umap method. umap.local.connectivity local connectivity required, .e. expected number nearest neighbours locally connected. higher, local connections output. practice, local intrinsic dimension manifold. applies umap method umap.apply.set.operations = TRUE. umap.niter.smoothing maximum number iterations smoothing process distances. applies umap method. umap.apply.set.operations set FALSE disable fuzzy union intersection local fuzzy simplicial sets global fuzzy simplicial set. applies umap method. umap.bipartite whether knn network bipartite (FALSE default). applies umap method. gauss.sigmas default, sigma value (.e. width kernel) per cell computed internally. sigmas controlling cell's connectivities range magnitude. Alternatively, can provide width(s). length sigmas shorter number cells, recycled. applies Gaussian method. gauss.median.sigma estimation method use sigmas = NULL. default, use cell’s distance kth nearest neighbour. median.sigma = TRUE, use median distances nearest neighbours (excluding self). applies Gaussian method. verbose whether print progress messages","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Derive connectivities from distances — GetConnectivities","text":"Seurat object new Graph instance name graph.name","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Derive connectivities from distances — GetConnectivities","text":"UMAP method re-implementation function fuzzy_simplicial_set() umap-learn estimate identical connectivities. can check original documentation. Gaussian kernel method re-implementation analogous function scanpy called sc.pp.neighbors(). can look original functionmedian.sigmas = FALSE method used Haghverdi L. et al.,2016.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Derive connectivities from distances — GetConnectivities","text":"McInnes, L., Healy, J. & Melville, J. UMAP: Uniform Manifold Approximation Projection Dimension Reduction. arXiv preprint (2018). DOI Wolf, F. ., Angerer, P. & Theis, F. J. SCANPY: large-scale single-cell gene expression data analysis. Genome Biology 19, (2018). Coifman, R. R., Lafon, S., Lee, . B., Maggioni, M., Nadler, B., Warner, F. & Zucker, S. W. Geometric diffusions tool harmonic analysis structure definition data: Diffusion maps. PNAS 102, 7426–7431 (2005). DOI Haghverdi, L., Büttner, M., Wolf, F. ., Buettner, F. & Theis, F. J. Diffusion pseudotime robustly reconstructs lineage branching. Nature Methods 13, 845–848 (2016). DOI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetNeighborsPerBatch.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate number of nearest neighbours between batches — GetNeighborsPerBatch","title":"Calculate number of nearest neighbours between batches — GetNeighborsPerBatch","text":"Calculate number nearest neighbours batches knn graph","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetNeighborsPerBatch.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate number of nearest neighbours between batches — GetNeighborsPerBatch","text":"","code":"GetNeighborsPerBatch( object, batch.var, graph.name = \"RNA_nn\", count.self = TRUE ) # S4 method for class 'Seurat,character' GetNeighborsPerBatch( object, batch.var, graph.name = \"RNA_nn\", count.self = TRUE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetNeighborsPerBatch.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate number of nearest neighbours between batches — GetNeighborsPerBatch","text":"object Seurat object batch.var name column Seurat object's metadata containing batch information graph.name name Graph Neighbor instance stored object. available, prefer distance based network connectivities graph (especially computed UMAP method). count.self whether include self--self vertices calculation","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetNeighborsPerBatch.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate number of nearest neighbours between batches — GetNeighborsPerBatch","text":"square count matrix size number batches (see Details section)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetNeighborsPerBatch.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Calculate number of nearest neighbours between batches — GetNeighborsPerBatch","text":"output matrix likely symmetrical. due approximate nature nearest neighbour search algorithm used compute knn graph. must read row. instance, number times cells batch 1 cells batch 3 nn matrix[1,3]","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropInterBatch.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate proportion of nearest neighbours between batches — GetPropInterBatch","title":"Calculate proportion of nearest neighbours between batches — GetPropInterBatch","text":"Calculate proportion nearest neighbours batches knn graph","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropInterBatch.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate proportion of nearest neighbours between batches — GetPropInterBatch","text":"","code":"GetPropInterBatch( object, batch.var, graph.name = \"RNA_nn\", count.self = TRUE, per.batch = TRUE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropInterBatch.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate proportion of nearest neighbours between batches — GetPropInterBatch","text":"object Seurat object batch.var name column Seurat object's metadata containing batch information graph.name name Graph Neighbor instance stored object. available, prefer distance based network connectivities graph (especially computed UMAP method). count.self whether include self--self vertices calculation per.batch whether keep proportions per batch aggregate everything","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropInterBatch.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate proportion of nearest neighbours between batches — GetPropInterBatch","text":"vector length 1 number batches, depending per.batch argument value","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropIntraBatch.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate proportion of nearest neighbours within batches — GetPropIntraBatch","title":"Calculate proportion of nearest neighbours within batches — GetPropIntraBatch","text":"Calculate proportion nearest neighbours within batches knn graph","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropIntraBatch.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate proportion of nearest neighbours within batches — GetPropIntraBatch","text":"","code":"GetPropIntraBatch( object, batch.var, graph.name = \"RNA_nn\", count.self = TRUE, per.batch = TRUE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropIntraBatch.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate proportion of nearest neighbours within batches — GetPropIntraBatch","text":"object Seurat object batch.var name column Seurat object's metadata containing batch information graph.name name Graph Neighbor instance stored object. available, prefer distance based network connectivities graph (especially computed UMAP method). count.self whether include self--self vertices calculation per.batch whether keep proportions per batch aggregate everything","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/GetPropIntraBatch.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate proportion of nearest neighbours within batches — GetPropIntraBatch","text":"vector length 1 number batches, depending per.batch argument value","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"wrapper run Harmony multi-layered Seurat V5 object Can called via SeuratIntegrate::HarmonyIntegration() HarmonyIntegration.fix()","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"","code":"HarmonyIntegration( object, orig, groups = NULL, groups.name = NULL, layers = NULL, scale.layer = \"scale.data\", features = NULL, new.reduction = \"harmony\", dims = NULL, key = \"harmony_\", seed.use = 42L, theta = NULL, sigma = 0.1, lambda = NULL, nclust = NULL, ncores = 1L, max_iter = 10, early_stop = TRUE, plot_convergence = FALSE, .options = harmony_options(), verbose = TRUE, ... ) HarmonyIntegration.fix(...)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) orig DimReduc object. set directly called IntegrateLayers, use orig.reduction argument instead groups named data frame grouping information. Preferably one-column groups.name = NULL groups.name Column name groups data frame stores grouping information. groups.name = NULL, first column used layers Ignored unless groups = NULL, used create grouping variable correct batch-effect. scale.layer Ignored features Ignored new.reduction Name new integrated dimensional reduction dims Dimensions dimensional reduction use integration. used default key Prefix dimension names computed harmony. seed.use integer generate reproducible outputs. Set seed.use = NULL disable theta Diversity clustering penalty parameter. Specify variable vars_use Default theta=2. theta=0 encourage diversity. Larger values theta result diverse clusters. sigma Width soft kmeans clusters. Default sigma=0.1. Sigma scales distance cell cluster centroids. Larger values sigma result cells assigned clusters. Smaller values sigma make soft kmeans cluster approach hard clustering. lambda Ridge regression penalty. Default lambda=1. Bigger values protect correction. several covariates specified, lambda can also vector needs equal length number variables corrected. scenario, covariate level group assigned scalars specified user. set NULL, harmony start lambda estimation mode determine lambdas automatically try minimize overcorrection (Use caution still beta testing). nclust Number clusters model. nclust=1 equivalent simple linear regression. ncores Number processors used math operations optimized BLAS available. BLAS supporting multithreaded option effect. default, ncore=1 runs single-threaded process. Although Harmony supports multiple cores, optimized multithreading. Increase number large datasets iff single-core performance adequate. max_iter Maximum number rounds run Harmony. One round Harmony involves one clustering one correction step. early_stop Enable early stopping harmony. harmonization process stop change objective function corrections drops 1e-4 plot_convergence Whether print convergence plot clustering objective function. TRUE plot, FALSE suppress. can useful debugging. .options Setting advanced parameters RunHarmony. must result call `harmony_options`. See ?`harmony_options` parameters listed details. verbose Print messages. Set FALSE disable ... Ignored HarmonyIntegration(), HarmonyIntegration.fix()","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"function returns list containing: new DimReduc name reduction.name (key set reduction.key) corrected cell embeddings matrix length(dims) columns. called via IntegrateLayers, Seurat object new reduction returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"function requires harmony package installed","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"Korsunsky, ., Millard, N., Fan, J., Slowikowski, K., Zhang, F., Wei, K., Baglaenko, Y., Brenner, M., Loh, P. & Raychaudhuri, S. Fast, sensitive accurate integration single-cell data Harmony. Nat Methods 16, 1289–1296 (2019). DOI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run Harmony on Seurat's Assay5 object through IntegrateLayers — HarmonyIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- UpdateSeuratObject(SeuratData::LoadData(\"pbmcsca\")) obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers based on the \"Method\" variable: obj <- IntegrateLayers(object = obj, method = SeuratIntegrate::HarmonyIntegration, verbose = TRUE) # We can also change parameters such as the batch-effect variable. # Here we change the groups variable, the number of dimension used from the original # PCA and minor options from `harmony_options()`: harmonyOptions <- harmony::harmony_options() harmonyOptions$max.iter.cluster <- 10 # 20 by default harmonyOptions$block.size <- .1 # .05 by default obj <- IntegrateLayers(object = obj, method = SeuratIntegrate::HarmonyIntegration, dims = 1:30, plot_convergence = TRUE, groups = obj[[]]$Experiment, new.reduction = \"harmony_custom\", .options = harmonyOptions, verbose = TRUE) } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","title":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","text":"wrapper run mnnCorrect multi-layered Seurat V5 object","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","text":"","code":"MNNIntegration( object, orig = NULL, groups = NULL, layers = NULL, scale.layer = NULL, features = 2000, reconstructed.assay = \"mnn.reconstructed\", verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) orig DimReduc object. set directly called IntegrateLayers, use orig.reduction argument instead groups Ignored layers Name layers use integration scale.layer Name scaled layer Assay features Either list features use calculating batch correction, number (2000 default) variable features select. reconstructed.assay Name assay containing low-rank reconstruction expression matrix. verbose Print messages. Set FALSE disable ... Extra parameters passed mnnCorrect","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","text":"Seurat object merged objects object.list new DimReduc name reduction.name (key set reduction.key) corrected embeddings matrix well rotation matrix used PCA stored feature loadings slot. Also returns expression matrix reconstructed low-rank approximation reconstructed.assay assay; metadata info mnnCorrect stored tool slot, accessible Tool","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","text":"function requires batchelor package installed","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run classical MNN on Seurat's Assay5 object through IntegrateLayers — MNNIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- UpdateSeuratObject(SeuratData::LoadData(\"pbmcsca\")) obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers: obj <- IntegrateLayers(object = obj, method = MNNIntegration, new.reduction = 'integrated.mnn', verbose = FALSE) # We can also add parameters specific to mnnCorrect. # Here we set `k` to specify the number of nearest neighbors # to use when identifying MNNs: obj <- IntegrateLayers(object = obj, method = MNNIntegration, new.reduction = 'integrated.mnn', k = 15, verbose = FALSE) } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/NormaliseL2.html","id":null,"dir":"Reference","previous_headings":"","what":"Normalise a matrix using L2 norm — NormaliseL2","title":"Normalise a matrix using L2 norm — NormaliseL2","text":"Normalise rows columns matrix using L2 norm","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/NormaliseL2.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Normalise a matrix using L2 norm — NormaliseL2","text":"","code":"NormaliseL2(mat, MARGIN = 1)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/NormaliseL2.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Normalise a matrix using L2 norm — NormaliseL2","text":"mat matrix (sparse dense) MARGIN one 1 2, corresponding normalisation per rows columns respectively","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/NormaliseL2.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Normalise a matrix using L2 norm — NormaliseL2","text":"matrix normalised rows columns","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/NormaliseL2.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Normalise a matrix using L2 norm — NormaliseL2","text":"Adapted Seurat:::L2Norm","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/PlotScores.html","id":null,"dir":"Reference","previous_headings":"","what":"Visualise and compare the performances of integration algorithms — PlotScores","title":"Visualise and compare the performances of integration algorithms — PlotScores","text":"Plot scaled integration scores compare obtained integrations","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/PlotScores.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Visualise and compare the performances of integration algorithms — PlotScores","text":"","code":"PlotScores( object, plot.type = c(\"dot\", \"radar\", \"lollipop\"), split.by.score.type = TRUE, order.by = c(\"score\", \"name\", \"asis\"), hide.zeros = FALSE, include.integration = NULL, exclude.integration = NULL, include.score = NULL, exclude.score = NULL, recompute.overall.scores = TRUE, rescale = TRUE, batch.coeff = 0.4, bio.coeff = 0.6, point.max.size = 20L, use.ggforce = is_installed(\"ggforce\") )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/PlotScores.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Visualise and compare the performances of integration algorithms — PlotScores","text":"object Seurat object plot.type one 'table' (default), 'radar' 'lollipop'. Type desired plot split..score.type whether split scores type (bio-conservation, batch correction overall scores). set FALSE, scores mixed single figure. order.one 'score' (default), 'name' 'asis'. Determines order integrations legend (y-axis lolliplop table plots). Scores ordered decreasing overall score default, name row-order setting 'name' 'asis' respectively. hide.zeros whether zero(ed) scores visible plot. include.integration name integration(s) include. default value (NULL) enable include . exclude.integration name integration(s) exclude. default value (NULL) enable include . include.score name score(s) include. default value (NULL) enable include . exclude.score name score(s) exclude. default value (NULL) enable include . recompute.overall.scores whether recompute overall scores. Useful restriction scores plot. FALSE, coefficient parameters impact. rescale whether rescale score 0 1 using min-max normalisation computing overall scores. ensures metric equally contributes overall scores. effect recompute.overall.scores = FALSE. TRUE default batch.coeff weight batch correction performance evaluation scores overall score. bio.coeff weight bio-conservation performance evaluation scores overall score. point.max.size inoperative unless plot.type = 'table' use.ggforce = FALSE. Determine maximum size points (achieved score 1) fit plotting area (handled automaticaly ggforce used). use.ggforce plot.type = 'table', enable disable use ggforce draw circles. Used default package installed","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/PlotScores.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Visualise and compare the performances of integration algorithms — PlotScores","text":"ggplot object","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScaleScores.html","id":null,"dir":"Reference","previous_headings":"","what":"Scale the scores in the score tibble to plot them — ScaleScores","title":"Scale the scores in the score tibble to plot them — ScaleScores","text":"scores interest computed saved score tibble, can scaled make comparable bounding 0 1 harmonise direction (0 1 always mean bad good performance respectively). also prerequisite plotting.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScaleScores.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Scale the scores in the score tibble to plot them — ScaleScores","text":"","code":"ScaleScores( object, ref = \"Unintegrated\", rescale = FALSE, batch.coeff = 0.4, bio.coeff = 0.6 )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScaleScores.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Scale the scores in the score tibble to plot them — ScaleScores","text":"object Seurat object ref name integration use reference scaling. Useful PCA regression (density) cell cycle conservation scores. rescale whether rescale score 0 1 using min-max normalisation computing overall scores. ensures metric equally contributes overall scores. TRUE default batch.coeff weight batch correction performance evaluation scores overall score. bio.coeff weight bio-conservation performance evaluation scores overall score.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"wrapper run Scanorama multi-layered Seurat V5 object. Requires conda environment scanorama necessary dependencies","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"","code":"ScanoramaIntegration( object, orig, layers = NULL, features = NULL, scale.layer = \"scale.data\", conda_env = NULL, new.reduction = \"integrated.scanorama\", reduction.key = \"scanorama_\", reconstructed.assay = \"scanorama.reconstructed\", ncores = 1L, ndims.out = 100L, return_dense = TRUE, batch_size = 5000, approx = TRUE, sigma = 15L, alpha = 0.1, knn = 20L, hvg.scanorama = NULL, union.features = FALSE, sketch = FALSE, sketch_method = c(\"geosketch\", \"uniform\"), sketch_max = 10000, seed.use = 42L, verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) orig DimReduc object. set directly called IntegrateLayers, use orig.reduction argument instead layers Name layers use integration features Vector feature names input integration method. features = NULL (default), VariableFeatures used. pass features, use output Features() scale.layer Name scaled layer Assay conda_env Path conda environment run scanorama (also contain scipy python module). default, uses conda environment registered scanorama conda environment manager new.reduction Name store resulting dimensional reduction object. NULL FALSE disables dimension reduction computation reduction.key Key resulting dimensional reduction object. Ignored reduction.key NULL FALSE reconstructed.assay Name assay containing corrected expression matrix dimension #features x #cells. NULL FALSE disables corrected expression matrix computation ncores Number parallel threads create blas_set_num_threads. Pointless BLAS supporting multithreaded ndims.Number dimensions new.reduction output. Scanorama specific argument return_dense Whether scanorama returns numpy.ndarray matrices instead scipy.sparse.csr_matrix. Scanorama specific argument batch_size Used alignment vector computation. Higer values increase memory burden.Scanorama specific argument approx Whether scanorama approximates nearest neighbors computation. Scanorama specific argument sigma Correction smoothing parameter gaussian kernel. Scanorama specific argument alpha Minimum alignment score. Scanorama specific argument knn Number nearest neighbours used matching. Scanorama specific argument hvg.scanorama positive integer turn scanorama's internal HVG selection . Disabled default. Scanorama specific argument union.features default, scanorama uses intersection features perform integration. Set parameter TRUE use union. Discouraged. Scanorama specific argument sketch Turns sketching-based acceleration first downsampling datasets. See Hie et al., Cell Systems (2019). Disabled default. Ignored reconstructed.assay enabled. Scanorama specific argument sketch_method skething method apply data. Either 'geosketch' (default) 'uniform'. Ignored reconstructed.assay enabled sketch FALSE. Scanorama specific argument sketch_max Downsampling cutoff. Ignored sketching disabled. Scanorama specific argument seed.use integer generate reproducible outputs. Set seed.use = NULL disable verbose Print messages. Set FALSE disable ... Ignored","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"list containing least one : new DimReduc name reduction.name (key set reduction.key) corrected embeddings matrix ndims.. new Assay name reconstructed.assay corrected counts features (less hvg set lower integer). called via IntegrateLayers, Seurat object new reduction /assay returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"function requires Scanorama package installed (along scipy)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"Hie, B., Bryson, B. & Berger, B. Efficient integration heterogeneous single-cell transcriptomes using Scanorama. Nat Biotechnol 37, 685–691 (2019). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run Scanorama on Seurat's Assay5 object through IntegrateLayers — ScanoramaIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers: obj <- IntegrateLayers(object = obj, method = ScanoramaIntegration) # To disable feature expression matrix correction: obj <- IntegrateLayers(object = obj, method = ScanoramaIntegration, reconstructed.assay = NULL) } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SetMiscScore.html","id":null,"dir":"Reference","previous_headings":"","what":"Set the value of a score in the score tibble — SetMiscScore","title":"Set the value of a score in the score tibble — SetMiscScore","text":"Set score value given integration given score name. exist yet, created though AddMiscIntegrations AddMiscScores respectively.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SetMiscScore.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set the value of a score in the score tibble — SetMiscScore","text":"","code":"SetMiscScore(object, integration, score.name, score.value, ...)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SetMiscScore.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set the value of a score in the score tibble — SetMiscScore","text":"object Seurat object integration name integration score computed. score.name name computed score score.value value score ... additional parameter pass AddMiscScores. effect score slot already present tibble. Otherwise, enable pass class argument specify class score slot create.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SetMiscScore.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set the value of a score in the score tibble — SetMiscScore","text":"Seurat object updated table scores.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SeuratIntegrate-package.html","id":null,"dir":"Reference","previous_headings":"","what":"SeuratIntegrate: Expands the set of integration methods available to Seurat — SeuratIntegrate-package","title":"SeuratIntegrate: Expands the set of integration methods available to Seurat — SeuratIntegrate-package","text":"R package gathering set wrappers apply various integration methods Seurat objects (rate methods). Intended apply Seurat V5 objects bearing multiple layers.","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SeuratIntegrate-package.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"SeuratIntegrate: Expands the set of integration methods available to Seurat — SeuratIntegrate-package","text":"Maintainer: Florian Specque florian.specque@u-bordeaux.fr (ORCID) Authors: Domitille Chalopin domitille.chalopin-fillot@u-bordeaux.fr (ORCID) contributors: Macha Nikolski macha.nikolski@u-bordeaux.fr (ORCID) [reviewer] Aurélien Barré aurelien.barre@u-bordeaux.fr (ORCID) [contributor] Centre de Bioinformatique de Bordeaux (CBiB) [copyright holder]","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SymmetrizeKnn.html","id":null,"dir":"Reference","previous_headings":"","what":"Symmetrize a nearest neighbours graph — SymmetrizeKnn","title":"Symmetrize a nearest neighbours graph — SymmetrizeKnn","text":"approximate nature nearest neighbour search algorithm used compute knn graph makes resulting adjacency matrix asymmetric. functions symmetrize Graph Neighbor object.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SymmetrizeKnn.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Symmetrize a nearest neighbours graph — SymmetrizeKnn","text":"","code":"SymmetrizeKnn(object, graph.name = \"RNA_nn\", use.max = TRUE, assay = NULL) # S4 method for class 'Seurat' SymmetrizeKnn(object, graph.name = \"RNA_nn\", use.max = TRUE, assay = NULL) # S4 method for class 'Matrix' SymmetrizeKnn(object, use.max = TRUE) # S4 method for class 'Graph' SymmetrizeKnn(object, use.max = TRUE) # S4 method for class 'Neighbor' SymmetrizeKnn(object, use.max = TRUE)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SymmetrizeKnn.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Symmetrize a nearest neighbours graph — SymmetrizeKnn","text":"object Seurat, Graph Neighbor object graph.name name Graph Neighbor instance stored Seurat object. use.max default, use maximum value case discrepancy m[,j] m[j,]. Set FALSE use minimum value. assay name assay store output Graph","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/SymmetrizeKnn.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Symmetrize a nearest neighbours graph — SymmetrizeKnn","text":"Seurat object new Graph instance dgCMatrix representing Graph ","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/UpdateEnvCache.html","id":null,"dir":"Reference","previous_headings":"","what":"Handy CondaEnvManger instance modifier — UpdateEnvCache","title":"Handy CondaEnvManger instance modifier — UpdateEnvCache","text":"Wrapper update CondaEnvManager object stored cache used configuration conda environments known methods (typically stored package's cache). single method can updated time. cases, best way modify package's conda environments registry.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/UpdateEnvCache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Handy CondaEnvManger instance modifier — UpdateEnvCache","text":"","code":"UpdateEnvCache( method = known.methods, conda.bin = \"auto\", conda.env = NULL, conda.env.is.path = \"auto\", separate.scvi.envs = FALSE, overwrite.env = FALSE, dry.run = FALSE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/UpdateEnvCache.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Handy CondaEnvManger instance modifier — UpdateEnvCache","text":"method name method update. One \"combat\", \"harmony\", \"mnn\", \"bbknn\", \"scvi\", \"scanvi\", \"scanorama\", \"trvae\" conda.bin path conda binary. empty (\"\"), NULL \"conda\", \"auto\" passed conda_binary() find path conda binary PATH conda.env Either name conda environment path environment. Must reachable provided conda.bin. NULL enable use default environment names. (see Details section) conda.env..path Whether conda.env path (TRUE), name (FALSE). default (\"auto\") guesses. careful make mistake switch non-default value separate.scvi.envs default, SCVI SCANVI share conda environment, since rely python package. wish distinct environment , set TRUE. Ignored method SCVI SCANVI. overwrite.env Turn TRUE enable overwriting existing environment (name path). provided conda.env already exists, default behaviour update package's registry existing environment dry.run TRUE, package's current cache updated. new conda environment () created. FALSE default.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/UpdateEnvCache.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Handy CondaEnvManger instance modifier — UpdateEnvCache","text":"CondaEnvManager object","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/UpdateEnvCache.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Handy CondaEnvManger instance modifier — UpdateEnvCache","text":"conda environments default names : bbknn: SeuratIntegrate_scvi SCVI: SeuratIntegrate_scvi-tools SCANVI: SeuratIntegrate_scvi-tools scanorama: SeuratIntegrate_scanorama trVAE: SeuratIntegrate_trvae","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/add-score.html","id":null,"dir":"Reference","previous_headings":"","what":"Add integration(s) or score(s) slot(s) to the score tibble — add-score","title":"Add integration(s) or score(s) slot(s) to the score tibble — add-score","text":"AddMiscIntegrations: Add integration(s) slot(s) score tibble (make sure ). enables save scores later. AddMiscScores: Add score(s) slot(s) score tibble (make sure ). enables save later.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/add-score.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Add integration(s) or score(s) slot(s) to the score tibble — add-score","text":"","code":"AddMiscIntegrations(object, which) AddMiscScores(object, which, class = \"numeric\")"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/add-score.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Add integration(s) or score(s) slot(s) to the score tibble — add-score","text":"object Seurat object name new integration(s) score(s) class class column, 'numeric' (default). instance, cell cycle conservation scores 'list' LISI scores 'numeric_lisi'.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/add-score.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Add integration(s) or score(s) slot(s) to the score tibble — add-score","text":"Seurat object updated table scores.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"wrapper run bbknn multi-layered Seurat V5 object. Requires conda environment bbknn necessary dependencies","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"","code":"bbknnIntegration( object, orig, groups = NULL, groups.name = NULL, layers = \"data\", scale.layer = \"scale.data\", conda_env = NULL, new.graph = \"bbknn\", new.reduction = \"pca.bbknn\", reduction.key = \"bbknnPCA_\", reconstructed.assay = \"bbknn.ridge\", ndims = 50L, ndims.use = 30L, ridge_regression = T, graph.use = c(\"connectivities\", \"distances\"), verbose = TRUE, seed.use = 42L, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) orig DimReduc object. set directly called IntegrateLayers, use orig.reduction argument instead groups named data frame grouping information. Preferably one-column groups.name = NULL groups.name Column name groups data frame stores grouping information. groups.name = NULL, first column used layers Name layers use integration scale.layer Name scaled layer Assay conda_env Path conda environment run bbknn (also contain scipy python module). default, uses conda environment registered bbknn conda environment manager new.graph Name Graph object new.reduction Name new integrated dimensional reduction reduction.key Key new integrated dimensional reduction reconstructed.assay Name assay containing corrected expression matrix ndims Number dimensions new PCA computed first output bbknn. 50 default. Ignored ridge_regression = FALSE ndims.use Number dimensions orig use bbknn, newly computed PCA ridge_regression = TRUE. ridge_regression set TRUE (default), new clusters computed output bbknn, ridge regression performed remove technical variables preserving biological variables. , new bbknn run performed. graph.use graph(s) bbknn output. least one \"connectivities\" \"distances\". provided (default) ridge_regression = TRUE, first one (\"connectivities\" default, recommended) used input computing clusters. verbose Print messages. Set FALSE disable seed.use integer generate reproducible outputs. Set seed.use = NULL disable ... Additional arguments passed bbknn.bbknn(). ridge_regression = TRUE, also accepts arguments pass Seurat::FindClusters(), Seurat::RunPCA() bbknn.ridge_regression(). See Details section","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"list containing least one : 1 2 new Graph(s) name [new_graph]_scale.data_[graph.use] corresponding output(s) first run bbknn new Assay name reconstructed.assay corrected counts feature scale.layer. new DimReduc (PCA) name new.reduction (key set reduction.key) 1 2 new Graph(s) name [new_graph]_ridge.residuals_[graph.use] corresponding output(s) second run bbknn [graph.use] can take two values (either \"connectivities\" \"distances\"), depending graph.use parameter. called via IntegrateLayers, Seurat object new reduction /assay returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"wrappers calls three python functions reticulate. Find bbknn-specific arguments : bbknn function: bbknn.bbknn, relies bbknn.matrix.bbknn ridge regression: bbknn.ridge_regression, relies sklearn.linear_model.Ridge","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"function requires bbknn package installed (along scipy)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"Polański, K., Young, M. D., Miao, Z., Meyer, K. B., Teichmann, S. . & Park, J.-E. BBKNN: fast batch alignment single cell transcriptomes. Bioinformatics 36, 964–965 (2019). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run bbknn on Seurat's Assay5 object through IntegrateLayers — bbknnIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers: obj <- IntegrateLayers(object = obj, method = bbknnIntegration, conda_env = 'bbknn', groups = obj[[]], groups.name = 'Method') # To disable the ridge regression and subsequent steps: obj <- IntegrateLayers(object = obj, method = bbknnIntegration, conda_env = 'bbknn', groups = obj[[]], groups.name = 'Method', ridge_regression = FALSE) } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/checkCondaEnv.html","id":null,"dir":"Reference","previous_headings":"","what":"Check the validity of conda environment's components — checkCondaBin","title":"Check the validity of conda environment's components — checkCondaBin","text":"Check validity conda environment's components. Best used CondaEnv object. Internally call: checkCondaBin: conda_binary checkCondaEnvPath: condaenv_exists checkCondaEnvName: condaenv_exists checkCondaEnv: ","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/checkCondaEnv.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check the validity of conda environment's components — checkCondaBin","text":"","code":"checkCondaBin(x, ..., verbose = getOption(\"verbose\")) checkCondaEnvPath(x, ..., verbose = getOption(\"verbose\")) checkCondaEnvName(x, ..., verbose = getOption(\"verbose\")) checkCondaEnv(x, ..., verbose = getOption(\"verbose\"))"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/checkCondaEnv.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check the validity of conda environment's components — checkCondaBin","text":"x CondaEnv object sub element class CondaEnvSlot. checkCondaEnv() accepts CondaEnv object ... ignored x CondaEnv object. Otherwise, additional arguments reticulate functions Description conda = ... verbose ignored","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/checkCondaEnv.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check the validity of conda environment's components — checkCondaBin","text":"updated object class input x","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/checkCondaEnv.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Check the validity of conda environment's components — checkCondaBin","text":"checkCondaEnv wrapper calls checks.","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/get-score.html","id":null,"dir":"Reference","previous_headings":"","what":"Retrieve integration scores from a Seurat object — GetMiscIntegrations","title":"Retrieve integration scores from a Seurat object — GetMiscIntegrations","text":"Scores stored tibble objects Misc. Slot raw scores named 'si_scores' scaled scores found 'si_scaled.scores'. GetMiscIntegrations: Get (search ) integration names score tibble GetMiscScores: Get (search ) score names score tibble IntegrationScores: Get tibble scaled unscaled scores","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/get-score.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Retrieve integration scores from a Seurat object — GetMiscIntegrations","text":"","code":"GetMiscIntegrations(object, search = NULL) GetMiscScores(object, search = NULL) IntegrationScores(object, scaled = FALSE)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/get-score.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Retrieve integration scores from a Seurat object — GetMiscIntegrations","text":"object Seurat object search character vector names search case-insensitive exact match. NULL disables search (default) scaled whether query unscaled (default) scaled scores (scaling performed)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/get-score.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Retrieve integration scores from a Seurat object — GetMiscIntegrations","text":"GetMiscIntegrations: character vector integration names, NULL object 'si_scores' Misc search return result. GetMiscScores: character vector score names, NULL object 'si_scores' Misc search return result. IntegrationScores: either NULL requested object exist, otherwise tibble. first column contains name integrations, following column corresponds score.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCache.html","id":null,"dir":"Reference","previous_headings":"","what":"Get current cache of conda environments — getCache","title":"Get current cache of conda environments — getCache","text":"Get current cache conda environments package environment cache disk","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get current cache of conda environments — getCache","text":"","code":"getCache(from = c(\"env\", \"cache\"))"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCache.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get current cache of conda environments — getCache","text":"Either \"env\" \"cache\". load cache .","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCache.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Get current cache of conda environments — getCache","text":"CondaEnvManager object","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCachePath.html","id":null,"dir":"Reference","previous_headings":"","what":"Get path to package config cache — getCachePath","title":"Get path to package config cache — getCachePath","text":"Get path package config cache file directory","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCachePath.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get path to package config cache — getCachePath","text":"","code":"getCachePath(include.file = TRUE)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCachePath.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get path to package config cache — getCachePath","text":"include.file Set FALSE retrieve directory containing cache file. Return path file default.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/getCachePath.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Get path to package config cache — getCachePath","text":"single character, path cache file directory","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/isValid.html","id":null,"dir":"Reference","previous_headings":"","what":"Check the validity of conda environment's components — isValid","title":"Check the validity of conda environment's components — isValid","text":"Get validity conda environment's components. Best used CondaEnvManager CondaEnv object.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/isValid.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check the validity of conda environment's components — isValid","text":"","code":"isValid(x, ...) # S4 method for class 'CondaEnvSlot' isValid(x, ...) # S4 method for class 'CondaEnv' isValid(x, do.check = FALSE, ...) # S4 method for class 'CondaEnvManager' isValid(x, ...)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/isValid.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check the validity of conda environment's components — isValid","text":"x CondaEnvManager, CondaEnv object sub element class CondaEnvSlot. ... ignored x CondaEnvSlot object. Otherwise, can used pass .check argument. .check whether call check functions. apply x CondaEnvSlot object.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/isValid.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check the validity of conda environment's components — isValid","text":"TRUE FALSE logical named vector x CondaEnvManager object (one element per method)","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-indexing.html","id":null,"dir":"Reference","previous_headings":"","what":"Matrix indexing — matrix-indexing","title":"Matrix indexing — matrix-indexing","text":"Switch rows & columns indices vector-like indices matrices.rowcol2idx get indices rows columnsidx2col get columns indicesidx2row get rows indices","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-indexing.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Matrix indexing — matrix-indexing","text":"","code":"rowcol2idx(rows.idx, cols.idx, height) idx2col(idx, height) idx2row(idx, height)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-indexing.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Matrix indexing — matrix-indexing","text":"rows.idx indices rows cols.idx indices columns height height matrix (number rows) idx vector-like, matrix-wide indices","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-indexing.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Matrix indexing — matrix-indexing","text":"vector indices","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-sorting.html","id":null,"dir":"Reference","previous_headings":"","what":"Matrix sorting — matrix-sorting","title":"Matrix sorting — matrix-sorting","text":"Sort matrix row- column-wise manner, check isrowSort sort row independentlycolSort sort column independentlyrowSorted check row independently sortedcolSorted check column independently sorted","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-sorting.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Matrix sorting — matrix-sorting","text":"","code":"rowSort(mat, by = NULL, ncol = NULL, decreasing = FALSE) colSort(mat, by = NULL, ncol = NULL, decreasing = FALSE) rowSorted(mat, decreasing = FALSE) colSorted(mat, decreasing = FALSE)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-sorting.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Matrix sorting — matrix-sorting","text":"mat matrix sort check matrix sort . NULL, sort mat (default) ncol number desired columns sorted mat. NULL, keep original dimensions mat (default) decreasing logical. sort increasing decreasing? available partial sorting.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-sorting.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Matrix sorting — matrix-sorting","text":"sorted matrix ncol columns","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-sorting.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Matrix sorting — matrix-sorting","text":"mat different dimensions, results might incorrect","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-symmetrize.html","id":null,"dir":"Reference","previous_headings":"","what":"Matrix symmetrizing — matrix-symmetrize","title":"Matrix symmetrizing — matrix-symmetrize","text":"Create sparse matrix using , j x (row indices, column indicies values respectively) symmetrizes low memory footprintsymmetrize.pmax.sparse symmetrize matrix max(m[,j], m[j,])symmetrize.pmin.sparse symmetrize matrix min(m[,j], m[j,])","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-symmetrize.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Matrix symmetrizing — matrix-symmetrize","text":"","code":"symmetrize.pmax.sparse(i, j, x, height) symmetrize.pmin.sparse(i, j, x, height)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-symmetrize.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Matrix symmetrizing — matrix-symmetrize","text":"row indices (1-based) j column indices (1-based) x values m[,j] = x height height matrix (number rows)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/matrix-symmetrize.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Matrix symmetrizing — matrix-symmetrize","text":"symmetric sparse dgCMatrix size height x height","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/numeric_lisi-methods.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert a numeric vector to a `numeric_lisi` vector — as.numeric,numeric_lisi-method","title":"Convert a numeric vector to a `numeric_lisi` vector — as.numeric,numeric_lisi-method","text":"Convert numeric vector `numeric_lisi` vector Indexing method `numeric_lisi` (keep `@N` slot) Replicate method numeric_lisi (keep `@N` slot) Value replacement method `numeric_lisi` (check `@N` slot compatibility)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/numeric_lisi-methods.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert a numeric vector to a `numeric_lisi` vector — as.numeric,numeric_lisi-method","text":"","code":"# S4 method for class 'numeric_lisi' as.numeric(x) # S4 method for class 'numeric_lisi,ANY,ANY,ANY' x[i] # S4 method for class 'numeric_lisi' rep(x, ...) # S4 method for class 'numeric_lisi,ANY,ANY,ANY' x[i] <- value"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/numeric_lisi-methods.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert a numeric vector to a `numeric_lisi` vector — as.numeric,numeric_lisi-method","text":"x numeric_lisi vector indices specifying elements extract replace ... passed rep.numeric value value replace ","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/reloadCache.html","id":null,"dir":"Reference","previous_headings":"","what":"Reload cache from disk — reloadCache","title":"Reload cache from disk — reloadCache","text":"Reload cache disk update current list conda environments package environment","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/reloadCache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Reload cache from disk — reloadCache","text":"","code":"reloadCache()"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/reloadCache.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Reload cache from disk — reloadCache","text":"CondaEnvManager object (invisibly)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/resetCache.html","id":null,"dir":"Reference","previous_headings":"","what":"Reset a conda environment — resetCache","title":"Reset a conda environment — resetCache","text":"Reset (unset) conda environment linked provided method. Update cache disk package environment","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/resetCache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Reset a conda environment — resetCache","text":"","code":"resetCache(method = known.methods)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/resetCache.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Reset a conda environment — resetCache","text":"method name method update. One \"combat\", \"harmony\", \"mnn\", \"bbknn\", \"scvi\", \"scanvi\", \"scanorama\", \"trvae\"","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/resetCache.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Reset a conda environment — resetCache","text":"CondaEnvManager object (invisibly)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/saveToCache.html","id":null,"dir":"Reference","previous_headings":"","what":"Save a conda environment manager to cache — saveToCache","title":"Save a conda environment manager to cache — saveToCache","text":"Save conda environment manager cache ( R_user_dir(\"SeuratIntegrate\", = \"config\")) data.frame compressed RDS file.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/saveToCache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Save a conda environment manager to cache — saveToCache","text":"","code":"saveToCache(x, ..., verbose = getOption(\"verbose\")) # S4 method for class 'CondaEnvManager' saveToCache(x)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/saveToCache.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Save a conda environment manager to cache — saveToCache","text":"x CondaEnvManager object ... ignored verbose ignored","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"wrapper run scANVI multi-layered Seurat V5 object. Requires conda environment scvi-tools necessary dependencies Recommendations: use raw counts features (features = Features(object), layers = \"counts\")","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"","code":"scANVIIntegration( object, groups = NULL, groups.name = NULL, labels.name = NULL, labels.null = NULL, features = NULL, layers = \"counts\", scale.layer = \"scale.data\", conda_env = NULL, new.reduction = \"integrated.scANVI\", reduction.key = \"scANVIlatent_\", torch.intraop.threads = 4L, torch.interop.threads = NULL, model.save.dir = NULL, ndims.out = 10, n_hidden = 128L, n_layers = 1L, dropout_rate = 0.1, dispersion = c(\"gene\", \"gene-batch\", \"gene-label\", \"gene-cell\"), gene_likelihood = c(\"zinb\", \"nb\", \"poisson\"), linear_classifier = FALSE, max_epochs = NULL, train_size = 0.9, batch_size = 128L, seed.use = 42L, verbose = TRUE, verbose.scvi = c(\"INFO\", \"NOTSET\", \"DEBUG\", \"WARNING\", \"ERROR\", \"CRITICAL\"), ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) groups named data frame grouping information. Can also contain cell labels guide scANVI. groups.name Column name groups data frame stores grouping information. groups.name = NULL, first column used labels.name Column name groups data frame stores cell label information. labels.name = NULL, cells assigned label. labels.null One value groups$labels.name indicates unlabeled observations. labels.null = NULL means labels valid. applies labels.name != NULL. features Vector feature names input integration method. features = NULL (default), VariableFeatures used. pass features, use output Features() layers Name layers use integration. 'counts' highly recommended scale.layer Name scaled layer Assay conda_env Path conda environment run scANVI (also contain scipy python module). default, uses conda environment registered scANVI conda environment manager new.reduction Name new integrated dimensional reduction reduction.key Key new integrated dimensional reduction torch.intraop.threads Number intra-op threads available torch training CPU instead GPU. Set via torch.set_num_threads(). torch.interop.threads Number intra-op threads available torch training CPU instead GPU. Set via torch.set_num_interop_threads(). Can changed , first call. model.save.dir Path directory save model . Uses SCANVI.save(). save anndata. Note neither trainer optimizer state trainer history saved. model.save.dir = NULL (default) disables saving model. ndims.Number dimensions new.reduction output. Corresponds n_latent argument original API SCANVI n_hidden Number nodes per hidden layer. n_layers Number hidden layers used encoder decoder NNs. dropout_rate Dropout rate neural networks. dispersion One following: gene: dispersion parameter NB constant per gene across cells (default) gene-batch: dispersion can differ different batches gene-label: dispersion can differ different labels gene-cell: dispersion can differ every gene every cell gene_likelihood One following: zinb: Zero-inflated negative binomial distribution (default) nb: Negative binomial distribution poisson: Poisson distribution linear_classifier switched TRUE, uses single linear layer classification instead multi-layer perceptron. max_epochs Number passes dataset semisupervised training. train_size Size training set range [0.0, 1.0] batch_size Minibatch size use training. seed.use integer generate reproducible outputs. Set seed.use = NULL disable verbose Print messages. Set FALSE disable verbose.scvi Verbosity level scANVI. quietest talkiest: CRITICAL, ERROR, WARNING, INFO (default), DEBUG, NOTSET ... Additional arguments passed scvi.model.SCANVI, SCANVI.setup_anndata SCANVI.train (see Details section)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"list containing: new DimReduc name new.reduction (key set reduction.key) consisting latent space model ndims.dimensions. called via IntegrateLayers, Seurat object new reduction /assay returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"wrappers calls three python functions reticulate. Find scVANVI-specific arguments : model initiation: scvi.model.SCANVI, relies scvi.module.SCANVAE turn relies scvi.module.VAE anndata setup: SCANVI.setup_anndata training: SCANVI.train","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"function requires scvi-tools package installed (along scipy)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"Kingma, D. P., Rezende, D. J., Mohamed, S. & Welling, M. Semi- Supervised Learning Deep Generative Models. Preprint arXiv (2014). DOI Xu, C., Lopez, R., Mehlman, E., Regier, J., Jordan, M. . & Yosef, N. Probabilistic harmonization annotation single‐cell transcriptomics data deep generative models. Molecular Systems Biology 17, (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run scANVI on Seurat's Assay5 object through IntegrateLayers — scANVIIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers: obj <- IntegrateLayers(object = obj, method = scANVIIntegration, features = Features(obj), conda_env = 'scvi-tools', layers = 'counts', groups = obj[[]], groups.name = 'Method', labels.name = 'CellType', labels.null = 'Unassigned') # To enable saving the model, add other 'nuisance' factors and increase number of threads used: obj <- IntegrateLayers(object = obj, method = scANVIIntegration, features = Features(obj), conda_env = 'scvi-tools', layers = 'counts', groups = obj[[]], groups.name = \"Method\", labels.name = \"CellType\", labels.null = \"Unassigned\", categorical_covariate_keys = \"Experiment\", continuous_covariate_keys = \"percent.mito\", ncores = 8, model.save.dir = '~/Documents/scANVI.model') } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"wrapper run scVI multi-layered Seurat V5 object. Requires conda environment scvi-tools necessary dependencies Can called via SeuratIntegrate::scVIIntegration() scVIIntegration.fix() Recommendations: use raw counts features (features = Features(object), layers = \"counts\")","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"","code":"scVIIntegration( object, groups = NULL, groups.name = NULL, labels.name = NULL, features = NULL, layers = \"counts\", scale.layer = \"scale.data\", conda_env = NULL, new.reduction = \"integrated.scVI\", reduction.key = \"scVIlatent_\", torch.intraop.threads = 4L, torch.interop.threads = NULL, model.save.dir = NULL, ndims.out = 10, n_hidden = 128L, n_layers = 1L, dropout_rate = 0.1, dispersion = c(\"gene\", \"gene-batch\", \"gene-label\", \"gene-cell\"), gene_likelihood = c(\"zinb\", \"nb\", \"poisson\"), latent_distribution = c(\"normal\", \"ln\"), max_epochs = NULL, train_size = 0.9, batch_size = 128L, seed.use = 42L, verbose = TRUE, verbose.scvi = c(\"INFO\", \"NOTSET\", \"DEBUG\", \"WARNING\", \"ERROR\", \"CRITICAL\"), ... ) scVIIntegration.fix(...)"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) groups named data frame grouping information. groups.name Column name groups data frame stores grouping information. groups.name = NULL, first column used labels.name Column name groups data frame stores cell label information. labels.name = NULL, cells assigned label. features Vector feature names input integration method. features = NULL (default), VariableFeatures used. pass features, use output Features() layers Name layers use integration. 'counts' highly recommended scale.layer Name scaled layer Assay conda_env Path conda environment run scVI (also contain scipy python module). default, uses conda environment registered scVI conda environment manager new.reduction Name new integrated dimensional reduction reduction.key Key new integrated dimensional reduction torch.intraop.threads Number intra-op threads available torch training CPU instead GPU. Set via torch.set_num_threads(). torch.interop.threads Number intra-op threads available torch training CPU instead GPU. Set via torch.set_num_interop_threads(). Can changed , first call. model.save.dir Path directory save model . Uses SCVI.save(). save anndata. Note neither trainer optimizer state trainer history saved. model.save.dir = NULL (default) disables saving model. ndims.Number dimensions new.reduction output. Corresponds n_latent argument original API SCVI n_hidden Number nodes per hidden layer. n_layers Number hidden layers used encoder decoder NNs. dropout_rate Dropout rate neural networks. dispersion One following: gene: dispersion parameter NB constant per gene across cells (default) gene-batch: dispersion can differ different batches gene-label: dispersion can differ different labels gene-cell: dispersion can differ every gene every cell gene_likelihood One following: zinb: Zero-inflated negative binomial distribution (default) nb: Negative binomial distribution poisson: Poisson distribution latent_distribution One following: normal: Normal distribution (default) ln: Logistic normal distribution (Normal(0, ) transformed softmax) max_epochs Number passes dataset semisupervised training. train_size Size training set range [0.0, 1.0] batch_size Minibatch size use training. seed.use integer generate reproducible outputs. Set seed.use = NULL disable verbose Print messages. Set FALSE disable verbose.scvi Verbosity level scVI. quietest talkiest: CRITICAL, ERROR, WARNING, INFO (default), DEBUG, NOTSET ... scVIIntegration(), additional arguments passed scvi.model.SCVI, SCVI.setup_anndata SCVI.train (see Details section). scVIIntegration.fix(), ","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"list containing: new DimReduc name new.reduction (key set reduction.key) consisting latent space model ndims.dimensions. called via IntegrateLayers, Seurat object new reduction /assay returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"wrappers calls three python functions reticulate. Find scVI-specific arguments : model initiation: scvi.model.SCVI, relies scvi.module.VAE anndata setup: SCVI.setup_anndata training: SCVI.train","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"function requires scvi-tools package installed (along scipy)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"Lopez, R., Regier, J., Cole, M. B., Jordan, M. . & Yosef, N. Deep generative modeling single-cell transcriptomics. Nat Methods 15, 1053–1058 (2018). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run scVI on Seurat's Assay5 object through IntegrateLayers — scVIIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers: obj <- IntegrateLayers(object = obj, method = scVIIntegration, features = Features(obj), conda_env = 'scvi-tools', layers = 'counts', groups = obj[[]], groups.name = 'Method') # To enable cell label-guided correction, save the model, add other # 'nuisance' factors and increase number of threads used: obj <- IntegrateLayers(object = obj, method = scVIIntegration, features = Features(obj), conda_env = 'scvi-tools', layers = 'counts', groups = obj[[]], groups.name = \"Method\", labels.name = \"CellType\", categorical_covariate_keys = list(\"Experiment\"), continuous_covariate_keys = list(\"percent.mito\"), ncores = 8, model.save.dir = '~/Documents/scVI.model') } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a clustering result with adjusted rand index — ScoreARI","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"Compute score based adjusted rand index clustering result one cell type label variable(s). 0 1 reflect random clustering perfect clustering compared cell type labelling respectively.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"","code":"ScoreARI(object, cell.var, clust.var = \"seurat_clusters\") AddScoreARI(object, integration, cell.var, clust.var = \"seurat_clusters\")"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"object Seurat object cell.var name(s) column(s) cell type label variable (must object metadata). Multiple column names accepted clust.var name column cluster id assignment cell (must object metadata). one column name accepted integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"ScoreARI: named array many values common strings cell.var column names object's metadata. Names cell.var values ARI. AddScoreARI: updated Seurat object ARI score(s) set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"ARI rand index corrected chance: $$\\displaystyle ARI = \\frac{RI - RI_{expected}}{max(RI) - RI_{expected}}$$ precisely, contingency table computed two variables \\(L\\) \\(C\\) \\(r\\) \\(s\\) elements respectively. \\(\\[\\![1,r]\\!]\\) \\(j \\[\\![1,s]\\!]\\), \\(n_{ij}\\) number common samples (.e. cells) \\(L_i\\) \\(C_j\\), \\(a_i\\) number samples \\(L_i\\) \\(b_j\\) number samples \\(C_j\\). ARI : $$\\displaystyle ARI = \\frac{\\left. \\sum_{ij} \\binom{n_{ij}}{2} - \\left(\\sum_i \\binom{a_i}{2} \\sum_j \\binom{b_j}{2}\\right) \\right/ \\binom{n}{2} }{ \\left. \\frac{1}{2} \\left(\\sum_i \\binom{a_i}{2} + \\sum_j \\binom{b_j}{2}\\right) - \\left(\\sum_i \\binom{a_i}{2} \\sum_j \\binom{b_j}{2}\\right) \\right/ \\binom{n}{2}}$$","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"metric symmetric. Switching cell.var clust.var return value.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-ari.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a clustering result with adjusted rand index — ScoreARI","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":null,"dir":"Reference","previous_headings":"","what":"Score an embedding or a count matrix with the average silhouette width — score-asw","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"Compute scores based average silhouette width (ASW) metric. ScoreASW: First, cell--cell distances computed provided embedding layer matrix. , silhouette score calculated estimate quality partition according variable cell type labels. Hence, score measures extent cells identical label cluster together. ScoreASWBatch: Similar, batch variable. score provides estimation batch mixing.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"","code":"ScoreASW( object, cell.var, what, assay = NULL, metric = c(\"euclidean\", \"cosine\", \"angular\", \"manhattan\", \"hamming\"), dist.package = c(\"distances\", \"Rfast\", \"parallelDist\", \"stats\"), verbose = TRUE, ... ) AddScoreASW( object, integration, cell.var, what, assay = NULL, metric = c(\"euclidean\", \"cosine\", \"angular\", \"manhattan\", \"hamming\"), dist.package = c(\"distances\", \"Rfast\", \"parallelDist\", \"stats\"), verbose = TRUE, ... ) ScoreASWBatch( object, batch.var = NULL, cell.var = NULL, what, per.cell.var = TRUE, assay = NULL, metric = c(\"euclidean\", \"cosine\", \"angular\", \"manhattan\", \"hamming\"), dist.package = c(\"distances\", \"Rfast\", \"parallelDist\", \"stats\"), verbose = TRUE, ... ) AddScoreASWBatch( object, integration, batch.var = NULL, cell.var = NULL, what, per.cell.var = TRUE, assay = NULL, metric = c(\"euclidean\", \"cosine\", \"angular\", \"manhattan\", \"hamming\"), dist.package = c(\"distances\", \"Rfast\", \"parallelDist\", \"stats\"), verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"object Seurat object cell.var name column cell type label variable (must object metadata). Ignored ScoreASWBatch per.cell.var = FALSE name dimension reduction layer score. Must Seurat object obtainable JoinLayers() call. assay name assay use. output DefaultAssay() used default metric name distance metric use. One 'euclidean', 'cosine', 'angular', 'manhattan', 'hamming'. See Note details. dist.package name package compute distances . One 'distances', 'Rfast' ,'parallelDist', 'stats'. latter always available, others must installed beforehand. ordered fastest slowest. requested package installed, fastest amongst available ones picked. See Note details. verbose Print messages. Set FALSE disable ... additional parameters pass distance computation functions integration name integration score batch.var name column batch variable. (must object metadata). Required ScoreASWBatch. per.cell.var whether compute silhouette coefficients batch variable cell-type separately (default behaviour). Setting FALSE causes silhouette coefficients computed whole data directly.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"ScoreASW ScoreASWBatch: single float 0 1, corresponding scaled average silhouette score. AddScoreASW AddScoreASWBatch: updated Seurat object ASW score(s) set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"ScoreASW: Given matrix (reduction dimension layer), cell--cell distance matrix \\(D\\) computed. , silhouette width \\(s()\\) calculated cell \\(\\) label \\(c \\L\\) (\\(L\\) set possible cell type labels). , mean \\(s()\\) computed (.e. ASW) scaled 0 1: $$\\displaystyle ASW = \\frac{1}{\\left| L \\right|} \\times \\sum_{}{s()} \\\\[10pt] score = \\frac{ASW + 1}{2}$$ ScoreAWSBatch: default parameters (per.cell.var = TRUE) correspond original score Luecken M.D. et al., 2022. computed follow: cell type label \\(c\\) among set labels \\(L\\), cell--cell matrix distance \\(D_c\\) computed cells \\(\\) label \\(c\\). cell's silhouette width \\(s()\\) calculated according batch variable transformed close 1 absolute value close 0. average silhouette width \\(ASW_c\\) computed per cell type label \\(c \\L\\) mean correspond final score: $$\\displaystyle ASW_c = \\frac{1}{\\left| c \\right|} \\times \\sum_{\\c}{1 - \\left| s() \\right|} \\\\[10pt] score = \\frac{1}{\\left| L \\right|} \\times \\sum_{c \\L}{ASW_c}$$ per.cell.var = FALSE, \\(ASW\\) computed cells (just like ScoreASW batch variable), scaled averaged similarly: $$\\displaystyle score = ASW = \\frac{1}{N} \\times \\sum_{=1}^{N}{1 - \\left| s() \\right|}$$ \\(N\\) total number cells","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"scores adaptation (cell-type) ASW batch ASW described Luecken M.D. et al., 2022. Hamming distance supported parallelDist package, distances can compute euclidean related distances (cosine angular). Angular distances actually refereed 'cosine' FindNeighbors() (annoy.metric), hence called 'angular' . Actual cosine dissimilarity-derived distances returned metric = 'cosine'. Internally, angular distances computed euclidean distances \\(L^2\\) norm. cosine distances transformed : $$\\displaystyle D_{cosine} = \\frac{D_{angular}^2}{2}$$","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-asw.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score an embedding or a count matrix with the average silhouette width — score-asw","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"Linearly regresses S G2M scores predict principal components. resulting R2 weighted dimension's contribution variance. Cell cycles scores PCAs computed batch independently.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"","code":"ScoreRegressPC.CellCycle( object, batch.var = NULL, what = NULL, dims.use = NULL, npcs = 50L, s.var = \"S.Score\", g2m.var = \"G2M.Score\", compute.cc = TRUE, s.features = NULL, g2m.features = NULL, assay = NULL, weight.by = c(\"var\", \"stdev\"), adj.r2 = FALSE, approx = FALSE ) AddScoreRegressPC.CellCycle( object, integration, batch.var = NULL, what = NULL, dims.use = NULL, npcs = 50L, s.var = \"S.Score\", g2m.var = \"G2M.Score\", compute.cc = TRUE, s.features = NULL, g2m.features = NULL, assay = NULL, weight.by = c(\"var\", \"stdev\"), adj.r2 = FALSE, approx = FALSE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"object Seurat object batch.var name batch variable (must object metadata) slot Seurat score. Can layer reduction. dims.use dimensions consider. dimensions used default npcs Total Number PCs compute store (50 default) s.var name S phase score variable (must object metadata) g2m.var name G2M phase score variable (must object metadata) compute.cc whether (re-)compute cell cycle scores. TRUE (default), unless run CellCycleScoringPerBatch beforehand cell cycles scores expected computed per batch s.features vector features associated S phase g2m.features vector features associated G2M phase assay assay use. Passed Seurat automatically construct batch.var provided. Useless otherwise weight.one 'var' (default) 'stdev' (standing variance standard deviation respectively). Use variance standard deviation explained principal components weight PC's score. adj.r2 Whether use adjusted R2 instead raw R2 approx Use truncated singular value decomposition approximate PCA integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"ScoreRegressPC.CellCycle: 2-columns data frame batch variable first one corresponding score second one. many rows batches. AddScoreRegressPC.CellCycle: updated Seurat object cell cycle conservation score set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"linear regression $$PC_i = S_{score} + G2M_{score}$$ score computed follow : $$\\sum_{=1}^{p} \\left ( R^2_i * V_i \\right )$$ PCA p dimensions, \\(PC_i\\) principal component , \\(R^2_i\\) R squared coefficient linear regression dimension . \\(V_i\\) proportion variance explained \\(PC_i\\).","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"score adaptation principal component regression (PCR) score Luecken M.D. et al., 2022.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-cc.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Score a corrected or uncorrected PCA to estimate the contribution of S and G2M scores to variance — ScoreRegressPC.CellCycle","text":"","code":"if (FALSE) { # \\dontrun{ obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) score.cc.r2 <- ScoreRegressPC.CellCycle(obj, \"Method\", \"pca\", dim.use = 1:30) score.cc.adj.r2 <- ScoreRegressPC.CellCycle(obj, \"Method\", \"pca\", dim.use = 1:30, adj.r2 = TRUE) score.cc.r2 # ~ 0.0249 score.cc.adj.r2 # ~ 0.0249 } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"Compute scores based connectivity cells sharing label. score can calculated two fashions, either quantifying connectivity largest subgraph cell label (identical score used Luecken M.D. et al., 2022), directly whole graph.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"","code":"ScoreConnectivity( object, graph.name, cell.var, do.symmetrize = TRUE, per.component = TRUE, count.self = FALSE, weight.by.ncells = FALSE ) AddScoreConnectivity( object, integration, graph.name, cell.var, do.symmetrize = TRUE, per.component = TRUE, count.self = FALSE, weight.by.ncells = FALSE )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"object Seurat object graph.name name knn graph score. cell.var name cell variable (must object metadata). .symmetrize whether symmetrize knn graph. Set toFALSE disable (recommended, see Details) per.component whether use score Luecken M.D. et al., 2022. TRUE default. See Details. count.self whether account loops (.e. cells connected ). FALSE default weight..ncells whether weight connectivity-derived scores computed cell type label relative proportion number cells. default (FALSE), overall score computed mean scores computed per label. Ignored per.component = TRUE integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"ScoreConnectivity: single float 0 1, corresponding connectivity score. AddScoreConnectivity: updated Seurat object Graph connectivity score set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"default parameters (per.component = TRUE, count.self = FALSE) correspond original score Luecken M.D. et al., 2022. computed follow: cell type label \\(c\\) among set labels \\(L\\), sub graph \\(subG_c\\) exclusively composed cells \\(c\\) extracted full graph \\(G\\). , size (.e. number cells, hence vertices \\(V\\)) largest connected component divided size \\(subG_c\\). , mean sub graphs' scores computed: $$ratio_c = \\frac{max(\\left|V(CC(subG_c))\\right|)}{\\left|V(subG_c)\\right|}$$ $$score = \\frac{1}{\\left| L \\right|}\\sum_{c \\L} ratio_c$$ per.component = FALSE, connectivity computed full graph \\(G\\). consider set labels \\(L\\), \\(c \\L\\) \\(L\\prime = L \\setminus \\{c\\}\\). also denote edges cells \\(\\\\{c\\}\\) \\(E_c = E_{c \\c}(G)\\) edges connecting cells \\(\\\\{c\\}\\) cells \\(\\L\\prime\\) \\(E_c^{\\prime} = E_{c \\L\\prime}(G)\\). weight..ncells = TRUE, score computed follow: $$score = \\sum_{c \\L} \\left( \\frac{\\left| V(subG_c) \\right|}{\\left| V(G) \\right|} \\times \\frac{\\left| E_c \\right|}{\\left| E_c^\\prime \\right| + \\left| E_c \\right|}\\right)$$ weight..ncells = FALSE, score mean ratio edges: $$score = \\frac{1}{\\left| L \\right|}\\sum_{c \\L} \\frac{\\left| E_c \\right|}{\\left| E_c^\\prime \\right| + \\left| E_c \\right|}$$ either case, recommended keep .symmetrize = TRUE.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"score adaptation graph connectivity score described Luecken M.D. et al., 2022.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a knn graph based on cell-type label connectivity — ScoreConnectivity","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"batch-wise kernel density estimate computed dimension PCA. , global area shared kernels calculated divided reference area (see Arguments Details) proxy batch mixing. Finally, aforementioned proportions weighted dimension's contribution variance.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"","code":"ScoreDensityPC( object, batch.var = NULL, reduction = \"pca\", dims = NULL, use.union = TRUE, bw.join = mean, bw.kernel = c(\"nrd0\", \"nrd\", \"ucv\", \"bcv\", \"sj\"), weight.by = c(\"var\", \"stdev\"), assay = NULL, layer = NULL ) AddScoreDensityPC( object, integration, batch.var = NULL, reduction = \"pca\", dims = NULL, use.union = TRUE, bw.join = mean, bw.kernel = c(\"nrd0\", \"nrd\", \"ucv\", \"bcv\", \"sj\"), weight.by = c(\"var\", \"stdev\"), assay = NULL, layer = NULL )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"object Seurat object batch.var name batch variable (must object metadata) reduction name reduction score dims dimensions consider. dimensions used default use.union Whether use union densities (constructs fake density pmax). alternative use density kernels sum bw.join function pick joint bandwidth. default use mean(). can also chose median instance. want use distinct bandwidth batch, just set bw.join = c (recommended) bw.kernel Bandwidth selector use Gaussian kernel density estimation. One 'nrd0', 'nrd', 'ucv','bcv' 'sj' (see bandwidths). nrd0 default weight.one 'var' (default) 'stdev' (standing variance standard deviation respectively). Use variance standard deviation explained principal components weight PC's score. assay assay use. Passed Seurat automatically construct batch.var provided. Useless otherwise layer layer use. Passed Seurat automatically construct batch.var provided. Useless otherwise integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"ScoreDensityPC: single float corresponding score given reduction AddScoreDensityPC: updated Seurat object density PCA score set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"score computed follow : $$\\sum_{=1}^{p} \\left ( \\cfrac{ \\bigcup_{b=1}^n D_{bi} }{ Ref_i } * V_i \\right )$$ PCA p dimensions n batchs. \\(D_{bi}\\) vector density batch b dimension . \\(V_i\\) proportion variance explained \\(PC_i\\). \\(Ref = \\bigcap_{=1}^n D_{bi}\\) \\(Ref = \\sum_{=1}^n D_{bi}\\) use.union TRUE FALSE respectively, given dimension \\(\\). use.union = FALSE tends result lower score since reference sum kernel densities instead maximum","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"score adaptation principal component regression (PCR) score Luecken M.D. et al., 2022.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreDensityPC","text":"","code":"if (FALSE) { # \\dontrun{ obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) score.union <- ScoreDensityPC(obj, \"Method\", \"pca\", dim = 1:30) score.sum <- ScoreDensityPC(obj, \"Method\", \"pca\", dim = 1:30, use.union = FALSE) score.union # ~ 0.1511 score.sum # ~ 0.0319 } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-kbet.html","id":null,"dir":"Reference","previous_headings":"","what":"Score an embedding or a knn graph with the kBET test — ScoreKBET","title":"Score an embedding or a knn graph with the kBET test — ScoreKBET","text":"Compute scores based k-nearest neighbour batch effect test (kBET). Accepts DimReduc instance graph object (Graph Neighbor) provided contains distances connectivities. '' DimReduc object, knn graph computed k = 50. , ('' Graph Neighbor object), connectivities derives 50 nearest neighbours distances. Finally, kBET test computed cell-type label provided cell.var. kBET measures local batch label distribution similar global one. result kBET average test rejection rate (0 1). closest zero, less bias attributable batch effect.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-kbet.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score an embedding or a knn graph with the kBET test — ScoreKBET","text":"","code":"ScoreKBET( object, batch.var, cell.var, what, graph.type = c(\"distances\", \"connectivities\"), seed.use = 42L, verbose = TRUE, assay = NULL, layer = NULL ) AddScoreKBET( object, integration, batch.var, cell.var, what, graph.type = c(\"distances\", \"connectivities\"), seed.use = 42L, verbose = TRUE, assay = NULL, layer = NULL )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-kbet.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score an embedding or a knn graph with the kBET test — ScoreKBET","text":"object Seurat object batch.var name batch variable (must object metadata) cell.var name column cell type label variable (must object metadata). NULL passed, kBET score computed cells . name dimension reduction Graph/Neighbor object score. Must Seurat object. graph.type one 'distances' (default) 'connectivities', indicate type graph dimension reduction. seed.use value seed obtain reproducible results. NULL disables use seed verbose whether print progress messages assay assay use. Passed Seurat automatically construct batch.var provided (DefaultAssay() used default). Useless otherwise layer layer use. Passed Seurat automatically construct batch.var provided. Useless otherwise integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-kbet.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score an embedding or a knn graph with the kBET test — ScoreKBET","text":"ScoreKBET: list one element per cell.var. named numeric vector kBET score (floats 0 1), one per cell-label. AddScoreKBET: updated Seurat object mean kBET score(s) set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-kbet.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score an embedding or a knn graph with the kBET test — ScoreKBET","text":"Büttner, M., Miao, Z., Wolf, F. ., Teichmann, S. . & Theis, F. J. test metric assessing single-cell RNA-seq batch correction. Nat Methods 16, 43–49 (2018). DOI Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"Compute Local Inverse Simpson's Index (LISI) estimate batch mixing cell type mixing (iLISI cLISI respectively according Luecken M.D. et al., 2022). AddScoreLISI returns updated Seurat object, ScoreLISI outputs raw LISI scores cell","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"","code":"AddScoreLISI( object, integration, batch.var = NULL, cell.var = NULL, reduction, dims = NULL, graph.name, graph.type = c(\"distances\", \"connectivities\"), do.symmetrize = TRUE, save.graph = TRUE, new.graph = NULL, perplexity = 30, tol = 1e-05, do.scale = TRUE, largest.component.only = FALSE, assay = NULL, verbose = TRUE, ... ) ScoreLISI( object, batch.var = NULL, cell.var = NULL, reduction, dims = NULL, graph.name, graph.type = c(\"distances\", \"connectivities\"), do.symmetrize = TRUE, return.graph = FALSE, perplexity = 30, tol = 1e-05, largest.component.only = FALSE, assay = NULL, verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"object Seurat object integration name integration score batch.var name batch variable (must object metadata). Can omitted cell.var NULL cell.var name cell variable (must object metadata). Can omitted batch.var NULL reduction name reduction score. Arguments reduction graph.name mutually exclusive dims dimensions reduction consider. dimensions used default. Ignored scoring graph graph.name name knn graph score. Arguments reduction graph.name mutually exclusive graph.type one 'distances' 'connectivities' (supported yet). Ignored scoring cell embedding .symmetrize whether symmetrize knn graphs. Set toFALSE disable (recommended, especially scoring knn graph directly. See Details) save.graph whether save graph used compute LISI score(s) Seurat object new.graph name graph used compute LISI score(s). new.graph = NULL (default), name constructed depending input arguments. Ignored save.graph = FALSE perplexity third number cell's neighbours. value perplexity number neighbours (*3) discrepant, graph adapted. Multiple scores varying values perplexity comparable, hence recommended use value integration score. tol Stop computation local Simpson's index converges tolerance. .scale whether scale output LISI values 0 1. largest.component.whether compute scores largest component sufficiently large components (default) assay name assay reference output Graph object ( save.graph = TRUE) verbose whether print progress messages ... Additional parameters pass methods (see Details). return.graph whether return graph used compute LISI score(s)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"ScoreLISI: data frame cell's raw LISI score, list containing aforementioned data frame graph used compute (return.graph = TRUE). AddScoreLISI: updated Seurat object, cell-wise LISI scores meta data (identical ScoreLISI's output), global scores misc new Graph object save.graph = TRUE.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"scoring reduction, knn graph enough neighbours per cell computed. .symmetrize = TRUE, graph symmetrized k best neighbours kept. scoring knn graph, graph expanded Dijkstra's algorithm reach enough neighbours per cell. .symmetrize = TRUE, graph symmetrized beforehand. Note .symmetrize = FALSE, Dijkstra's algorithm applied asymmetric distance matrix, components computed. component symmetrized Dijkstra's algorithm computed . Indeed, guarantee cells' number neighbours preserved decomposing directed graph. Hence, .symmetrize = FALSE graph input, graph considered directed find components. either case, recommended keep .symmetrize = TRUE. possible additional parameters, see FindNeighbors (inputting reduction) ExpandNeighbours (inputting knn graph)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"score adaptation LISI score described Korsunsky . et al., 2019 also used Luecken M.D. et al., 2022.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a dimensionality reduction embedding or knn graph using the Local Inverse Simpson Index — AddScoreLISI","text":"Korsunsky, ., Millard, N., Fan, J., Slowikowski, K., Zhang, F., Wei, K., Baglaenko, Y., Brenner, M., Loh, P. & Raychaudhuri, S. Fast, sensitive accurate integration single-cell data Harmony. Nat Methods 16, 1289–1296 (2019). DOI Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a clustering result with normalised mutual information — ScoreNMI","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"Compute score based normalised mutual information clustering result one cell type label variable(s). 0 1 reflect absence mutual information perfect correlation respectively.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"","code":"ScoreNMI( object, cell.var, clust.var = \"seurat_clusters\", average.entropy = c(\"mean\", \"geom\", \"min\", \"max\") ) AddScoreNMI( object, integration, cell.var, clust.var = \"seurat_clusters\", average.entropy = c(\"mean\", \"geom\", \"min\", \"max\") )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"object Seurat object cell.var name(s) column(s) cell type label variable (must object metadata). Multiple column names accepted clust.var name column cluster id assignment cell (must object metadata). one column name accepted average.entropy method compute value normalisation denominator variable's entropy. one 'mean', 'geom', 'min' 'max', namely 'arithmetic mean ', 'geometric mean ', 'minimum' 'maximum' entropy respectively. integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"ScoreNMI: named array many values common strings cell.var column names object's metadata. Names cell.var values NMI scores. AddScoreNMI: updated Seurat object NMI score(s) set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"Considering \\(N\\)-cells dataset, \\(\\left|L_i\\right|\\) number cells labelled cell type \\(L_i\\) \\(\\left|C_i\\right|\\) number cells cluster \\(C_i\\). discrete mutual information \\(MI\\) approximation given : $$\\displaystyle MI(L, C) = \\sum_{=1}^{\\left|L\\right|}\\sum_{j=1}^{\\left|C\\right|} \\left( \\frac{\\left|L_i \\cap C_j\\right|}{N} \\times log \\left(\\frac{N \\times \\left|L_i \\cap C_j\\right|}{\\left|L_i\\right| \\left|C_j\\right|} \\right) \\right)$$ , \\(MI\\) normalised (scaled) denominator, computed applying function \\(f\\) variables' entropies (\\(H\\)). \\(f\\) can either arithmetic mean, geometric mean, maximum minimum entropies. $$\\displaystyle NMI(L, C) = \\frac{MI(L, C)}{f(H(L), H(C))}$$","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"metric symmetric. Switching cell.var clust.var return value.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a clustering result with normalised mutual information — ScoreNMI","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":null,"dir":"Reference","previous_headings":"","what":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"Linearly regresses principal components batch variable proxy estimate batch mixing. resulting R2 weighted dimension's contribution variance.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"","code":"ScoreRegressPC( object, batch.var = NULL, reduction = \"pca\", dims = NULL, adj.r2 = FALSE, weight.by = c(\"var\", \"stdev\"), assay = NULL, layer = NULL ) AddScoreRegressPC( object, integration, batch.var = NULL, reduction = \"pca\", dims = NULL, adj.r2 = FALSE, weight.by = c(\"var\", \"stdev\"), assay = NULL, layer = NULL )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"object Seurat object batch.var name batch variable (must object metadata) reduction name reduction score dims dimensions consider. dimensions used default adj.r2 Whether use adjusted R2 instead raw R2 weight.one 'var' (default) 'stdev' (standing variance standard deviation respectively). Use variance standard deviation explained principal components weight PC's score. assay assay use. Passed Seurat automatically construct batch.var provided. Useless otherwise layer layer use. Passed Seurat automatically construct batch.var provided. Useless otherwise integration name integration score","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"ScoreRegressPC: single float corresponding score given reduction AddScoreRegressPC: updated Seurat object regression PCA score set integration.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"linear regression $$PC_i = Batch$$ score computed follow : $$\\sum_{=1}^{p} \\left ( R^2_i * V_i \\right )$$ PCA p dimensions, \\(PC_i\\) principal component , \\(R^2_i\\) R squared coefficient linear regression dimension . \\(V_i\\) proportion variance explained \\(PC_i\\).","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"score adaptation principal component regression (PCR) score Luecken M.D. et al., 2022.","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"Luecken, M. D., Büttner, M., Chaichoompu, K., Danese, ., Interlandi, M., Mueller, M. F., Strobl, D. C., Zappia, L., Dugas, M., Colomé-Tatché, M. & Theis, F. J. Benchmarking atlas-level data integration single-cell genomics. Nat Methods 19, 41–50 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Score a corrected or uncorrected PCA to estimate batch mixing — ScoreRegressPC","text":"","code":"if (FALSE) { # \\dontrun{ obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) score.r2 <- ScoreRegressPC(obj, \"Method\", \"pca\", dim = 1:30) score.adj.r2 <- ScoreRegressPC(obj, \"Method\", \"pca\", dim = 1:30, adj.r2 = TRUE) score.r2 # ~ 0.1147 score.adj.r2 # ~ 0.1145 } # }"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":null,"dir":"Reference","previous_headings":"","what":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"wrapper run trVAE multi-layered Seurat V5 object. Requires conda environment scArches necessary dependencies Recommendations: use raw counts (except recon.loss = \"mse\") features (features = Features(object), layers = \"counts\", scale.layer = NULL).","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"","code":"trVAEIntegration( object, orig = NULL, groups = NULL, groups.name = NULL, surgery.name = NULL, surgery.sort = TRUE, features = NULL, layers = ifelse(recon.loss == \"mse\", \"data\", \"counts\"), scale.layer = \"scale.data\", conda_env = NULL, new.reduction = \"integrated.trVAE\", reduction.key = \"trVAElatent_\", torch.intraop.threads = 4L, torch.interop.threads = NULL, model.save.dir = NULL, ndims.out = 10L, recon.loss = c(\"nb\", \"zinb\", \"mse\"), hidden_layer_sizes = c(256L, 64L), dr_rate = 0.05, use_mmd = TRUE, mmd_on = c(\"z\", \"y\"), mmd_boundary = NULL, beta = 1, use_bn = FALSE, use_ln = TRUE, n_epochs = 400L, lr = 0.001, eps = 0.01, hide.py.warn = T, seed.use = 42L, verbose = TRUE, ... )"},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"object Seurat object (Assay5 object called IntegrateLayers) orig DimReduc object. set directly called IntegrateLayers, use orig.reduction argument instead groups named data frame grouping information. Can also contain surgery groups perform surgery integration. groups.name Column name groups data frame stores grouping information. groups.name = NULL, first column used surgery.name Column name groups data frame stores surgery information. surgery.name = NULL, one shot integration performed surgery.sort change order surgery groups integrated. default (surgery.sort = TRUE), surgery groups ordered name. FALSE, group integrated order first occurrence column surgery.name features Vector feature names input integration method. features = NULL (default), VariableFeatures used. pass features, use output Features() layers Name layers use integration scale.layer Name scaled layer Assay conda_env Path conda environment run trVAE (also contain scipy python module). default, uses conda environment registered trVAE conda environment manager new.reduction Name new integrated dimensional reduction reduction.key Key new integrated dimensional reduction torch.intraop.threads Number intra-op threads available torch training CPU instead GPU. Set via torch.set_num_threads(). torch.interop.threads Number intra-op threads available torch training CPU instead GPU. Set via torch.set_num_interop_threads(). Can changed , first call. model.save.dir Path directory save model(s) . Uses TRVAE.save(). save anndata. model.save.dir = NULL (default) disables saving model(s). ndims.Number dimensions new.reduction output. Corresponds latent_dim argument original API TRVAE scArches recon.loss Definition Reconstruction-Loss-Method. One 'mse', 'nb' 'zinb' (hence mean squared error, negative binomial zero-inflated negative binomial respectively). Recommended set layer = \"data\" 'mse' (layer = \"counts\" (zi)nb) hidden_layer_sizes Hidden layer sizes encoder network dr_rate Dropout rate applied layers. dr_rate = 0 disables dropout. use_mmd Whether additional MMD loss calculated latent dim. (see next argument) mmd_on Choose layer MMD loss calculated . One 'z' latent dim 'y' first decoder layer. applies use_mmd = TRUE mmd_boundary many groups MMD loss calculated . mmd_boundary = NULL (default), MMD calculated groups. applies use_mmd = TRUE beta Scaling factor MMD loss (1 default). applies use_mmd = TRUE use_bn Whether apply batch normalization layers use_ln Whether apply layer normalization layers n_epochs Maximum number epochs train model lr Learning rate training eps torch.optim.Adam eps parameter improve numerical stability (see ) hide.py.warn Disables uninformative warnings torch seed.use integer generate reproducible outputs. Set seed.use = NULL disable verbose Print messages. Set FALSE disable ... Additional arguments passed scarches.models.TRVAE.train, TRVAE.load_query_data TRVAE.get_latent (see Details section)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"list containing: Without surgery groups: new DimReduc name new.reduction (key set reduction.key) consisting latent space model ndims.dimensions. surgery groups: one new DimReduc per surgery groups name new.reduction_[surgery.group] (key set reduction.key[surgery.group]) consisting latent space corresponding models ndims.dimensions, well 'full' latent representation name new.reduction_[surgery1]_[surgery2]_... key set reduction.keyFull-. called via IntegrateLayers, Seurat object new reduction /assay returned","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"wrappers calls three four python functions reticulate. Find trVAE-specific arguments : model initiation: scarches.models.TRVAE training: TRVAE.train, relies scarches.trainers.trvae.train.Trainer post-training: scarches.models.base._base.CVAELatentsMixin.get_latent surgery initiation: scarches.models.base._base.SurgeryMixin.load_query_data Note seed.use passed torch.manual_seed(). sufficient achieve full reproducibility, set mean = TRUE mean_var = TRUE","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"note","dir":"Reference","previous_headings":"","what":"Note","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"function requires scArches package installed (along scipy)","code":""},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"references","dir":"Reference","previous_headings":"","what":"References","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"Lotfollahi, M., Naghipourfar, M., Theis, F. J. & Wolf, F. . Conditional --distribution generation unpaired data using transfer VAE. Bioinformatics 36, i610–i617 (2020). DOI Lotfollahi, M., Naghipourfar, M., Luecken, M. D., Khajavi, M., Büttner, M., Wagenstetter, M., Avsec, Ž., Gayoso, ., Yosef, N., Interlandi, M., Rybakov, S., Misharin, . V. & Theis, F. J. Mapping single-cell data reference atlases transfer learning. Nat Biotechnol 40, 121–130 (2021). DOI","code":""},{"path":[]},{"path":"https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run trVAE on Seurat's Assay5 object through IntegrateLayers — trVAEIntegration","text":"","code":"if (FALSE) { # \\dontrun{ # Preprocessing obj <- SeuratData::LoadData(\"pbmcsca\") obj[[\"RNA\"]] <- split(obj[[\"RNA\"]], f = obj$Method) obj <- NormalizeData(obj) obj <- FindVariableFeatures(obj) obj <- ScaleData(obj) obj <- RunPCA(obj) # After preprocessing, we integrate layers: obj <- IntegrateLayers(object = obj, method = trVAEIntegration, features = Features(obj), scale.layer = NULL, layers = 'counts', groups = obj[[]], groups.name = 'Method') # To enable surgery and full reproducibility and change the recon loss method: obj <- IntegrateLayers(object = obj, method = trVAEIntegration, features = Features(obj), scale.layer = NULL, layers = 'data', groups = obj[[]], groups.name = 'Method', surgery.name = 'Experiment', mean_var = TRUE, recon.loss = 'mse') } # }"}] diff --git a/site.webmanifest b/site.webmanifest new file mode 100644 index 0000000..4ebda26 --- /dev/null +++ b/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..5417a71 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,65 @@ + +https://cbib.github.io/Seurat-Integrate/404.html +https://cbib.github.io/Seurat-Integrate/LICENSE-text.html +https://cbib.github.io/Seurat-Integrate/LICENSE.html +https://cbib.github.io/Seurat-Integrate/articles/SeuratIntegrate.html +https://cbib.github.io/Seurat-Integrate/articles/index.html +https://cbib.github.io/Seurat-Integrate/articles/introduction.html +https://cbib.github.io/Seurat-Integrate/articles/memo_integration.html +https://cbib.github.io/Seurat-Integrate/articles/memo_score.html +https://cbib.github.io/Seurat-Integrate/articles/setup_and_tips.html +https://cbib.github.io/Seurat-Integrate/authors.html +https://cbib.github.io/Seurat-Integrate/index.html +https://cbib.github.io/Seurat-Integrate/reference/CellCycleScoringPerBatch.html +https://cbib.github.io/Seurat-Integrate/reference/CombatIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/CondaEnv-class.html +https://cbib.github.io/Seurat-Integrate/reference/CondaEnv.html +https://cbib.github.io/Seurat-Integrate/reference/CondaEnvManager-class.html +https://cbib.github.io/Seurat-Integrate/reference/CondaManager.html +https://cbib.github.io/Seurat-Integrate/reference/CutKnn.html +https://cbib.github.io/Seurat-Integrate/reference/DoIntegrate.html +https://cbib.github.io/Seurat-Integrate/reference/ExpandNeighbours.html +https://cbib.github.io/Seurat-Integrate/reference/FindOptimalClusters.html +https://cbib.github.io/Seurat-Integrate/reference/GetConnectivities.html +https://cbib.github.io/Seurat-Integrate/reference/GetNeighborsPerBatch.html +https://cbib.github.io/Seurat-Integrate/reference/GetPropInterBatch.html +https://cbib.github.io/Seurat-Integrate/reference/GetPropIntraBatch.html +https://cbib.github.io/Seurat-Integrate/reference/HarmonyIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/MNNIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/NormaliseL2.html +https://cbib.github.io/Seurat-Integrate/reference/PlotScores.html +https://cbib.github.io/Seurat-Integrate/reference/ScaleScores.html +https://cbib.github.io/Seurat-Integrate/reference/ScanoramaIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/SetMiscScore.html +https://cbib.github.io/Seurat-Integrate/reference/SeuratIntegrate-package.html +https://cbib.github.io/Seurat-Integrate/reference/SymmetrizeKnn.html +https://cbib.github.io/Seurat-Integrate/reference/UpdateEnvCache.html +https://cbib.github.io/Seurat-Integrate/reference/add-score.html +https://cbib.github.io/Seurat-Integrate/reference/bbknnIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/checkCondaEnv.html +https://cbib.github.io/Seurat-Integrate/reference/get-score.html +https://cbib.github.io/Seurat-Integrate/reference/getCache.html +https://cbib.github.io/Seurat-Integrate/reference/getCachePath.html +https://cbib.github.io/Seurat-Integrate/reference/index.html +https://cbib.github.io/Seurat-Integrate/reference/isValid.html +https://cbib.github.io/Seurat-Integrate/reference/matrix-indexing.html +https://cbib.github.io/Seurat-Integrate/reference/matrix-sorting.html +https://cbib.github.io/Seurat-Integrate/reference/matrix-symmetrize.html +https://cbib.github.io/Seurat-Integrate/reference/numeric_lisi-methods.html +https://cbib.github.io/Seurat-Integrate/reference/reloadCache.html +https://cbib.github.io/Seurat-Integrate/reference/resetCache.html +https://cbib.github.io/Seurat-Integrate/reference/saveToCache.html +https://cbib.github.io/Seurat-Integrate/reference/scANVIIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/scVIIntegration.html +https://cbib.github.io/Seurat-Integrate/reference/score-ari.html +https://cbib.github.io/Seurat-Integrate/reference/score-asw.html +https://cbib.github.io/Seurat-Integrate/reference/score-cc.html +https://cbib.github.io/Seurat-Integrate/reference/score-connectivity.html +https://cbib.github.io/Seurat-Integrate/reference/score-densityPC.html +https://cbib.github.io/Seurat-Integrate/reference/score-kbet.html +https://cbib.github.io/Seurat-Integrate/reference/score-lisi.html +https://cbib.github.io/Seurat-Integrate/reference/score-nmi.html +https://cbib.github.io/Seurat-Integrate/reference/score-regressPC.html +https://cbib.github.io/Seurat-Integrate/reference/trVAEIntegration.html + + diff --git a/web-app-manifest-192x192.png b/web-app-manifest-192x192.png new file mode 100644 index 0000000..9f4a3a5 Binary files /dev/null and b/web-app-manifest-192x192.png differ diff --git a/web-app-manifest-512x512.png b/web-app-manifest-512x512.png new file mode 100644 index 0000000..9523212 Binary files /dev/null and b/web-app-manifest-512x512.png differ